// This file is generated by Parser_h.template.

// Copyright 2019 The Chromium 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 {{"_".join(config.protocol.namespace)}}_BASE_STRING_ADAPTER_H
#define {{"_".join(config.protocol.namespace)}}_BASE_STRING_ADAPTER_H

#include <memory>
#include <string>
#include <vector>

#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_number_conversions.h"
{% if config.lib.export_header %}
#include "{{config.lib.export_header}}"
{% endif %}

namespace base {
class Value;
}

{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}

class Value;

using String = std::string;
using ProtocolMessage = std::string;

class {{config.lib.export_macro}} StringBuilder {
 public:
  StringBuilder();
  ~StringBuilder();
  void append(const String&);
  void append(char);
  void append(const char*, size_t);
  String toString();
  void reserveCapacity(size_t);

 private:
  std::string string_;
};

class {{config.lib.export_macro}} StringUtil {
 public:
  static String substring(const String& s, unsigned pos, unsigned len) {
    return s.substr(pos, len);
  }
  static String fromInteger(int number) { return base::NumberToString(number); }
  static String fromDouble(double number) {
    String s = base::NumberToString(number);
    if (!s.empty()) {  // .123 -> 0.123; -.123 -> -0.123 for valid JSON.
      if (s[0] == '.')
        s.insert(/*index=*/ 0, /*count=*/ 1, /*ch=*/ '0');
      else if (s[0] == '-' && s.size() >= 2 && s[1] == '.')
        s.insert(/*index=*/ 1, /*count=*/ 1, /*ch=*/ '0');
    }
    return s;
  }
  static double toDouble(const char* s, size_t len, bool* ok) {
    double v = 0.0;
    *ok = base::StringToDouble(std::string(s, len), &v);
    return *ok ? v : 0.0;
  }
  static size_t find(const String& s, const char* needle) {
    return s.find(needle);
  }
  static size_t find(const String& s, const String& needle) {
    return s.find(needle);
  }
  static const size_t kNotFound = static_cast<size_t>(-1);
  static void builderAppend(StringBuilder& builder, const String& s) {
    builder.append(s);
  }
  static void builderAppend(StringBuilder& builder, char c) {
    builder.append(c);
  }
  static void builderAppend(StringBuilder& builder, const char* s, size_t len) {
    builder.append(s, len);
  }
  static void builderAppendQuotedString(StringBuilder& builder,
                                        const String& str);
  static void builderReserve(StringBuilder& builder, unsigned capacity) {
    builder.reserveCapacity(capacity);
  }
  static String builderToString(StringBuilder& builder) {
    return builder.toString();
  }

  static std::unique_ptr<Value> parseMessage(const std::string& message, bool binary);
  static ProtocolMessage jsonToMessage(String message);
  static ProtocolMessage binaryToMessage(std::vector<uint8_t> message);

  static String fromUTF8(const uint8_t* data, size_t length) {
    return std::string(reinterpret_cast<const char*>(data), length);
  }

  static String fromUTF16(const uint16_t* data, size_t length);

  static const uint8_t* CharactersLatin1(const String& s) { return nullptr; }
  static const uint8_t* CharactersUTF8(const String& s) {
    return reinterpret_cast<const uint8_t*>(s.data());
  }
  static const uint16_t* CharactersUTF16(const String& s) { return nullptr; }
  static size_t CharacterCount(const String& s) { return s.size(); }
};

// A read-only sequence of uninterpreted bytes with reference-counted storage.
class {{config.lib.export_macro}} Binary {
 public:
  Binary(const Binary&);
  Binary();
  ~Binary();

  const uint8_t* data() const { return bytes_->front(); }
  size_t size() const { return bytes_->size(); }
  scoped_refptr<base::RefCountedMemory> bytes() const { return bytes_; }

  String toBase64() const;

  static Binary fromBase64(const String& base64, bool* success);
  static Binary fromRefCounted(scoped_refptr<base::RefCountedMemory> memory);
  static Binary fromVector(std::vector<uint8_t> data);
  static Binary fromString(std::string data);
  static Binary fromSpan(const uint8_t* data, size_t size);

 private:
  explicit Binary(scoped_refptr<base::RefCountedMemory> bytes);
  scoped_refptr<base::RefCountedMemory> bytes_;
};

std::unique_ptr<Value> toProtocolValue(const base::Value* value, int depth);
std::unique_ptr<base::Value> toBaseValue(Value* value, int depth);

bool AppendStringValueToMapBinary(base::StringPiece in,
    base::StringPiece key, base::StringPiece value, std::string* out);
bool AppendStringValueToMapJSON(base::StringPiece in,
    base::StringPiece key, base::StringPiece value, std::string* out);

{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}

#endif // !defined({{"_".join(config.protocol.namespace)}}_BASE_STRING_ADAPTER_H)
