// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_STRING_STREAM_H_
#define V8_STRING_STREAM_H_

#include "src/allocation.h"
#include "src/base/small-vector.h"
#include "src/handles.h"
#include "src/objects/heap-object.h"
#include "src/vector.h"

namespace v8 {
namespace internal {

// Forward declarations.
class ByteArray;

class StringAllocator {
 public:
  virtual ~StringAllocator() = default;
  // Allocate a number of bytes.
  virtual char* allocate(unsigned bytes) = 0;
  // Allocate a larger number of bytes and copy the old buffer to the new one.
  // bytes is an input and output parameter passing the old size of the buffer
  // and returning the new size.  If allocation fails then we return the old
  // buffer and do not increase the size.
  virtual char* grow(unsigned* bytes) = 0;
};


// Normal allocator uses new[] and delete[].
class HeapStringAllocator final : public StringAllocator {
 public:
  ~HeapStringAllocator() override { DeleteArray(space_); }
  char* allocate(unsigned bytes) override;
  char* grow(unsigned* bytes) override;

 private:
  char* space_;
};


class FixedStringAllocator final : public StringAllocator {
 public:
  FixedStringAllocator(char* buffer, unsigned length)
      : buffer_(buffer), length_(length) {}
  ~FixedStringAllocator() override = default;

  char* allocate(unsigned bytes) override;
  char* grow(unsigned* bytes) override;

 private:
  char* buffer_;
  unsigned length_;
  DISALLOW_COPY_AND_ASSIGN(FixedStringAllocator);
};

template <std::size_t kInlineSize>
class SmallStringOptimizedAllocator final : public StringAllocator {
 public:
  typedef base::SmallVector<char, kInlineSize> SmallVector;

  explicit SmallStringOptimizedAllocator(SmallVector* vector) V8_NOEXCEPT
      : vector_(vector) {}

  char* allocate(unsigned bytes) override {
    vector_->resize_no_init(bytes);
    return vector_->data();
  }

  char* grow(unsigned* bytes) override {
    unsigned new_bytes = *bytes * 2;
    // Check for overflow.
    if (new_bytes <= *bytes) {
      return vector_->data();
    }
    vector_->resize_no_init(new_bytes);
    *bytes = new_bytes;
    return vector_->data();
  }

 private:
  SmallVector* vector_;
};

class StringStream final {
  class FmtElm final {
   public:
    FmtElm(int value) : FmtElm(INT) {  // NOLINT
      data_.u_int_ = value;
    }
    explicit FmtElm(double value) : FmtElm(DOUBLE) {  // NOLINT
      data_.u_double_ = value;
    }
    FmtElm(const char* value) : FmtElm(C_STR) {  // NOLINT
      data_.u_c_str_ = value;
    }
    FmtElm(const Vector<const uc16>& value) : FmtElm(LC_STR) {  // NOLINT
      data_.u_lc_str_ = &value;
    }
    FmtElm(Object value) : FmtElm(OBJ) {  // NOLINT
      data_.u_obj_ = value.ptr();
    }
    FmtElm(Handle<Object> value) : FmtElm(HANDLE) {  // NOLINT
      data_.u_handle_ = value.location();
    }
    FmtElm(void* value) : FmtElm(POINTER) {  // NOLINT
      data_.u_pointer_ = value;
    }

   private:
    friend class StringStream;
    enum Type { INT, DOUBLE, C_STR, LC_STR, OBJ, HANDLE, POINTER };

#ifdef DEBUG
    Type type_;
    explicit FmtElm(Type type) : type_(type) {}
#else
    explicit FmtElm(Type) {}
#endif

    union {
      int u_int_;
      double u_double_;
      const char* u_c_str_;
      const Vector<const uc16>* u_lc_str_;
      Address u_obj_;
      Address* u_handle_;
      void* u_pointer_;
    } data_;
  };

 public:
  enum ObjectPrintMode { kPrintObjectConcise, kPrintObjectVerbose };
  explicit StringStream(StringAllocator* allocator,
                        ObjectPrintMode object_print_mode = kPrintObjectVerbose)
      : allocator_(allocator),
        object_print_mode_(object_print_mode),
        capacity_(kInitialCapacity),
        length_(0),
        buffer_(allocator_->allocate(kInitialCapacity)) {
    buffer_[0] = 0;
  }

  bool Put(char c);
  bool Put(String str);
  bool Put(String str, int start, int end);
  void Add(const char* format) { Add(CStrVector(format)); }
  void Add(Vector<const char> format) { Add(format, Vector<FmtElm>()); }

  template <typename... Args>
  void Add(const char* format, Args... args) {
    Add(CStrVector(format), args...);
  }

  template <typename... Args>
  void Add(Vector<const char> format, Args... args) {
    FmtElm elems[]{args...};
    Add(format, ArrayVector(elems));
  }

  // Getting the message out.
  void OutputToFile(FILE* out);
  void OutputToStdOut() { OutputToFile(stdout); }
  void Log(Isolate* isolate);
  Handle<String> ToString(Isolate* isolate);
  std::unique_ptr<char[]> ToCString() const;
  int length() const { return length_; }

  // Object printing support.
  void PrintName(Object o);
  void PrintFixedArray(FixedArray array, unsigned int limit);
  void PrintByteArray(ByteArray ba);
  void PrintUsingMap(JSObject js_object);
  void PrintPrototype(JSFunction fun, Object receiver);
  void PrintSecurityTokenIfChanged(JSFunction function);
  // NOTE: Returns the code in the output parameter.
  void PrintFunction(JSFunction function, Object receiver, Code* code);

  // Reset the stream.
  void Reset() {
    length_ = 0;
    buffer_[0] = 0;
  }

  // Mentioned object cache support.
  void PrintMentionedObjectCache(Isolate* isolate);
  V8_EXPORT_PRIVATE static void ClearMentionedObjectCache(Isolate* isolate);
#ifdef DEBUG
  bool IsMentionedObjectCacheClear(Isolate* isolate);
#endif

  static const int kInitialCapacity = 16;

 private:
  void Add(Vector<const char> format, Vector<FmtElm> elms);
  void PrintObject(Object obj);

  StringAllocator* allocator_;
  ObjectPrintMode object_print_mode_;
  unsigned capacity_;
  unsigned length_;  // does not include terminating 0-character
  char* buffer_;

  bool full() const { return (capacity_ - length_) == 1; }
  int space() const { return capacity_ - length_; }

  DISALLOW_IMPLICIT_CONSTRUCTORS(StringStream);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_STRING_STREAM_H_
