text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <google/protobuf/util/internal/json_escaping.h>

#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>

namespace google {
namespace protobuf {
namespace util {
namespace converter {

namespace {

// Array of hex characters for conversion to hex.
static const char kHex[] = "0123456789abcdef";

// Characters 0x00 to 0x9f are very commonly used, so we provide a special
// table lookup.
//
// For unicode code point ch < 0xa0:
// kCommonEscapes[ch] is the escaped string of ch, if escaping is needed;
//                    or an empty string, if escaping is not needed.
static const char kCommonEscapes[160][7] = {
  // C0 (ASCII and derivatives) control characters
  "\\u0000", "\\u0001", "\\u0002", "\\u0003",  // 0x00
  "\\u0004", "\\u0005", "\\u0006", "\\u0007",
  "\\b",     "\\t",     "\\n",     "\\u000b",
  "\\f",     "\\r",     "\\u000e", "\\u000f",
  "\\u0010", "\\u0011", "\\u0012", "\\u0013",  // 0x10
  "\\u0014", "\\u0015", "\\u0016", "\\u0017",
  "\\u0018", "\\u0019", "\\u001a", "\\u001b",
  "\\u001c", "\\u001d", "\\u001e", "\\u001f",
  // Escaping of " and \ are required by www.json.org string definition.
  // Escaping of < and > are required for HTML security.
  "", "", "\\\"", "", "",        "", "",        "",  // 0x20
  "", "", "",     "", "",        "", "",        "",
  "", "", "",     "", "",        "", "",        "",  // 0x30
  "", "", "",     "", "\\u003c", "", "\\u003e", "",
  "", "", "",     "", "",        "", "",        "",  // 0x40
  "", "", "",     "", "",        "", "",        "",
  "", "", "",     "", "",        "", "",        "",  // 0x50
  "", "", "",     "", "\\\\",    "", "",        "",
  "", "", "",     "", "",        "", "",        "",  // 0x60
  "", "", "",     "", "",        "", "",        "",
  "", "", "",     "", "",        "", "",        "",  // 0x70
  "", "", "",     "", "",        "", "",        "\\u007f",
  // C1 (ISO 8859 and Unicode) extended control characters
  "\\u0080", "\\u0081", "\\u0082", "\\u0083",  // 0x80
  "\\u0084", "\\u0085", "\\u0086", "\\u0087",
  "\\u0088", "\\u0089", "\\u008a", "\\u008b",
  "\\u008c", "\\u008d", "\\u008e", "\\u008f",
  "\\u0090", "\\u0091", "\\u0092", "\\u0093",  // 0x90
  "\\u0094", "\\u0095", "\\u0096", "\\u0097",
  "\\u0098", "\\u0099", "\\u009a", "\\u009b",
  "\\u009c", "\\u009d", "\\u009e", "\\u009f"
};

// Determines if the given char value is a unicode surrogate code unit (either
// high-surrogate or low-surrogate).
inline bool IsSurrogate(uint32 c) {
  // Optimized form of:
  // return c >= kMinHighSurrogate && c <= kMaxLowSurrogate;
  // (Reduced from 3 ALU instructions to 2 ALU instructions)
  return (c & 0xfffff800) == JsonEscaping::kMinHighSurrogate;
}

// Returns true if the given unicode code point cp is a valid
// unicode code point (i.e. in the range 0 <= cp <= kMaxCodePoint).
inline bool IsValidCodePoint(uint32 cp) {
  return cp <= JsonEscaping::kMaxCodePoint;
}

// Returns the low surrogate for the given unicode code point. The result is
// meaningless if the given code point is not a supplementary character.
inline uint16 ToLowSurrogate(uint32 cp) {
  return (cp & (JsonEscaping::kMaxLowSurrogate
                - JsonEscaping::kMinLowSurrogate))
      + JsonEscaping::kMinLowSurrogate;
}

// Returns the high surrogate for the given unicode code point. The result is
// meaningless if the given code point is not a supplementary character.
inline uint16 ToHighSurrogate(uint32 cp) {
  return (cp >> 10) + (JsonEscaping::kMinHighSurrogate -
                       (JsonEscaping::kMinSupplementaryCodePoint >> 10));
}

// Input str is encoded in UTF-8. A unicode code point could be encoded in
// UTF-8 using anywhere from 1 to 4 characters, and it could span multiple
// reads of the ByteSource.
//
// This function reads the next unicode code point from the input (str) at
// the given position (index), taking into account any left-over partial
// code point from the previous iteration (cp), together with the number
// of characters left to read to complete this code point (num_left).
//
// This function assumes that the input (str) is valid at the given position
// (index). In order words, at least one character could be read successfully.
//
// The code point read (partial or complete) is stored in (cp). Upon return,
// (num_left) stores the number of characters that has yet to be read in
// order to complete the current unicode code point. If the read is complete,
// then (num_left) is 0. Also, (num_read) is the number of characters read.
//
// Returns false if we encounter an invalid UTF-8 string. Returns true
// otherwise, including the case when we reach the end of the input (str)
// before a complete unicode code point is read.
bool ReadCodePoint(StringPiece str, int index,
                   uint32 *cp, int* num_left, int *num_read) {
  if (*num_left == 0) {
    // Last read was complete. Start reading a new unicode code point.
    *cp = static_cast<uint8>(str[index++]);
    *num_read = 1;
    // The length of the code point is determined from reading the first byte.
    //
    // If the first byte is between:
    //    0..0x7f: that's the value of the code point.
    // 0x80..0xbf: <invalid>
    // 0xc0..0xdf: 11-bit code point encoded in 2 bytes.
    //                                   bit 10-6, bit 5-0
    // 0xe0..0xef: 16-bit code point encoded in 3 bytes.
    //                        bit 15-12, bit 11-6, bit 5-0
    // 0xf0..0xf7: 21-bit code point encoded in 4 bytes.
    //             bit 20-18, bit 17-12, bit 11-6, bit 5-0
    // 0xf8..0xff: <invalid>
    //
    // Meaning of each bit:
    // <msb> bit 7: 0 - single byte code point: bits 6-0 are values.
    //              1 - multibyte code point
    //       bit 6: 0 - subsequent bytes of multibyte code point:
    //                  bits 5-0 are values.
    //              1 - first byte of multibyte code point
    //       bit 5: 0 - first byte of 2-byte code point: bits 4-0 are values.
    //              1 - first byte of code point with >= 3 bytes.
    //       bit 4: 0 - first byte of 3-byte code point: bits 3-0 are values.
    //              1 - first byte of code point with >= 4 bytes.
    //       bit 3: 0 - first byte of 4-byte code point: bits 2-0 are values.
    //              1 - reserved for future expansion.
    if (*cp <= 0x7f) {
      return true;
    } else if (*cp <= 0xbf) {
      return false;
    } else if (*cp <= 0xdf) {
      *cp &= 0x1f;
      *num_left = 1;
    } else if (*cp <= 0xef) {
      *cp &= 0x0f;
      *num_left = 2;
    } else if (*cp <= 0xf7) {
      *cp &= 0x07;
      *num_left = 3;
    } else {
      return false;
    }
  } else {
    // Last read was partial. Initialize num_read to 0 and continue reading
    // the last unicode code point.
    *num_read = 0;
  }
  while (*num_left > 0 && index < str.size()) {
    uint32 ch = static_cast<uint8>(str[index++]);
    --(*num_left);
    ++(*num_read);
    *cp = (*cp << 6) | (ch & 0x3f);
    if (ch < 0x80 || ch > 0xbf) return false;
  }
  return *num_left > 0 || (!IsSurrogate(*cp) && IsValidCodePoint(*cp));
}

// Stores the 16-bit unicode code point as its hexadecimal digits in buffer
// and returns a StringPiece that points to this buffer. The input buffer needs
// to be at least 6 bytes long.
StringPiece ToHex(uint16 cp, char* buffer) {
  buffer[5] = kHex[cp & 0x0f];
  cp >>= 4;
  buffer[4] = kHex[cp & 0x0f];
  cp >>= 4;
  buffer[3] = kHex[cp & 0x0f];
  cp >>= 4;
  buffer[2] = kHex[cp & 0x0f];
  return StringPiece(buffer, 6);
}

// Stores the 32-bit unicode code point as its hexadecimal digits in buffer
// and returns a StringPiece that points to this buffer. The input buffer needs
// to be at least 12 bytes long.
StringPiece ToSurrogateHex(uint32 cp, char* buffer) {
  uint16 low = ToLowSurrogate(cp);
  uint16 high = ToHighSurrogate(cp);

  buffer[11] = kHex[low & 0x0f];
  low >>= 4;
  buffer[10] = kHex[low & 0x0f];
  low >>= 4;
  buffer[9] = kHex[low & 0x0f];
  low >>= 4;
  buffer[8] = kHex[low & 0x0f];

  buffer[5] = kHex[high & 0x0f];
  high >>= 4;
  buffer[4] = kHex[high & 0x0f];
  high >>= 4;
  buffer[3] = kHex[high & 0x0f];
  high >>= 4;
  buffer[2] = kHex[high & 0x0f];

  return StringPiece(buffer, 12);
}

// If the given unicode code point needs escaping, then returns the
// escaped form. The returned StringPiece either points to statically
// pre-allocated char[] or to the given buffer. The input buffer needs
// to be at least 12 bytes long.
//
// If the given unicode code point does not need escaping, an empty
// StringPiece is returned.
StringPiece EscapeCodePoint(uint32 cp, char* buffer) {
  if (cp < 0xa0) return kCommonEscapes[cp];
  switch (cp) {
    // These are not required by json spec
    // but used to prevent security bugs in javascript.
    case 0xfeff:  // Zero width no-break space
    case 0xfff9:  // Interlinear annotation anchor
    case 0xfffa:  // Interlinear annotation separator
    case 0xfffb:  // Interlinear annotation terminator

    case 0x00ad:  // Soft-hyphen
    case 0x06dd:  // Arabic end of ayah
    case 0x070f:  // Syriac abbreviation mark
    case 0x17b4:  // Khmer vowel inherent Aq
    case 0x17b5:  // Khmer vowel inherent Aa
      return ToHex(cp, buffer);

    default:
      if ((cp >= 0x0600 && cp <= 0x0603) ||  // Arabic signs
          (cp >= 0x200b && cp <= 0x200f) ||  // Zero width etc.
          (cp >= 0x2028 && cp <= 0x202e) ||  // Separators etc.
          (cp >= 0x2060 && cp <= 0x2064) ||  // Invisible etc.
          (cp >= 0x206a && cp <= 0x206f)) {  // Shaping etc.
        return ToHex(cp, buffer);
      }

      if (cp == 0x000e0001 ||                        // Language tag
          (cp >= 0x0001d173 && cp <= 0x0001d17a) ||  // Music formatting
          (cp >= 0x000e0020 && cp <= 0x000e007f)) {  // TAG symbols
        return ToSurrogateHex(cp, buffer);
      }
  }
  return StringPiece();
}

// Tries to escape the given code point first. If the given code point
// does not need to be escaped, but force_output is true, then render
// the given multi-byte code point in UTF8 in the buffer and returns it.
StringPiece EscapeCodePoint(uint32 cp, char* buffer, bool force_output) {
  StringPiece sp = EscapeCodePoint(cp, buffer);
  if (force_output && sp.empty()) {
    buffer[5] = (cp & 0x3f) | 0x80;
    cp >>= 6;
    if (cp <= 0x1f) {
      buffer[4] = cp | 0xc0;
      sp = StringPiece(buffer + 4, 2);
      return sp;
    }
    buffer[4] = (cp & 0x3f) | 0x80;
    cp >>= 6;
    if (cp <= 0x0f) {
      buffer[3] = cp | 0xe0;
      sp = StringPiece(buffer + 3, 3);
      return sp;
    }
    buffer[3] = (cp & 0x3f) | 0x80;
    buffer[2] = ((cp >> 6) & 0x07) | 0xf0;
    sp = StringPiece(buffer + 2, 4);
  }
  return sp;
}

}  // namespace

void JsonEscaping::Escape(strings::ByteSource* input,
                          strings::ByteSink* output) {
  char buffer[12] = "\\udead\\ubee";
  uint32 cp = 0;     // Current unicode code point.
  int num_left = 0;  // Num of chars to read to complete the code point.
  while (input->Available() > 0) {
    StringPiece str = input->Peek();
    StringPiece escaped;
    int i = 0;
    int num_read;
    bool ok;
    bool cp_was_split = num_left > 0;
    // Loop until we encounter either
    //   i) a code point that needs to be escaped; or
    //  ii) a split code point is completely read; or
    // iii) a character that is not a valid utf8; or
    //  iv) end of the StringPiece str is reached.
    do {
      ok = ReadCodePoint(str, i, &cp, &num_left, &num_read);
      if (num_left > 0 || !ok) break;  // case iii or iv
      escaped = EscapeCodePoint(cp, buffer, cp_was_split);
      if (!escaped.empty()) break;     // case i or ii
      i += num_read;
      num_read = 0;
    } while (i < str.length());        // case iv
    // First copy the un-escaped prefix, if any, to the output ByteSink.
    if (i > 0) input->CopyTo(output, i);
    if (num_read > 0) input->Skip(num_read);
    if (!ok) {
      // Case iii: Report error.
      // TODO(wpoon): Add error reporting.
      num_left = 0;
    } else if (num_left == 0 && !escaped.empty()) {
      // Case i or ii: Append the escaped code point to the output ByteSink.
      output->Append(escaped.data(), escaped.size());
    }
  }
  if (num_left > 0) {
    // Treat as case iii: report error.
    // TODO(wpoon): Add error reporting.
  }
}

}  // namespace converter
}  // namespace util
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__
#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__

#include <deque>
#include <string>
#include <vector>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/internal/type_info.h>
#include <google/protobuf/util/internal/datapiece.h>
#include <google/protobuf/util/internal/error_listener.h>
#include <google/protobuf/util/internal/structured_objectwriter.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/bytestream.h>
#include <google/protobuf/stubs/hash.h>

namespace google {
namespace protobuf {
namespace io {
class CodedOutputStream;
}  // namespace io
}  // namespace protobuf

namespace protobuf {
class Type;
class Field;
}  // namespace protobuf

namespace protobuf {
namespace util {
namespace converter {

class ObjectLocationTracker;

// An ObjectWriter that can write protobuf bytes directly from writer events.
// This class does not support special types like Struct or Map. However, since
// this class supports raw protobuf, it can be used to provide support for
// special types by inheriting from it or by wrapping it.
//
// It also supports streaming.
class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter {
 public:
// Constructor. Does not take ownership of any parameter passed in.
  ProtoWriter(TypeResolver* type_resolver, const google::protobuf::Type& type,
              strings::ByteSink* output, ErrorListener* listener);
  virtual ~ProtoWriter();

  // ObjectWriter methods.
  ProtoWriter* StartObject(StringPiece name);
  ProtoWriter* EndObject();
  ProtoWriter* StartList(StringPiece name);
  ProtoWriter* EndList();
  ProtoWriter* RenderBool(StringPiece name, bool value) {
    return RenderDataPiece(name, DataPiece(value));
  }
  ProtoWriter* RenderInt32(StringPiece name, int32 value) {
    return RenderDataPiece(name, DataPiece(value));
  }
  ProtoWriter* RenderUint32(StringPiece name, uint32 value) {
    return RenderDataPiece(name, DataPiece(value));
  }
  ProtoWriter* RenderInt64(StringPiece name, int64 value) {
    return RenderDataPiece(name, DataPiece(value));
  }
  ProtoWriter* RenderUint64(StringPiece name, uint64 value) {
    return RenderDataPiece(name, DataPiece(value));
  }
  ProtoWriter* RenderDouble(StringPiece name, double value) {
    return RenderDataPiece(name, DataPiece(value));
  }
  ProtoWriter* RenderFloat(StringPiece name, float value) {
    return RenderDataPiece(name, DataPiece(value));
  }
  ProtoWriter* RenderString(StringPiece name, StringPiece value) {
    return RenderDataPiece(name,
                           DataPiece(value, use_strict_base64_decoding()));
  }
  virtual ProtoWriter* RenderBytes(StringPiece name, StringPiece value) {
    return RenderDataPiece(
        name, DataPiece(value, false, use_strict_base64_decoding()));
  }
  ProtoWriter* RenderNull(StringPiece name) {
    return RenderDataPiece(name, DataPiece::NullData());
  }

  // Renders a DataPiece 'value' into a field whose wire type is determined
  // from the given field 'name'.
  virtual ProtoWriter* RenderDataPiece(StringPiece name,
                                       const DataPiece& value);

  // Returns the location tracker to use for tracking locations for errors.
  const LocationTrackerInterface& location() {
    return element_ != NULL ? *element_ : *tracker_;
  }

  // When true, we finished writing to output a complete message.
  bool done() { return done_; }

  // Returns the proto stream object.
  google::protobuf::io::CodedOutputStream* stream() { return stream_.get(); }

  // Getters and mutators of invalid_depth_.
  void IncrementInvalidDepth() { ++invalid_depth_; }
  void DecrementInvalidDepth() { --invalid_depth_; }
  int invalid_depth() { return invalid_depth_; }

  ErrorListener* listener() { return listener_; }

  const TypeInfo* typeinfo() { return typeinfo_; }

  void set_ignore_unknown_fields(bool ignore_unknown_fields) {
    ignore_unknown_fields_ = ignore_unknown_fields;
  }

  void set_use_lower_camel_for_enums(bool use_lower_camel_for_enums) {
    use_lower_camel_for_enums_ = use_lower_camel_for_enums;
  }

 protected:
  class LIBPROTOBUF_EXPORT ProtoElement : public BaseElement, public LocationTrackerInterface {
   public:
    // Constructor for the root element. No parent nor field.
    ProtoElement(const TypeInfo* typeinfo, const google::protobuf::Type& type,
                 ProtoWriter* enclosing);

    // Constructor for a field of an element.
    ProtoElement(ProtoElement* parent, const google::protobuf::Field* field,
                 const google::protobuf::Type& type, bool is_list);

    virtual ~ProtoElement() {}

    // Called just before the destructor for clean up:
    //   - reports any missing required fields
    //   - computes the space needed by the size field, and augment the
    //     length of all parent messages by this additional space.
    //   - releases and returns the parent pointer.
    ProtoElement* pop();

    // Accessors
    // parent_field() may be NULL if we are at root.
    const google::protobuf::Field* parent_field() const {
      return parent_field_;
    }
    const google::protobuf::Type& type() const { return type_; }

    // Registers field for accounting required fields.
    void RegisterField(const google::protobuf::Field* field);

    // To report location on error messages.
    virtual string ToString() const;

    virtual ProtoElement* parent() const {
      return static_cast<ProtoElement*>(BaseElement::parent());
    }

    // Returns true if the index is already taken by a preceding oneof input.
    bool IsOneofIndexTaken(int32 index);

    // Marks the oneof 'index' as taken. Future inputs to this oneof will
    // generate an error.
    void TakeOneofIndex(int32 index);

    bool proto3() { return proto3_; }

   private:
    // Used for access to variables of the enclosing instance of
    // ProtoWriter.
    ProtoWriter* ow_;

    // Describes the element as a field in the parent message.
    // parent_field_ is NULL if and only if this element is the root element.
    const google::protobuf::Field* parent_field_;

    // TypeInfo to lookup types.
    const TypeInfo* typeinfo_;

    // Whether the type_ is proto3 or not.
    bool proto3_;

    // Additional variables if this element is a message:
    // (Root element is always a message).
    // type_             : the type of this element.
    // required_fields_  : set of required fields.
    // size_index_       : index into ProtoWriter::size_insert_
    //                     for later insertion of serialized message length.
    const google::protobuf::Type& type_;
    std::set<const google::protobuf::Field*> required_fields_;
    const int size_index_;

    // Tracks position in repeated fields, needed for LocationTrackerInterface.
    int array_index_;

    // Set of oneof indices already seen for the type_. Used to validate
    // incoming messages so no more than one oneof is set.
    std::vector<bool> oneof_indices_;

    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement);
  };

  // Container for inserting 'size' information at the 'pos' position.
  struct SizeInfo {
    const int pos;
    int size;
  };

  ProtoWriter(const TypeInfo* typeinfo, const google::protobuf::Type& type,
              strings::ByteSink* output, ErrorListener* listener);

  ProtoElement* element() { return element_.get(); }

  // Helper methods for calling ErrorListener. See error_listener.h.
  void InvalidName(StringPiece unknown_name, StringPiece message);
  void InvalidValue(StringPiece type_name, StringPiece value);
  void MissingField(StringPiece missing_name);

  // Common code for BeginObject() and BeginList() that does invalid_depth_
  // bookkeeping associated with name lookup.
  const google::protobuf::Field* BeginNamed(StringPiece name, bool is_list);

  // Lookup the field in the current element. Looks in the base descriptor
  // and in any extension. This will report an error if the field cannot be
  // found when ignore_unknown_names_ is false or if multiple matching
  // extensions are found.
  const google::protobuf::Field* Lookup(StringPiece name);

  // Lookup the field type in the type descriptor. Returns NULL if the type
  // is not known.
  const google::protobuf::Type* LookupType(
      const google::protobuf::Field* field);

  // Write serialized output to the final output ByteSink, inserting all
  // the size information for nested messages that are missing from the
  // intermediate Cord buffer.
  void WriteRootMessage();

  // Helper method to write proto tags based on the given field.
  void WriteTag(const google::protobuf::Field& field);

  // Returns true if the field for type_ can be set as a oneof. If field is not
  // a oneof type, this function does nothing and returns true.
  // If another field for this oneof is already set, this function returns
  // false. It also calls the appropriate error callback.
  // unnormalized_name is used for error string.
  bool ValidOneof(const google::protobuf::Field& field,
                  StringPiece unnormalized_name);

  // Returns true if the field is repeated.
  bool IsRepeated(const google::protobuf::Field& field);

  // Starts an object given the field and the enclosing type.
  ProtoWriter* StartObjectField(const google::protobuf::Field& field,
                                const google::protobuf::Type& type);

  // Starts a list given the field and the enclosing type.
  ProtoWriter* StartListField(const google::protobuf::Field& field,
                              const google::protobuf::Type& type);

  // Renders a primitve field given the field and the enclosing type.
  ProtoWriter* RenderPrimitiveField(const google::protobuf::Field& field,
                                    const google::protobuf::Type& type,
                                    const DataPiece& value);

 private:
  // Variables for describing the structure of the input tree:
  // master_type_: descriptor for the whole protobuf message.
  // typeinfo_ : the TypeInfo object to lookup types.
  const google::protobuf::Type& master_type_;
  const TypeInfo* typeinfo_;
  // Whether we own the typeinfo_ object.
  bool own_typeinfo_;

  // Indicates whether we finished writing root message completely.
  bool done_;

  // If true, don't report unknown field names to the listener.
  bool ignore_unknown_fields_;

  // If true, check if enum name in camel case or without underscore matches the
  // field name.
  bool use_lower_camel_for_enums_;

  // Variable for internal state processing:
  // element_    : the current element.
  // size_insert_: sizes of nested messages.
  //               pos  - position to insert the size field.
  //               size - size value to be inserted.
  google::protobuf::scoped_ptr<ProtoElement> element_;
  std::deque<SizeInfo> size_insert_;

  // Variables for output generation:
  // output_  : pointer to an external ByteSink for final user-visible output.
  // buffer_  : buffer holding partial message before being ready for output_.
  // adapter_ : internal adapter between CodedOutputStream and buffer_.
  // stream_  : wrapper for writing tags and other encodings in wire format.
  strings::ByteSink* output_;
  string buffer_;
  google::protobuf::io::StringOutputStream adapter_;
  google::protobuf::scoped_ptr<google::protobuf::io::CodedOutputStream> stream_;

  // Variables for error tracking and reporting:
  // listener_     : a place to report any errors found.
  // invalid_depth_: number of enclosing invalid nested messages.
  // tracker_      : the root location tracker interface.
  ErrorListener* listener_;
  int invalid_depth_;
  google::protobuf::scoped_ptr<LocationTrackerInterface> tracker_;

  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoWriter);
};

}  // namespace converter
}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__

mime_type: text/plain


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__

#include <functional>
#include <google/protobuf/stubs/hash.h>
#include <string>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/type.pb.h>
#include <google/protobuf/util/internal/object_source.h>
#include <google/protobuf/util/internal/object_writer.h>
#include <google/protobuf/util/internal/type_info.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/stringpiece.h>
#include <google/protobuf/stubs/status.h>
#include <google/protobuf/stubs/statusor.h>

namespace google {
namespace protobuf {
class Field;
class Type;
}  // namespace protobuf

namespace protobuf {
namespace util {
namespace converter {

class TypeInfo;

// An ObjectSource that can parse a stream of bytes as a protocol buffer.
// Its WriteTo() method can be given an ObjectWriter.
// This implementation uses a google.protobuf.Type for tag and name lookup.
// The field names are converted into lower camel-case when writing to the
// ObjectWriter.
//
// Sample usage: (suppose input is: string proto)
//   ArrayInputStream arr_stream(proto.data(), proto.size());
//   CodedInputStream in_stream(&arr_stream);
//   ProtoStreamObjectSource os(&in_stream, /*ServiceTypeInfo*/ typeinfo,
//                              <your message google::protobuf::Type>);
//
//   Status status = os.WriteTo(<some ObjectWriter>);
class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
 public:
  ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
                          TypeResolver* type_resolver,
                          const google::protobuf::Type& type);

  virtual ~ProtoStreamObjectSource();

  virtual util::Status NamedWriteTo(StringPiece name, ObjectWriter* ow) const;

  // Sets whether or not to use lowerCamelCase casing for enum values. If set to
  // false, enum values are output without any case conversions.
  //
  // For example, if we have an enum:
  // enum Type {
  //   ACTION_AND_ADVENTURE = 1;
  // }
  // Type type = 20;
  //
  // And this option is set to true. Then the rendered "type" field will have
  // the string "actionAndAdventure".
  // {
  //   ...
  //   "type": "actionAndAdventure",
  //   ...
  // }
  //
  // If set to false, the rendered "type" field will have the string
  // "ACTION_AND_ADVENTURE".
  // {
  //   ...
  //   "type": "ACTION_AND_ADVENTURE",
  //   ...
  // }
  void set_use_lower_camel_for_enums(bool value) {
    use_lower_camel_for_enums_ = value;
  }

  // Sets whether to always output enums as ints, by default this is off, and
  // enums are rendered as strings.
  void set_use_ints_for_enums(bool value) { use_ints_for_enums_ = value; }

  // Sets whether to use original proto field names
  void set_preserve_proto_field_names(bool value) {
    preserve_proto_field_names_ = value;
  }

  // Sets the max recursion depth of proto message to be deserialized. Proto
  // messages over this depth will fail to be deserialized.
  // Default value is 64.
  void set_max_recursion_depth(int max_depth) {
    max_recursion_depth_ = max_depth;
  }

 protected:
  // Writes a proto2 Message to the ObjectWriter. When the given end_tag is
  // found this method will complete, allowing it to be used for parsing both
  // nested messages (end with 0) and nested groups (end with group end tag).
  // The include_start_and_end parameter allows this method to be called when
  // already inside of an object, and skip calling StartObject and EndObject.
  virtual util::Status WriteMessage(const google::protobuf::Type& descriptor,
                                      StringPiece name, const uint32 end_tag,
                                      bool include_start_and_end,
                                      ObjectWriter* ow) const;

  // Renders a repeating field (packed or unpacked).  Returns the next tag after
  // reading all sequential repeating elements. The caller should use this tag
  // before reading more tags from the stream.
  virtual util::StatusOr<uint32> RenderList(
      const google::protobuf::Field* field, StringPiece name, uint32 list_tag,
      ObjectWriter* ow) const;

  // Looks up a field and verify its consistency with wire type in tag.
  const google::protobuf::Field* FindAndVerifyField(
      const google::protobuf::Type& type, uint32 tag) const;

  // Renders a field value to the ObjectWriter.
  util::Status RenderField(const google::protobuf::Field* field,
                             StringPiece field_name, ObjectWriter* ow) const;

  // Reads field value according to Field spec in 'field' and returns the read
  // value as string. This only works for primitive datatypes (no message
  // types).
  const string ReadFieldValueAsString(
      const google::protobuf::Field& field) const;

 private:
  ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
                          const TypeInfo* typeinfo,
                          const google::protobuf::Type& type);
  // Function that renders a well known type with a modified behavior.
  typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*,
                                         const google::protobuf::Type&,
                                         StringPiece, ObjectWriter*);

  // TODO(skarvaje): Mark these methods as non-const as they modify internal
  // state (stream_).
  //
  // Renders a NWP map.
  // Returns the next tag after reading all map entries. The caller should use
  // this tag before reading more tags from the stream.
  util::StatusOr<uint32> RenderMap(const google::protobuf::Field* field,
                                     StringPiece name, uint32 list_tag,
                                     ObjectWriter* ow) const;

  // Renders a packed repeating field. A packed field is stored as:
  // {tag length item1 item2 item3} instead of the less efficient
  // {tag item1 tag item2 tag item3}.
  util::Status RenderPacked(const google::protobuf::Field* field,
                              ObjectWriter* ow) const;

  // Renders a google.protobuf.Timestamp value to ObjectWriter
  static util::Status RenderTimestamp(const ProtoStreamObjectSource* os,
                                        const google::protobuf::Type& type,
                                        StringPiece name, ObjectWriter* ow);

  // Renders a google.protobuf.Duration value to ObjectWriter
  static util::Status RenderDuration(const ProtoStreamObjectSource* os,
                                       const google::protobuf::Type& type,
                                       StringPiece name, ObjectWriter* ow);

  // Following RenderTYPE functions render well known types in
  // google/protobuf/wrappers.proto corresponding to TYPE.
  static util::Status RenderDouble(const ProtoStreamObjectSource* os,
                                     const google::protobuf::Type& type,
                                     StringPiece name, ObjectWriter* ow);
  static util::Status RenderFloat(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
                                    StringPiece name, ObjectWriter* ow);
  static util::Status RenderInt64(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
                                    StringPiece name, ObjectWriter* ow);
  static util::Status RenderUInt64(const ProtoStreamObjectSource* os,
                                     const google::protobuf::Type& type,
                                     StringPiece name, ObjectWriter* ow);
  static util::Status RenderInt32(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
                                    StringPiece name, ObjectWriter* ow);
  static util::Status RenderUInt32(const ProtoStreamObjectSource* os,
                                     const google::protobuf::Type& type,
                                     StringPiece name, ObjectWriter* ow);
  static util::Status RenderBool(const ProtoStreamObjectSource* os,
                                   const google::protobuf::Type& type,
                                   StringPiece name, ObjectWriter* ow);
  static util::Status RenderString(const ProtoStreamObjectSource* os,
                                     const google::protobuf::Type& type,
                                     StringPiece name, ObjectWriter* ow);
  static util::Status RenderBytes(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
                                    StringPiece name, ObjectWriter* ow);

  // Renders a google.protobuf.Struct to ObjectWriter.
  static util::Status RenderStruct(const ProtoStreamObjectSource* os,
                                     const google::protobuf::Type& type,
                                     StringPiece name, ObjectWriter* ow);

  // Helper to render google.protobuf.Struct's Value fields to ObjectWriter.
  static util::Status RenderStructValue(const ProtoStreamObjectSource* os,
                                          const google::protobuf::Type& type,
                                          StringPiece name, ObjectWriter* ow);

  // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
  static util::Status RenderStructListValue(
      const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
      StringPiece name, ObjectWriter* ow);

  // Render the "Any" type.
  static util::Status RenderAny(const ProtoStreamObjectSource* os,
                                  const google::protobuf::Type& type,
                                  StringPiece name, ObjectWriter* ow);

  // Render the "FieldMask" type.
  static util::Status RenderFieldMask(const ProtoStreamObjectSource* os,
                                        const google::protobuf::Type& type,
                                        StringPiece name, ObjectWriter* ow);

  static hash_map<string, TypeRenderer>* renderers_;
  static void InitRendererMap();
  static void DeleteRendererMap();
  static TypeRenderer* FindTypeRenderer(const string& type_url);

  // Same as above but renders all non-message field types. Callers don't call
  // this function directly. They just use RenderField.
  util::Status RenderNonMessageField(const google::protobuf::Field* field,
                                       StringPiece field_name,
                                       ObjectWriter* ow) const;

  // Utility function to detect proto maps. The 'field' MUST be repeated.
  bool IsMap(const google::protobuf::Field& field) const;

  // Utility to read int64 and int32 values from a message type in stream_.
  // Used for reading google.protobuf.Timestamp and Duration messages.
  std::pair<int64, int32> ReadSecondsAndNanos(
      const google::protobuf::Type& type) const;

  // Helper function to check recursion depth and increment it. It will return
  // Status::OK if the current depth is allowed. Otherwise an error is returned.
  // type_name and field_name are used for error reporting.
  util::Status IncrementRecursionDepth(StringPiece type_name,
                                         StringPiece field_name) const;

  // Input stream to read from. Ownership rests with the caller.
  google::protobuf::io::CodedInputStream* stream_;

  // Type information for all the types used in the descriptor. Used to find
  // google::protobuf::Type of nested messages/enums.
  const TypeInfo* typeinfo_;

  // Whether this class owns the typeinfo_ object. If true the typeinfo_ object
  // should be deleted in the destructor.
  bool own_typeinfo_;

  // google::protobuf::Type of the message source.
  const google::protobuf::Type& type_;

  // Whether to render enums using lowerCamelCase. Defaults to false.
  bool use_lower_camel_for_enums_;

  // Whether to render enums as ints always. Defaults to false.
  bool use_ints_for_enums_;

  // Whether to preserve proto field names
  bool preserve_proto_field_names_;

  // Tracks current recursion depth.
  mutable int recursion_depth_;

  // Maximum allowed recursion depth.
  int max_recursion_depth_;

  // Whether to render unknown fields.
  bool render_unknown_fields_;

  // Whether to render unknown enum values.
  bool render_unknown_enum_values_;

  // Whether to add trailing zeros for timestamp and duration.
  bool add_trailing_zeros_for_timestamp_and_duration_;

  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
};

}  // namespace converter
}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__
#define GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__

#include <algorithm>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
#include <vector>

#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/util/internal/location_tracker.h>
#include <google/protobuf/stubs/stringpiece.h>

namespace google {
namespace protobuf {
namespace util {
namespace converter {

// Interface for error listener.
class LIBPROTOBUF_EXPORT ErrorListener {
 public:
  virtual ~ErrorListener() {}

  // Reports an invalid name at the given location.
  virtual void InvalidName(const LocationTrackerInterface& loc,
                           StringPiece invalid_name, StringPiece message) = 0;

  // Reports an invalid value for a field.
  virtual void InvalidValue(const LocationTrackerInterface& loc,
                            StringPiece type_name, StringPiece value) = 0;

  // Reports a missing required field.
  virtual void MissingField(const LocationTrackerInterface& loc,
                            StringPiece missing_name) = 0;

 protected:
  ErrorListener() {}

 private:
  // Do not add any data members to this class.
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorListener);
};

// An error listener that ignores all errors.
class LIBPROTOBUF_EXPORT NoopErrorListener : public ErrorListener {
 public:
  NoopErrorListener() {}
  virtual ~NoopErrorListener() {}

  virtual void InvalidName(const LocationTrackerInterface& loc,
                           StringPiece invalid_name, StringPiece message) {}

  virtual void InvalidValue(const LocationTrackerInterface& loc,
                            StringPiece type_name, StringPiece value) {}

  virtual void MissingField(const LocationTrackerInterface& loc,
                            StringPiece missing_name) {}

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NoopErrorListener);
};

}  // namespace converter
}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <google/protobuf/util/internal/default_value_objectwriter.h>
#include <google/protobuf/util/internal/expecting_objectwriter.h>
#include <google/protobuf/util/internal/testdata/default_value_test.pb.h>
#include <google/protobuf/util/internal/type_info_test_helper.h>
#include <google/protobuf/util/internal/constants.h>
#include <gtest/gtest.h>

namespace google {
namespace protobuf {
namespace util {
namespace converter {
namespace testing {

using google::protobuf::testing::DefaultValueTest;

// Base class for setting up required state for running default values tests on
// different descriptors.
class BaseDefaultValueObjectWriterTest
    : public ::testing::TestWithParam<testing::TypeInfoSource> {
 protected:
  explicit BaseDefaultValueObjectWriterTest(const Descriptor* descriptor)
      : helper_(GetParam()), mock_(), expects_(&mock_) {
    helper_.ResetTypeInfo(descriptor);
    testing_.reset(helper_.NewDefaultValueWriter(
        string(kTypeServiceBaseUrl) + "/" + descriptor->full_name(), &mock_));
  }

  virtual ~BaseDefaultValueObjectWriterTest() {}

  TypeInfoTestHelper helper_;
  MockObjectWriter mock_;
  ExpectingObjectWriter expects_;
  google::protobuf::scoped_ptr<DefaultValueObjectWriter> testing_;
};

// Tests to cover some basic DefaultValueObjectWriter use cases. More tests are
// in the marshalling_test.cc and translator_integration_test.cc.
class DefaultValueObjectWriterTest : public BaseDefaultValueObjectWriterTest {
 protected:
  DefaultValueObjectWriterTest()
      : BaseDefaultValueObjectWriterTest(DefaultValueTest::descriptor()) {}
  virtual ~DefaultValueObjectWriterTest() {}
};

INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
                        DefaultValueObjectWriterTest,
                        ::testing::Values(
                            testing::USE_TYPE_RESOLVER));

TEST_P(DefaultValueObjectWriterTest, Empty) {
  // Set expectation
  expects_.StartObject("")
      ->RenderDouble("doubleValue", 0.0)
      ->StartList("repeatedDouble")
      ->EndList()
      ->RenderFloat("floatValue", 0.0)
      ->RenderInt64("int64Value", 0)
      ->RenderUint64("uint64Value", 0)
      ->RenderInt32("int32Value", 0)
      ->RenderUint32("uint32Value", 0)
      ->RenderBool("boolValue", false)
      ->RenderString("stringValue", "")
      ->RenderBytes("bytesValue", "")
      ->RenderString("enumValue", "ENUM_FIRST")
      ->EndObject();

  // Actual testing
  testing_->StartObject("")->EndObject();
}

TEST_P(DefaultValueObjectWriterTest, NonDefaultDouble) {
  // Set expectation
  expects_.StartObject("")
      ->RenderDouble("doubleValue", 1.0)
      ->StartList("repeatedDouble")
      ->EndList()
      ->RenderFloat("floatValue", 0.0)
      ->RenderInt64("int64Value", 0)
      ->RenderUint64("uint64Value", 0)
      ->RenderInt32("int32Value", 0)
      ->RenderUint32("uint32Value", 0)
      ->RenderBool("boolValue", false)
      ->RenderString("stringValue", "")
      ->RenderString("enumValue", "ENUM_FIRST")
      ->EndObject();

  // Actual testing
  testing_->StartObject("")->RenderDouble("doubleValue", 1.0)->EndObject();
}

TEST_P(DefaultValueObjectWriterTest, ShouldRetainUnknownField) {
  // Set expectation
  expects_.StartObject("")
      ->RenderDouble("doubleValue", 1.0)
      ->StartList("repeatedDouble")
      ->EndList()
      ->RenderFloat("floatValue", 0.0)
      ->RenderInt64("int64Value", 0)
      ->RenderUint64("uint64Value", 0)
      ->RenderInt32("int32Value", 0)
      ->RenderUint32("uint32Value", 0)
      ->RenderBool("boolValue", false)
      ->RenderString("stringValue", "")
      ->RenderString("unknown", "abc")
      ->StartObject("unknownObject")
      ->RenderString("unknown", "def")
      ->EndObject()
      ->RenderString("enumValue", "ENUM_FIRST")
      ->EndObject();

  // Actual testing
  testing_->StartObject("")
      ->RenderDouble("doubleValue", 1.0)
      ->RenderString("unknown", "abc")
      ->StartObject("unknownObject")
      ->RenderString("unknown", "def")
      ->EndObject()
      ->EndObject();
}

class DefaultValueObjectWriterSuppressListTest
    : public BaseDefaultValueObjectWriterTest {
 protected:
  DefaultValueObjectWriterSuppressListTest()
      : BaseDefaultValueObjectWriterTest(DefaultValueTest::descriptor()) {
    testing_->set_suppress_empty_list(true);
  }
  ~DefaultValueObjectWriterSuppressListTest() {}
};

INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
                        DefaultValueObjectWriterSuppressListTest,
                        ::testing::Values(
                            testing::USE_TYPE_RESOLVER));

TEST_P(DefaultValueObjectWriterSuppressListTest, Empty) {
  // Set expectation. Emtpy lists should be suppressed.
  expects_.StartObject("")
      ->RenderDouble("doubleValue", 0.0)
      ->RenderFloat("floatValue", 0.0)
      ->RenderInt64("int64Value", 0)
      ->RenderUint64("uint64Value", 0)
      ->RenderInt32("int32Value", 0)
      ->RenderUint32("uint32Value", 0)
      ->RenderBool("boolValue", false)
      ->RenderString("stringValue", "")
      ->RenderBytes("bytesValue", "")
      ->RenderString("enumValue", "ENUM_FIRST")
      ->EndObject();

  // Actual testing
  testing_->StartObject("")->EndObject();
}
}  // namespace testing
}  // namespace converter
}  // namespace util
}  // namespace protobuf
}  // namespace google


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__
#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__

#include <deque>
#include <google/protobuf/stubs/hash.h>
#include <string>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/internal/type_info.h>
#include <google/protobuf/util/internal/datapiece.h>
#include <google/protobuf/util/internal/error_listener.h>
#include <google/protobuf/util/internal/proto_writer.h>
#include <google/protobuf/util/internal/structured_objectwriter.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/bytestream.h>

namespace google {
namespace protobuf {
namespace io {
class CodedOutputStream;
}  // namespace io
}  // namespace protobuf

namespace protobuf {
class Type;
class Field;
}  // namespace protobuf

namespace protobuf {
namespace util {
namespace converter {

class ObjectLocationTracker;

// An ObjectWriter that can write protobuf bytes directly from writer events.
// This class supports all special types like Struct and Map. It uses
// the ProtoWriter class to write raw proto bytes.
//
// It also supports streaming.
class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter {
 public:
  // Options that control ProtoStreamObjectWriter class's behavior.
  struct Options {
    // Treats numeric inputs in google.protobuf.Struct as strings. Normally,
    // numeric values are returned in double field "number_value" of
    // google.protobuf.Struct. However, this can cause precision loss for
    // int64/uint64/double inputs. This option is provided for cases that want
    // to preserve number precision.
    //
    // TODO(skarvaje): Rename to struct_numbers_as_strings as it covers double
    // as well.
    bool struct_integers_as_strings;

    // Not treat unknown fields as an error. If there is an unknown fields,
    // just ignore it and continue to process the rest.
    bool ignore_unknown_fields;

    // If true, check if enum name in camel case or without underscore matches
    // the field name.
    bool use_lower_camel_for_enums;

    Options()
        : struct_integers_as_strings(false),
          ignore_unknown_fields(false),
          use_lower_camel_for_enums(false) {}

    // Default instance of Options with all options set to defaults.
    static const Options& Defaults() {
      static Options defaults;
      return defaults;
    }
  };

// Constructor. Does not take ownership of any parameter passed in.
  ProtoStreamObjectWriter(TypeResolver* type_resolver,
                          const google::protobuf::Type& type,
                          strings::ByteSink* output, ErrorListener* listener,
                          const ProtoStreamObjectWriter::Options& options =
                              ProtoStreamObjectWriter::Options::Defaults());
  virtual ~ProtoStreamObjectWriter();

  // ObjectWriter methods.
  virtual ProtoStreamObjectWriter* StartObject(StringPiece name);
  virtual ProtoStreamObjectWriter* EndObject();
  virtual ProtoStreamObjectWriter* StartList(StringPiece name);
  virtual ProtoStreamObjectWriter* EndList();

  // Renders a DataPiece 'value' into a field whose wire type is determined
  // from the given field 'name'.
  virtual ProtoStreamObjectWriter* RenderDataPiece(StringPiece name,
                                                   const DataPiece& value);

 protected:
  // Function that renders a well known type with modified behavior.
  typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*,
                                         const DataPiece&);

  // Handles writing Anys out using nested object writers and the like.
  class LIBPROTOBUF_EXPORT AnyWriter {
   public:
    explicit AnyWriter(ProtoStreamObjectWriter* parent);
    ~AnyWriter();

    // Passes a StartObject call through to the Any writer.
    void StartObject(StringPiece name);

    // Passes an EndObject call through to the Any. Returns true if the any
    // handled the EndObject call, false if the Any is now all done and is no
    // longer needed.
    bool EndObject();

    // Passes a StartList call through to the Any writer.
    void StartList(StringPiece name);

    // Passes an EndList call through to the Any writer.
    void EndList();

    // Renders a data piece on the any.
    void RenderDataPiece(StringPiece name, const DataPiece& value);

   private:
    // Before the "@type" field is encountered, we store all incoming data
    // into this Event struct and replay them after we get the "@type" field.
    class LIBPROTOBUF_EXPORT Event {
     public:
      enum Type {
        START_OBJECT = 0,
        END_OBJECT = 1,
        START_LIST = 2,
        END_LIST = 3,
        RENDER_DATA_PIECE = 4,
      };

      // Constructor for END_OBJECT and END_LIST events.
      explicit Event(Type type) : type_(type), value_(DataPiece::NullData()) {}

      // Constructor for START_OBJECT and START_LIST events.
      explicit Event(Type type, StringPiece name)
          : type_(type),
            name_(name.ToString()),
            value_(DataPiece::NullData()) {}

      // Constructor for RENDER_DATA_PIECE events.
      explicit Event(StringPiece name, const DataPiece& value)
          : type_(RENDER_DATA_PIECE), name_(name.ToString()), value_(value) {
        DeepCopy();
      }

      Event(const Event& other)
          : type_(other.type_), name_(other.name_), value_(other.value_) {
        DeepCopy();
      }

      Event& operator=(const Event& other) {
        type_ = other.type_;
        name_ = other.name_;
        value_ = other.value_;
        DeepCopy();
        return *this;
      }

      void Replay(AnyWriter* writer) const;

     private:
      void DeepCopy();

      Type type_;
      string name_;
      DataPiece value_;
      string value_storage_;
    };

    // Handles starting up the any once we have a type.
    void StartAny(const DataPiece& value);

    // Writes the Any out to the parent writer in its serialized form.
    void WriteAny();

    // The parent of this writer, needed for various bits such as type info and
    // the listeners.
    ProtoStreamObjectWriter* parent_;

    // The nested object writer, used to write events.
    google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_;

    // The type_url_ that this Any represents.
    string type_url_;

    // Whether this any is invalid. This allows us to only report an invalid
    // Any message a single time rather than every time we get a nested field.
    bool invalid_;

    // The output data and wrapping ByteSink.
    string data_;
    strings::StringByteSink output_;

    // The depth within the Any, so we can track when we're done.
    int depth_;

    // True if the type is a well-known type. Well-known types in Any
    // has a special formating:
    // {
    //   "@type": "type.googleapis.com/google.protobuf.XXX",
    //   "value": <JSON representation of the type>,
    // }
    bool is_well_known_type_;
    TypeRenderer* well_known_type_render_;

    // Store data before the "@type" field.
    std::vector<Event> uninterpreted_events_;
  };

  // Represents an item in a stack of items used to keep state between
  // ObjectWrier events.
  class LIBPROTOBUF_EXPORT Item : public BaseElement {
   public:
    // Indicates the type of item.
    enum ItemType {
      MESSAGE,  // Simple message
      MAP,      // Proto3 map type
      ANY,      // Proto3 Any type
    };

    // Constructor for the root item.
    Item(ProtoStreamObjectWriter* enclosing, ItemType item_type,
         bool is_placeholder, bool is_list);

    // Constructor for a field of a message.
    Item(Item* parent, ItemType item_type, bool is_placeholder, bool is_list);

    virtual ~Item() {}

    // These functions return true if the element type is corresponding to the
    // type in function name.
    bool IsMap() { return item_type_ == MAP; }
    bool IsAny() { return item_type_ == ANY; }

    AnyWriter* any() const { return any_.get(); }

    virtual Item* parent() const {
      return static_cast<Item*>(BaseElement::parent());
    }

    // Inserts map key into hash set if and only if the key did NOT already
    // exist in hash set.
    // The hash set (map_keys_) is ONLY used to keep track of map keys.
    // Return true if insert successfully; returns false if the map key was
    // already present.
    bool InsertMapKeyIfNotPresent(StringPiece map_key);

    bool is_placeholder() const { return is_placeholder_; }
    bool is_list() const { return is_list_; }

   private:
    // Used for access to variables of the enclosing instance of
    // ProtoStreamObjectWriter.
    ProtoStreamObjectWriter* ow_;

    // A writer for Any objects, handles all Any-related nonsense.
    google::protobuf::scoped_ptr<AnyWriter> any_;

    // The type of this element, see enum for permissible types.
    ItemType item_type_;

    // Set of map keys already seen for the type_. Used to validate incoming
    // messages so no map key appears more than once.
    google::protobuf::scoped_ptr<hash_set<string> > map_keys_;

    // Conveys whether this Item is a placeholder or not. Placeholder items are
    // pushed to stack to account for special types.
    bool is_placeholder_;

    // Conveys whether this Item is a list or not. This is used to send
    // StartList or EndList calls to underlying ObjectWriter.
    bool is_list_;

    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Item);
  };

  ProtoStreamObjectWriter(const TypeInfo* typeinfo,
                          const google::protobuf::Type& type,
                          strings::ByteSink* output, ErrorListener* listener);

  // Returns true if the field is a map.
  inline bool IsMap(const google::protobuf::Field& field);

  // Returns true if the field is an any.
  inline bool IsAny(const google::protobuf::Field& field);

  // Returns true if the field is google.protobuf.Struct.
  inline bool IsStruct(const google::protobuf::Field& field);

  // Returns true if the field is google.protobuf.Value.
  inline bool IsStructValue(const google::protobuf::Field& field);

  // Returns true if the field is google.protobuf.ListValue.
  inline bool IsStructListValue(const google::protobuf::Field& field);

  // Renders google.protobuf.Value in struct.proto. It picks the right oneof
  // type based on value's type.
  static util::Status RenderStructValue(ProtoStreamObjectWriter* ow,
                                          const DataPiece& value);

  // Renders google.protobuf.Timestamp value.
  static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow,
                                        const DataPiece& value);

  // Renders google.protobuf.FieldMask value.
  static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow,
                                        const DataPiece& value);

  // Renders google.protobuf.Duration value.
  static util::Status RenderDuration(ProtoStreamObjectWriter* ow,
                                       const DataPiece& value);

  // Renders wrapper message types for primitive types in
  // google/protobuf/wrappers.proto.
  static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow,
                                          const DataPiece& value);

  static void InitRendererMap();
  static void DeleteRendererMap();
  static TypeRenderer* FindTypeRenderer(const string& type_url);

  // Returns true if the map key for type_ is not duplicated key.
  // If map key is duplicated key, this function returns false.
  // Note that caller should make sure that the current proto element (current_)
  // is of element type MAP or STRUCT_MAP.
  // It also calls the appropriate error callback and unnormalzied_name is used
  // for error string.
  bool ValidMapKey(StringPiece unnormalized_name);

  // Pushes an item on to the stack. Also calls either StartObject or StartList
  // on the underlying ObjectWriter depending on whether is_list is false or
  // not.
  // is_placeholder conveys whether the item is a placeholder item or not.
  // Placeholder items are pushed when adding auxillary types' StartObject or
  // StartList calls.
  void Push(StringPiece name, Item::ItemType item_type, bool is_placeholder,
            bool is_list);

  // Pops items from the stack. All placeholder items are popped until a
  // non-placeholder item is found.
  void Pop();

  // Pops one element from the stack. Calls EndObject() or EndList() on the
  // underlying ObjectWriter depending on the value of is_list_.
  void PopOneElement();

 private:
  // Helper functions to create the map and find functions responsible for
  // rendering well known types, keyed by type URL.
  static hash_map<string, TypeRenderer>* renderers_;

  // Variables for describing the structure of the input tree:
  // master_type_: descriptor for the whole protobuf message.
  const google::protobuf::Type& master_type_;

  // The current element, variable for internal state processing.
  google::protobuf::scoped_ptr<Item> current_;

  // Reference to the options that control this class's behavior.
  const ProtoStreamObjectWriter::Options options_;

  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter);
};

}  // namespace converter
}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__
#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__

#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <vector>

#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/internal/default_value_objectwriter.h>
#include <google/protobuf/util/internal/type_info.h>
#include <google/protobuf/util/internal/protostream_objectsource.h>
#include <google/protobuf/util/internal/protostream_objectwriter.h>
#include <google/protobuf/util/type_resolver.h>

namespace google {
namespace protobuf {
namespace util {
namespace converter {
namespace testing {

enum TypeInfoSource {
  USE_TYPE_RESOLVER,
};

// In the unit-tests we want to test two scenarios: one with type info from
// ServiceTypeInfo, the other with type info from TypeResolver. This class
// wraps the detail of where the type info is from and provides the same
// interface so the same unit-test code can test both scenarios.
class TypeInfoTestHelper {
 public:
  explicit TypeInfoTestHelper(TypeInfoSource type) : type_(type) {}

  // Creates a TypeInfo object for the given set of descriptors.
  void ResetTypeInfo(const std::vector<const Descriptor*>& descriptors);

  // Convinent overloads.
  void ResetTypeInfo(const Descriptor* descriptor);
  void ResetTypeInfo(const Descriptor* descriptor1,
                     const Descriptor* descriptor2);

  // Returns the TypeInfo created after ResetTypeInfo.
  TypeInfo* GetTypeInfo();

  ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input,
                                          const string& type_url);

  ProtoStreamObjectWriter* NewProtoWriter(
      const string& type_url, strings::ByteSink* output,
      ErrorListener* listener, const ProtoStreamObjectWriter::Options& options);

  DefaultValueObjectWriter* NewDefaultValueWriter(const string& type_url,
                                                  ObjectWriter* writer);

 private:
  TypeInfoSource type_;
  google::protobuf::scoped_ptr<TypeInfo> typeinfo_;
  google::protobuf::scoped_ptr<TypeResolver> type_resolver_;
};
}  // namespace testing
}  // namespace converter
}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__

#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <stack>
#include <vector>

#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/util/internal/type_info.h>
#include <google/protobuf/util/internal/datapiece.h>
#include <google/protobuf/util/internal/object_writer.h>
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/stringpiece.h>

namespace google {
namespace protobuf {
namespace util {
namespace converter {

// An ObjectWriter that renders non-repeated primitive fields of proto messages
// with their default values. DefaultValueObjectWriter holds objects, lists and
// fields it receives in a tree structure and writes them out to another
// ObjectWriter when EndObject() is called on the root object. It also writes
// out all non-repeated primitive fields that haven't been explicitly rendered
// with their default values (0 for numbers, "" for strings, etc).
class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
 public:
  // A Callback function to check whether a field needs to be scrubbed.
  //
  // Returns true if the field should not be present in the output. Returns
  // false otherwise.
  //
  // The 'path' parameter is a vector of path to the field from root. For
  // example: if a nested field "a.b.c" (b is the parent message field of c and
  // a is the parent message field of b), then the vector should contain { "a",
  // "b", "c" }.
  //
  // The Field* should point to the google::protobuf::Field of "c".
  typedef ResultCallback2<bool /*return*/,
                          const std::vector<string>& /*path of the field*/,
                          const google::protobuf::Field* /*field*/>
      FieldScrubCallBack;

  // A unique pointer to a DefaultValueObjectWriter::FieldScrubCallBack.
  typedef google::protobuf::scoped_ptr<FieldScrubCallBack> FieldScrubCallBackPtr;

  DefaultValueObjectWriter(TypeResolver* type_resolver,
                           const google::protobuf::Type& type,
                           ObjectWriter* ow);

  virtual ~DefaultValueObjectWriter();

  // ObjectWriter methods.
  virtual DefaultValueObjectWriter* StartObject(StringPiece name);

  virtual DefaultValueObjectWriter* EndObject();

  virtual DefaultValueObjectWriter* StartList(StringPiece name);

  virtual DefaultValueObjectWriter* EndList();

  virtual DefaultValueObjectWriter* RenderBool(StringPiece name, bool value);

  virtual DefaultValueObjectWriter* RenderInt32(StringPiece name, int32 value);

  virtual DefaultValueObjectWriter* RenderUint32(StringPiece name,
                                                 uint32 value);

  virtual DefaultValueObjectWriter* RenderInt64(StringPiece name, int64 value);

  virtual DefaultValueObjectWriter* RenderUint64(StringPiece name,
                                                 uint64 value);

  virtual DefaultValueObjectWriter* RenderDouble(StringPiece name,
                                                 double value);

  virtual DefaultValueObjectWriter* RenderFloat(StringPiece name, float value);

  virtual DefaultValueObjectWriter* RenderString(StringPiece name,
                                                 StringPiece value);
  virtual DefaultValueObjectWriter* RenderBytes(StringPiece name,
                                                StringPiece value);

  virtual DefaultValueObjectWriter* RenderNull(StringPiece name);

  // Register the callback for scrubbing of fields. Owership of
  // field_scrub_callback pointer is also transferred to this class
  void RegisterFieldScrubCallBack(FieldScrubCallBackPtr field_scrub_callback);

  // If set to true, empty lists are suppressed from output when default values
  // are written.
  void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; }

  // If set to true, original proto field names are used
  void set_preserve_proto_field_names(bool value) {
    preserve_proto_field_names_ = value;
  }

 protected:
  enum NodeKind {
    PRIMITIVE = 0,
    OBJECT = 1,
    LIST = 2,
    MAP = 3,
  };

  // "Node" represents a node in the tree that holds the input of
  // DefaultValueObjectWriter.
  class LIBPROTOBUF_EXPORT Node {
   public:
    Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
         const DataPiece& data, bool is_placeholder,
         const std::vector<string>& path, bool suppress_empty_list,
         FieldScrubCallBack* field_scrub_callback);
    Node(const string& name, const google::protobuf::Type* type, NodeKind kind,
         const DataPiece& data, bool is_placeholder,
         const std::vector<string>& path, bool suppress_empty_list,
         bool preserve_proto_field_names,
         FieldScrubCallBack* field_scrub_callback);
    virtual ~Node() {
      for (int i = 0; i < children_.size(); ++i) {
        delete children_[i];
      }
    }

    // Adds a child to this node. Takes ownership of this child.
    void AddChild(Node* child) { children_.push_back(child); }

    // Finds the child given its name.
    Node* FindChild(StringPiece name);

    // Populates children of this Node based on its type. If there are already
    // children created, they will be merged to the result. Caller should pass
    // in TypeInfo for looking up types of the children.
    virtual void PopulateChildren(const TypeInfo* typeinfo);

    // If this node is a leaf (has data), writes the current node to the
    // ObjectWriter; if not, then recursively writes the children to the
    // ObjectWriter.
    virtual void WriteTo(ObjectWriter* ow);

    // Accessors
    const string& name() const { return name_; }

    const std::vector<string>& path() const { return path_; }

    const google::protobuf::Type* type() const { return type_; }

    void set_type(const google::protobuf::Type* type) { type_ = type; }

    NodeKind kind() const { return kind_; }

    int number_of_children() const { return children_.size(); }

    void set_data(const DataPiece& data) { data_ = data; }

    bool is_any() const { return is_any_; }

    void set_is_any(bool is_any) { is_any_ = is_any; }

    void set_is_placeholder(bool is_placeholder) {
      is_placeholder_ = is_placeholder;
    }

   protected:
    // Returns the Value Type of a map given the Type of the map entry and a
    // TypeInfo instance.
    const google::protobuf::Type* GetMapValueType(
        const google::protobuf::Type& entry_type, const TypeInfo* typeinfo);

    // Calls WriteTo() on every child in children_.
    void WriteChildren(ObjectWriter* ow);

    // The name of this node.
    string name_;
    // google::protobuf::Type of this node. Owned by TypeInfo.
    const google::protobuf::Type* type_;
    // The kind of this node.
    NodeKind kind_;
    // Whether this is a node for "Any".
    bool is_any_;
    // The data of this node when it is a leaf node.
    DataPiece data_;
    // Children of this node.
    std::vector<Node*> children_;
    // Whether this node is a placeholder for an object or list automatically
    // generated when creating the parent node. Should be set to false after
    // the parent node's StartObject()/StartList() method is called with this
    // node's name.
    bool is_placeholder_;

    // Path of the field of this node
    std::vector<string> path_;

    // Whether to suppress empty list output.
    bool suppress_empty_list_;

    // Whether to preserve original proto field names
    bool preserve_proto_field_names_;

    // Pointer to function for determining whether a field needs to be scrubbed
    // or not. This callback is owned by the creator of this node.
    FieldScrubCallBack* field_scrub_callback_;

   private:
    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
  };

  // Creates a new Node and returns it. Caller owns memory of returned object.
  virtual Node* CreateNewNode(const string& name,
                              const google::protobuf::Type* type, NodeKind kind,
                              const DataPiece& data, bool is_placeholder,
                              const std::vector<string>& path,
                              bool suppress_empty_list,
                              FieldScrubCallBack* field_scrub_callback);

  // Creates a new Node and returns it. Caller owns memory of returned object.
  virtual Node* CreateNewNode(const string& name,
                              const google::protobuf::Type* type, NodeKind kind,
                              const DataPiece& data, bool is_placeholder,
                              const std::vector<string>& path,
                              bool suppress_empty_list,
                              bool preserve_proto_field_names,
                              FieldScrubCallBack* field_scrub_callback);

  // Creates a DataPiece containing the default value of the type of the field.
  static DataPiece CreateDefaultDataPieceForField(
      const google::protobuf::Field& field, const TypeInfo* typeinfo);

 protected:
  // Returns a pointer to current Node in tree.
  Node* current() { return current_; }

 private:
  // Populates children of "node" if it is an "any" Node and its real type has
  // been given.
  void MaybePopulateChildrenOfAny(Node* node);

  // Writes the root_ node to ow_ and resets the root_ and current_ pointer to
  // NULL.
  void WriteRoot();

  // Adds or replaces the data_ of a primitive child node.
  void RenderDataPiece(StringPiece name, const DataPiece& data);

  // Returns the default enum value as a DataPiece, or the first enum value if
  // there is no default. For proto3, where we cannot specify an explicit
  // default, a zero value will always be returned.
  static DataPiece FindEnumDefault(const google::protobuf::Field& field,
                                   const TypeInfo* typeinfo);

  // Type information for all the types used in the descriptor. Used to find
  // google::protobuf::Type of nested messages/enums.
  const TypeInfo* typeinfo_;
  // Whether the TypeInfo object is owned by this class.
  bool own_typeinfo_;
  // google::protobuf::Type of the root message type.
  const google::protobuf::Type& type_;
  // Holds copies of strings passed to RenderString.
  std::vector<string*> string_values_;

  // The current Node. Owned by its parents.
  Node* current_;
  // The root Node.
  google::protobuf::scoped_ptr<Node> root_;
  // The stack to hold the path of Nodes from current_ to root_;
  std::stack<Node*> stack_;

  // Whether to suppress output of empty lists.
  bool suppress_empty_list_;

  // Whether to preserve original proto field names
  bool preserve_proto_field_names_;

  // Unique Pointer to function for determining whether a field needs to be
  // scrubbed or not.
  FieldScrubCallBackPtr field_scrub_callback_;

  ObjectWriter* ow_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter);
};

}  // namespace converter
}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__
#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringpiece.h>
#include <google/protobuf/stubs/status.h>

namespace google {
namespace protobuf {
namespace util {
namespace converter {

class ObjectWriter;

// An ObjectSource is anything that can write to an ObjectWriter.
// Implementation of this interface typically provide constructors or
// factory methods to create an instance based on some source data, for
// example, a character stream, or protobuf.
//
// Derived classes could be thread-unsafe.
class LIBPROTOBUF_EXPORT ObjectSource {
 public:
  virtual ~ObjectSource() {}

  // Writes to the ObjectWriter
  virtual util::Status WriteTo(ObjectWriter* ow) const {
    return NamedWriteTo("", ow);
  }

  // Writes to the ObjectWriter with a custom name for the message.
  // This is useful when you chain ObjectSource together by embedding one
  // within another.
  virtual util::Status NamedWriteTo(StringPiece name,
                                      ObjectWriter* ow) const = 0;

 protected:
  ObjectSource() {}

 private:
  // Do not add any data members to this class.
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectSource);
};

}  // namespace converter
}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__


text:
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__
#define GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__

#include <google/protobuf/stubs/common.h>

// This file contains constants used by //net/proto2/util/converter.

namespace google {
namespace protobuf {
namespace util {
namespace converter {
// Prefix for type URLs.
const char kTypeServiceBaseUrl[] = "type.googleapis.com";

// Format string for RFC3339 timestamp formatting.
const char kRfc3339TimeFormat[] = "%E4Y-%m-%dT%H:%M:%S";

// Same as above, but the year value is not zero-padded i.e. this accepts
// timestamps like "1-01-0001T23:59:59Z" instead of "0001-01-0001T23:59:59Z".
const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S";

// Minimun seconds allowed in a google.protobuf.Timestamp value.
const int64 kTimestampMinSeconds = -62135596800LL;

// Maximum seconds allowed in a google.protobuf.Timestamp value.
const int64 kTimestampMaxSeconds = 253402300799LL;

// Minimum seconds allowed in a google.protobuf.Duration value.
const int64 kDurationMinSeconds = -315576000000LL;

// Maximum seconds allowed in a google.protobuf.Duration value.
const int64 kDurationMaxSeconds = 315576000000LL;

// Nano seconds in a second.
const int32 kNanosPerSecond = 1000000000;

// Type url representing NULL values in google.protobuf.Struct type.
const char kStructNullValueTypeUrl[] =
    "type.googleapis.com/google.protobuf.NullValue";

// Type string for google.protobuf.Struct
const char kStructType[] = "google.protobuf.Struct";

// Type string for struct.proto's google.protobuf.Value value type.
const char kStructValueType[] = "google.protobuf.Value";

// Type string for struct.proto's google.protobuf.ListValue value type.
const char kStructListValueType[] = "google.protobuf.ListValue";

// Type string for google.protobuf.Timestamp
const char kTimestampType[] = "google.protobuf.Timestamp";

// Type string for google.protobuf.Duration
const char kDurationType[] = "google.protobuf.Duration";

// Type URL for struct value type google.protobuf.Value
const char kStructValueTypeUrl[] = "type.googleapis.com/google.protobuf.Value";

// Type URL for struct value type google.protobuf.Value
const char kStructTypeUrl[] = "type.googleapis.com/google.protobuf.Struct";

// Type string for google.protobuf.Any
const char kAnyType[] = "google.protobuf.Any";

// The type URL of google.protobuf.FieldMask;
const char kFieldMaskTypeUrl[] =
    "type.googleapis.com/google.protobuf.FieldMask";

}  // namespace converter
}  // namespace util
}  // namespace protobuf
}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__