// 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.

#include "src/strings/string-stream.h"

#include <memory>

#include "src/handles/handles-inl.h"
#include "src/logging/log.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/prototype.h"
#include "src/utils/vector.h"

namespace v8 {
namespace internal {

static const int kMentionedObjectCacheMaxSize = 256;

char* HeapStringAllocator::allocate(unsigned bytes) {
  space_ = NewArray<char>(bytes);
  return space_;
}

char* FixedStringAllocator::allocate(unsigned bytes) {
  CHECK_LE(bytes, length_);
  return buffer_;
}

char* FixedStringAllocator::grow(unsigned* old) {
  *old = length_;
  return buffer_;
}

bool StringStream::Put(char c) {
  if (full()) return false;
  DCHECK(length_ < capacity_);
  // Since the trailing '\0' is not accounted for in length_ fullness is
  // indicated by a difference of 1 between length_ and capacity_. Thus when
  // reaching a difference of 2 we need to grow the buffer.
  if (length_ == capacity_ - 2) {
    unsigned new_capacity = capacity_;
    char* new_buffer = allocator_->grow(&new_capacity);
    if (new_capacity > capacity_) {
      capacity_ = new_capacity;
      buffer_ = new_buffer;
    } else {
      // Reached the end of the available buffer.
      DCHECK_GE(capacity_, 5);
      length_ = capacity_ - 1;  // Indicate fullness of the stream.
      buffer_[length_ - 4] = '.';
      buffer_[length_ - 3] = '.';
      buffer_[length_ - 2] = '.';
      buffer_[length_ - 1] = '\n';
      buffer_[length_] = '\0';
      return false;
    }
  }
  buffer_[length_] = c;
  buffer_[length_ + 1] = '\0';
  length_++;
  return true;
}

// A control character is one that configures a format element.  For
// instance, in %.5s, .5 are control characters.
static bool IsControlChar(char c) {
  switch (c) {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
    case '.':
    case '-':
      return true;
    default:
      return false;
  }
}

void StringStream::Add(Vector<const char> format, Vector<FmtElm> elms) {
  // If we already ran out of space then return immediately.
  if (full()) return;
  int offset = 0;
  int elm = 0;
  while (offset < format.length()) {
    if (format[offset] != '%' || elm == elms.length()) {
      Put(format[offset]);
      offset++;
      continue;
    }
    // Read this formatting directive into a temporary buffer
    EmbeddedVector<char, 24> temp;
    int format_length = 0;
    // Skip over the whole control character sequence until the
    // format element type
    temp[format_length++] = format[offset++];
    while (offset < format.length() && IsControlChar(format[offset]))
      temp[format_length++] = format[offset++];
    if (offset >= format.length()) return;
    char type = format[offset];
    temp[format_length++] = type;
    temp[format_length] = '\0';
    offset++;
    FmtElm current = elms[elm++];
    switch (type) {
      case 's': {
        DCHECK_EQ(FmtElm::C_STR, current.type_);
        const char* value = current.data_.u_c_str_;
        Add(value);
        break;
      }
      case 'w': {
        DCHECK_EQ(FmtElm::LC_STR, current.type_);
        Vector<const uc16> value = *current.data_.u_lc_str_;
        for (int i = 0; i < value.length(); i++)
          Put(static_cast<char>(value[i]));
        break;
      }
      case 'o': {
        DCHECK_EQ(FmtElm::OBJ, current.type_);
        Object obj(current.data_.u_obj_);
        PrintObject(obj);
        break;
      }
      case 'k': {
        DCHECK_EQ(FmtElm::INT, current.type_);
        int value = current.data_.u_int_;
        if (0x20 <= value && value <= 0x7F) {
          Put(value);
        } else if (value <= 0xFF) {
          Add("\\x%02x", value);
        } else {
          Add("\\u%04x", value);
        }
        break;
      }
      case 'i':
      case 'd':
      case 'u':
      case 'x':
      case 'c':
      case 'X': {
        int value = current.data_.u_int_;
        EmbeddedVector<char, 24> formatted;
        int length = SNPrintF(formatted, temp.begin(), value);
        Add(Vector<const char>(formatted.begin(), length));
        break;
      }
      case 'f':
      case 'g':
      case 'G':
      case 'e':
      case 'E': {
        double value = current.data_.u_double_;
        int inf = std::isinf(value);
        if (inf == -1) {
          Add("-inf");
        } else if (inf == 1) {
          Add("inf");
        } else if (std::isnan(value)) {
          Add("nan");
        } else {
          EmbeddedVector<char, 28> formatted;
          SNPrintF(formatted, temp.begin(), value);
          Add(formatted.begin());
        }
        break;
      }
      case 'p': {
        void* value = current.data_.u_pointer_;
        EmbeddedVector<char, 20> formatted;
        SNPrintF(formatted, temp.begin(), value);
        Add(formatted.begin());
        break;
      }
      default:
        UNREACHABLE();
    }
  }

  // Verify that the buffer is 0-terminated
  DCHECK_EQ(buffer_[length_], '\0');
}

void StringStream::PrintObject(Object o) {
  o.ShortPrint(this);
  if (o.IsString()) {
    if (String::cast(o).length() <= String::kMaxShortPrintLength) {
      return;
    }
  } else if (o.IsNumber() || o.IsOddball()) {
    return;
  }
  if (o.IsHeapObject() && object_print_mode_ == kPrintObjectVerbose) {
    // TODO(delphick): Consider whether we can get the isolate without using
    // TLS.
    Isolate* isolate = Isolate::Current();
    DebugObjectCache* debug_object_cache =
        isolate->string_stream_debug_object_cache();
    for (size_t i = 0; i < debug_object_cache->size(); i++) {
      if (*(*debug_object_cache)[i] == o) {
        Add("#%d#", static_cast<int>(i));
        return;
      }
    }
    if (debug_object_cache->size() < kMentionedObjectCacheMaxSize) {
      Add("#%d#", static_cast<int>(debug_object_cache->size()));
      debug_object_cache->push_back(handle(HeapObject::cast(o), isolate));
    } else {
      Add("@%p", o);
    }
  }
}

std::unique_ptr<char[]> StringStream::ToCString() const {
  char* str = NewArray<char>(length_ + 1);
  MemCopy(str, buffer_, length_);
  str[length_] = '\0';
  return std::unique_ptr<char[]>(str);
}

void StringStream::Log(Isolate* isolate) {
  LOG(isolate, StringEvent("StackDump", buffer_));
}

void StringStream::OutputToFile(FILE* out) {
  // Dump the output to stdout, but make sure to break it up into
  // manageable chunks to avoid losing parts of the output in the OS
  // printing code. This is a problem on Windows in particular; see
  // the VPrint() function implementations in platform-win32.cc.
  unsigned position = 0;
  for (unsigned next; (next = position + 2048) < length_; position = next) {
    char save = buffer_[next];
    buffer_[next] = '\0';
    internal::PrintF(out, "%s", &buffer_[position]);
    buffer_[next] = save;
  }
  internal::PrintF(out, "%s", &buffer_[position]);
}

Handle<String> StringStream::ToString(Isolate* isolate) {
  return isolate->factory()
      ->NewStringFromUtf8(Vector<const char>(buffer_, length_))
      .ToHandleChecked();
}

void StringStream::ClearMentionedObjectCache(Isolate* isolate) {
  isolate->set_string_stream_current_security_token(Object());
  if (isolate->string_stream_debug_object_cache() == nullptr) {
    isolate->set_string_stream_debug_object_cache(new DebugObjectCache());
  }
  isolate->string_stream_debug_object_cache()->clear();
}

#ifdef DEBUG
bool StringStream::IsMentionedObjectCacheClear(Isolate* isolate) {
  return object_print_mode_ == kPrintObjectConcise ||
         isolate->string_stream_debug_object_cache()->size() == 0;
}
#endif

bool StringStream::Put(String str) { return Put(str, 0, str.length()); }

bool StringStream::Put(String str, int start, int end) {
  StringCharacterStream stream(str, start);
  for (int i = start; i < end && stream.HasMore(); i++) {
    uint16_t c = stream.GetNext();
    if (c >= 127 || c < 32) {
      c = '?';
    }
    if (!Put(static_cast<char>(c))) {
      return false;  // Output was truncated.
    }
  }
  return true;
}

void StringStream::PrintName(Object name) {
  if (name.IsString()) {
    String str = String::cast(name);
    if (str.length() > 0) {
      Put(str);
    } else {
      Add("/* anonymous */");
    }
  } else {
    Add("%o", name);
  }
}

void StringStream::PrintUsingMap(JSObject js_object) {
  Map map = js_object.map();
  int real_size = map.NumberOfOwnDescriptors();
  DescriptorArray descs = map.instance_descriptors();
  for (int i = 0; i < real_size; i++) {
    PropertyDetails details = descs.GetDetails(i);
    if (details.location() == kField) {
      DCHECK_EQ(kData, details.kind());
      Object key = descs.GetKey(i);
      if (key.IsString() || key.IsNumber()) {
        int len = 3;
        if (key.IsString()) {
          len = String::cast(key).length();
        }
        for (; len < 18; len++) Put(' ');
        if (key.IsString()) {
          Put(String::cast(key));
        } else {
          key.ShortPrint();
        }
        Add(": ");
        FieldIndex index = FieldIndex::ForDescriptor(map, i);
        if (js_object.IsUnboxedDoubleField(index)) {
          double value = js_object.RawFastDoublePropertyAt(index);
          Add("<unboxed double> %.16g\n", FmtElm(value));
        } else {
          Object value = js_object.RawFastPropertyAt(index);
          Add("%o\n", value);
        }
      }
    }
  }
}

void StringStream::PrintFixedArray(FixedArray array, unsigned int limit) {
  ReadOnlyRoots roots = array.GetReadOnlyRoots();
  for (unsigned int i = 0; i < 10 && i < limit; i++) {
    Object element = array.get(i);
    if (element.IsTheHole(roots)) continue;
    for (int len = 1; len < 18; len++) {
      Put(' ');
    }
    Add("%d: %o\n", i, array.get(i));
  }
  if (limit >= 10) {
    Add("                  ...\n");
  }
}

void StringStream::PrintByteArray(ByteArray byte_array) {
  unsigned int limit = byte_array.length();
  for (unsigned int i = 0; i < 10 && i < limit; i++) {
    byte b = byte_array.get(i);
    Add("             %d: %3d 0x%02x", i, b, b);
    if (b >= ' ' && b <= '~') {
      Add(" '%c'", b);
    } else if (b == '\n') {
      Add(" '\n'");
    } else if (b == '\r') {
      Add(" '\r'");
    } else if (b >= 1 && b <= 26) {
      Add(" ^%c", b + 'A' - 1);
    }
    Add("\n");
  }
  if (limit >= 10) {
    Add("                  ...\n");
  }
}

void StringStream::PrintMentionedObjectCache(Isolate* isolate) {
  if (object_print_mode_ == kPrintObjectConcise) return;
  DebugObjectCache* debug_object_cache =
      isolate->string_stream_debug_object_cache();
  Add("==== Key         ============================================\n\n");
  for (size_t i = 0; i < debug_object_cache->size(); i++) {
    HeapObject printee = *(*debug_object_cache)[i];
    Add(" #%d# %p: ", static_cast<int>(i),
        reinterpret_cast<void*>(printee.ptr()));
    printee.ShortPrint(this);
    Add("\n");
    if (printee.IsJSObject()) {
      if (printee.IsJSPrimitiveWrapper()) {
        Add("           value(): %o\n",
            JSPrimitiveWrapper::cast(printee).value());
      }
      PrintUsingMap(JSObject::cast(printee));
      if (printee.IsJSArray()) {
        JSArray array = JSArray::cast(printee);
        if (array.HasObjectElements()) {
          unsigned int limit = FixedArray::cast(array.elements()).length();
          unsigned int length =
              static_cast<uint32_t>(JSArray::cast(array).length().Number());
          if (length < limit) limit = length;
          PrintFixedArray(FixedArray::cast(array.elements()), limit);
        }
      }
    } else if (printee.IsByteArray()) {
      PrintByteArray(ByteArray::cast(printee));
    } else if (printee.IsFixedArray()) {
      unsigned int limit = FixedArray::cast(printee).length();
      PrintFixedArray(FixedArray::cast(printee), limit);
    }
  }
}

void StringStream::PrintSecurityTokenIfChanged(JSFunction fun) {
  Object token = fun.native_context().security_token();
  Isolate* isolate = fun.GetIsolate();
  if (token != isolate->string_stream_current_security_token()) {
    Add("Security context: %o\n", token);
    isolate->set_string_stream_current_security_token(token);
  }
}

void StringStream::PrintFunction(JSFunction fun, Object receiver, Code* code) {
  PrintPrototype(fun, receiver);
  *code = fun.code();
}

void StringStream::PrintPrototype(JSFunction fun, Object receiver) {
  Object name = fun.shared().Name();
  bool print_name = false;
  Isolate* isolate = fun.GetIsolate();
  if (receiver.IsNullOrUndefined(isolate) || receiver.IsTheHole(isolate) ||
      receiver.IsJSProxy()) {
    print_name = true;
  } else if (!isolate->context().is_null()) {
    if (!receiver.IsJSObject()) {
      receiver = receiver.GetPrototypeChainRootMap(isolate).prototype();
    }

    for (PrototypeIterator iter(isolate, JSObject::cast(receiver),
                                kStartAtReceiver);
         !iter.IsAtEnd(); iter.Advance()) {
      if (iter.GetCurrent().IsJSProxy()) break;
      Object key = iter.GetCurrent<JSObject>().SlowReverseLookup(fun);
      if (!key.IsUndefined(isolate)) {
        if (!name.IsString() || !key.IsString() ||
            !String::cast(name).Equals(String::cast(key))) {
          print_name = true;
        }
        if (name.IsString() && String::cast(name).length() == 0) {
          print_name = false;
        }
        name = key;
        break;
      }
    }
  }
  PrintName(name);
  // Also known as - if the name in the function doesn't match the name under
  // which it was looked up.
  if (print_name) {
    Add("(aka ");
    PrintName(fun.shared().Name());
    Put(')');
  }
}

char* HeapStringAllocator::grow(unsigned* bytes) {
  unsigned new_bytes = *bytes * 2;
  // Check for overflow.
  if (new_bytes <= *bytes) {
    return space_;
  }
  char* new_space = NewArray<char>(new_bytes);
  if (new_space == nullptr) {
    return space_;
  }
  MemCopy(new_space, space_, *bytes);
  *bytes = new_bytes;
  DeleteArray(space_);
  space_ = new_space;
  return new_space;
}

}  // namespace internal
}  // namespace v8
