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

#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>

namespace google {
namespace protobuf {
namespace util {

using google::protobuf::FieldMask;

string FieldMaskUtil::ToString(const FieldMask& mask) {
  return Join(mask.paths(), ",");
}

void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) {
  out->Clear();
  std::vector<string> paths = Split(str, ",");
  for (int i = 0; i < paths.size(); ++i) {
    if (paths[i].empty()) continue;
    out->add_paths(paths[i]);
  }
}

bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, string* output) {
  output->clear();
  bool after_underscore = false;
  for (int i = 0; i < input.size(); ++i) {
    if (input[i] >= 'A' && input[i] <= 'Z') {
      // The field name must not contain uppercase letters.
      return false;
    }
    if (after_underscore) {
      if (input[i] >= 'a' && input[i] <= 'z') {
        output->push_back(input[i] + 'A' - 'a');
        after_underscore = false;
      } else {
        // The character after a "_" must be a lowercase letter.
        return false;
      }
    } else if (input[i] == '_') {
      after_underscore = true;
    } else {
      output->push_back(input[i]);
    }
  }
  if (after_underscore) {
    // Trailing "_".
    return false;
  }
  return true;
}

bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input, string* output) {
  output->clear();
  for (int i = 0; i < input.size(); ++i) {
    if (input[i] == '_') {
      // The field name must not contain "_"s.
      return false;
    }
    if (input[i] >= 'A' && input[i] <= 'Z') {
      output->push_back('_');
      output->push_back(input[i] + 'a' - 'A');
    } else {
      output->push_back(input[i]);
    }
  }
  return true;
}

bool FieldMaskUtil::ToJsonString(const FieldMask& mask, string* out) {
  out->clear();
  for (int i = 0; i < mask.paths_size(); ++i) {
    const string& path = mask.paths(i);
    string camelcase_path;
    if (!SnakeCaseToCamelCase(path, &camelcase_path)) {
      return false;
    }
    if (i > 0) {
      out->push_back(',');
    }
    out->append(camelcase_path);
  }
  return true;
}

bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) {
  out->Clear();
  std::vector<string> paths = Split(str, ",");
  for (int i = 0; i < paths.size(); ++i) {
    if (paths[i].empty()) continue;
    string snakecase_path;
    if (!CamelCaseToSnakeCase(paths[i], &snakecase_path)) {
      return false;
    }
    out->add_paths(snakecase_path);
  }
  return true;
}

bool FieldMaskUtil::GetFieldDescriptors(
    const Descriptor* descriptor, StringPiece path,
    std::vector<const FieldDescriptor*>* field_descriptors) {
  if (field_descriptors != NULL) {
    field_descriptors->clear();
  }
  std::vector<string> parts = Split(path, ".");
  for (int i = 0; i < parts.size(); ++i) {
    const string& field_name = parts[i];
    if (descriptor == NULL) {
      return false;
    }
    const FieldDescriptor* field = descriptor->FindFieldByName(field_name);
    if (field == NULL) {
      return false;
    }
    if (field_descriptors != NULL) {
      field_descriptors->push_back(field);
    }
    if (!field->is_repeated() &&
        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
      descriptor = field->message_type();
    } else {
      descriptor = NULL;
    }
  }
  return true;
}

void FieldMaskUtil::InternalGetFieldMaskForAllFields(
    const Descriptor* descriptor, FieldMask* out) {
  for (int i = 0; i < descriptor->field_count(); ++i) {
    out->add_paths(descriptor->field(i)->name());
  }
}

namespace {
// A FieldMaskTree represents a FieldMask in a tree structure. For example,
// given a FieldMask "foo.bar,foo.baz,bar.baz", the FieldMaskTree will be:
//
//   [root] -+- foo -+- bar
//           |       |
//           |       +- baz
//           |
//           +- bar --- baz
//
// In the tree, each leaf node represents a field path.
class FieldMaskTree {
 public:
  FieldMaskTree();
  ~FieldMaskTree();

  void MergeFromFieldMask(const FieldMask& mask);
  void MergeToFieldMask(FieldMask* mask);

  // Add a field path into the tree. In a FieldMask, each field path matches
  // the specified field and also all its sub-fields. If the field path to
  // add is a sub-path of an existing field path in the tree (i.e., a leaf
  // node), it means the tree already matches the given path so nothing will
  // be added to the tree. If the path matches an existing non-leaf node in the
  // tree, that non-leaf node will be turned into a leaf node with all its
  // children removed because the path matches all the node's children.
  void AddPath(const string& path);

  // Remove a path from the tree.
  // If the path is a sub-path of an existing field path in the tree, it means
  // we need remove the existing fied path and add all sub-paths except
  // specified path. If the path matches an existing node in the tree, this node
  // will be moved.
  void RemovePath(const string& path, const Descriptor* descriptor);

  // Calculate the intersection part of a field path with this tree and add
  // the intersection field path into out.
  void IntersectPath(const string& path, FieldMaskTree* out);

  // Merge all fields specified by this tree from one message to another.
  void MergeMessage(const Message& source,
                    const FieldMaskUtil::MergeOptions& options,
                    Message* destination) {
    // Do nothing if the tree is empty.
    if (root_.children.empty()) {
      return;
    }
    MergeMessage(&root_, source, options, destination);
  }

  // Add required field path of the message to this tree based on current tree
  // structure. If a message is present in the tree, add the path of its
  // required field to the tree. This is to make sure that after trimming a
  // message with required fields are set, check IsInitialized() will not fail.
  void AddRequiredFieldPath(const Descriptor* descriptor) {
    // Do nothing if the tree is empty.
    if (root_.children.empty()) {
      return;
    }
    AddRequiredFieldPath(&root_, descriptor);
  }

  // Trims all fields not specified by this tree from the given message.
  void TrimMessage(Message* message) {
    // Do nothing if the tree is empty.
    if (root_.children.empty()) {
      return;
    }
    TrimMessage(&root_, message);
  }

 private:
  struct Node {
    Node() {}

    ~Node() { ClearChildren(); }

    void ClearChildren() {
      for (std::map<string, Node*>::iterator it = children.begin();
           it != children.end(); ++it) {
        delete it->second;
      }
      children.clear();
    }

    std::map<string, Node*> children;

   private:
    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
  };

  // Merge a sub-tree to mask. This method adds the field paths represented
  // by all leaf nodes descended from "node" to mask.
  void MergeToFieldMask(const string& prefix, const Node* node, FieldMask* out);

  // Merge all leaf nodes of a sub-tree to another tree.
  void MergeLeafNodesToTree(const string& prefix, const Node* node,
                            FieldMaskTree* out);

  // Merge all fields specified by a sub-tree from one message to another.
  void MergeMessage(const Node* node, const Message& source,
                    const FieldMaskUtil::MergeOptions& options,
                    Message* destination);

  // Add required field path of the message to this tree based on current tree
  // structure. If a message is present in the tree, add the path of its
  // required field to the tree. This is to make sure that after trimming a
  // message with required fields are set, check IsInitialized() will not fail.
  void AddRequiredFieldPath(Node* node, const Descriptor* descriptor);

  // Trims all fields not specified by this sub-tree from the given message.
  void TrimMessage(const Node* node, Message* message);

  Node root_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree);
};

FieldMaskTree::FieldMaskTree() {}

FieldMaskTree::~FieldMaskTree() {}

void FieldMaskTree::MergeFromFieldMask(const FieldMask& mask) {
  for (int i = 0; i < mask.paths_size(); ++i) {
    AddPath(mask.paths(i));
  }
}

void FieldMaskTree::MergeToFieldMask(FieldMask* mask) {
  MergeToFieldMask("", &root_, mask);
}

void FieldMaskTree::MergeToFieldMask(const string& prefix, const Node* node,
                                     FieldMask* out) {
  if (node->children.empty()) {
    if (prefix.empty()) {
      // This is the root node.
      return;
    }
    out->add_paths(prefix);
    return;
  }
  for (std::map<string, Node*>::const_iterator it = node->children.begin();
       it != node->children.end(); ++it) {
    string current_path = prefix.empty() ? it->first : prefix + "." + it->first;
    MergeToFieldMask(current_path, it->second, out);
  }
}

void FieldMaskTree::AddPath(const string& path) {
  std::vector<string> parts = Split(path, ".");
  if (parts.empty()) {
    return;
  }
  bool new_branch = false;
  Node* node = &root_;
  for (int i = 0; i < parts.size(); ++i) {
    if (!new_branch && node != &root_ && node->children.empty()) {
      // Path matches an existing leaf node. This means the path is already
      // coverred by this tree (for example, adding "foo.bar.baz" to a tree
      // which already contains "foo.bar").
      return;
    }
    const string& node_name = parts[i];
    Node*& child = node->children[node_name];
    if (child == NULL) {
      new_branch = true;
      child = new Node();
    }
    node = child;
  }
  if (!node->children.empty()) {
    node->ClearChildren();
  }
}

void FieldMaskTree::RemovePath(const string& path,
                               const Descriptor* descriptor) {
  std::vector<string> parts = Split(path, ".");
  if (parts.empty()) {
    return;
  }
  std::vector<Node*> nodes(parts.size());
  Node* node = &root_;
  const Descriptor* current_descriptor = descriptor;
  Node* new_branch_node = NULL;
  for (int i = 0; i < parts.size(); ++i) {
    nodes[i] = node;
    const FieldDescriptor* field_descriptor =
        current_descriptor->FindFieldByName(parts[i]);
    if (field_descriptor == NULL ||
        (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
         i != parts.size() - 1)) {
      // Invalid path.
      if (new_branch_node != NULL) {
        // If add any new nodes, cleanup.
        new_branch_node->ClearChildren();
      }
      return;
    }

    if (node->children.empty()) {
      if (new_branch_node == NULL) {
        new_branch_node = node;
      }
      for (int i = 0; i < current_descriptor->field_count(); ++i) {
        node->children[current_descriptor->field(i)->name()] = new Node();
      }
    }
    if (ContainsKey(node->children, parts[i])) {
      node = node->children[parts[i]];
      if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
        current_descriptor = field_descriptor->message_type();
      }
    } else {
      // Path does not exist.
      return;
    }
  }
  // Remove path.
  for (int i = parts.size() - 1; i >= 0; i--) {
    delete nodes[i]->children[parts[i]];
    nodes[i]->children.erase(parts[i]);
    if (!nodes[i]->children.empty()) {
      break;
    }
  }
}

void FieldMaskTree::IntersectPath(const string& path, FieldMaskTree* out) {
  std::vector<string> parts = Split(path, ".");
  if (parts.empty()) {
    return;
  }
  const Node* node = &root_;
  for (int i = 0; i < parts.size(); ++i) {
    if (node->children.empty()) {
      if (node != &root_) {
        out->AddPath(path);
      }
      return;
    }
    const string& node_name = parts[i];
    const Node* result = FindPtrOrNull(node->children, node_name);
    if (result == NULL) {
      // No intersection found.
      return;
    }
    node = result;
  }
  // Now we found a matching node with the given path. Add all leaf nodes
  // to out.
  MergeLeafNodesToTree(path, node, out);
}

void FieldMaskTree::MergeLeafNodesToTree(const string& prefix, const Node* node,
                                         FieldMaskTree* out) {
  if (node->children.empty()) {
    out->AddPath(prefix);
  }
  for (std::map<string, Node*>::const_iterator it = node->children.begin();
       it != node->children.end(); ++it) {
    string current_path = prefix.empty() ? it->first : prefix + "." + it->first;
    MergeLeafNodesToTree(current_path, it->second, out);
  }
}

void FieldMaskTree::MergeMessage(const Node* node, const Message& source,
                                 const FieldMaskUtil::MergeOptions& options,
                                 Message* destination) {
  GOOGLE_DCHECK(!node->children.empty());
  const Reflection* source_reflection = source.GetReflection();
  const Reflection* destination_reflection = destination->GetReflection();
  const Descriptor* descriptor = source.GetDescriptor();
  for (std::map<string, Node*>::const_iterator it = node->children.begin();
       it != node->children.end(); ++it) {
    const string& field_name = it->first;
    const Node* child = it->second;
    const FieldDescriptor* field = descriptor->FindFieldByName(field_name);
    if (field == NULL) {
      GOOGLE_LOG(ERROR) << "Cannot find field \"" << field_name << "\" in message "
                 << descriptor->full_name();
      continue;
    }
    if (!child->children.empty()) {
      // Sub-paths are only allowed for singular message fields.
      if (field->is_repeated() ||
          field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
        GOOGLE_LOG(ERROR) << "Field \"" << field_name << "\" in message "
                   << descriptor->full_name()
                   << " is not a singular message field and cannot "
                   << "have sub-fields.";
        continue;
      }
      MergeMessage(child, source_reflection->GetMessage(source, field), options,
                   destination_reflection->MutableMessage(destination, field));
      continue;
    }
    if (!field->is_repeated()) {
      switch (field->cpp_type()) {
#define COPY_VALUE(TYPE, Name)                                              \
  case FieldDescriptor::CPPTYPE_##TYPE: {                                   \
    if (source_reflection->HasField(source, field)) {                       \
      destination_reflection->Set##Name(                                    \
          destination, field, source_reflection->Get##Name(source, field)); \
    } else {                                                                \
      destination_reflection->ClearField(destination, field);               \
    }                                                                       \
    break;                                                                  \
  }
        COPY_VALUE(BOOL, Bool)
        COPY_VALUE(INT32, Int32)
        COPY_VALUE(INT64, Int64)
        COPY_VALUE(UINT32, UInt32)
        COPY_VALUE(UINT64, UInt64)
        COPY_VALUE(FLOAT, Float)
        COPY_VALUE(DOUBLE, Double)
        COPY_VALUE(ENUM, Enum)
        COPY_VALUE(STRING, String)
#undef COPY_VALUE
        case FieldDescriptor::CPPTYPE_MESSAGE: {
          if (options.replace_message_fields()) {
            destination_reflection->ClearField(destination, field);
          }
          if (source_reflection->HasField(source, field)) {
            destination_reflection->MutableMessage(destination, field)
                ->MergeFrom(source_reflection->GetMessage(source, field));
          }
          break;
        }
      }
    } else {
      if (options.replace_repeated_fields()) {
        destination_reflection->ClearField(destination, field);
      }
      switch (field->cpp_type()) {
#define COPY_REPEATED_VALUE(TYPE, Name)                            \
  case FieldDescriptor::CPPTYPE_##TYPE: {                          \
    int size = source_reflection->FieldSize(source, field);        \
    for (int i = 0; i < size; ++i) {                               \
      destination_reflection->Add##Name(                           \
          destination, field,                                      \
          source_reflection->GetRepeated##Name(source, field, i)); \
    }                                                              \
    break;                                                         \
  }
        COPY_REPEATED_VALUE(BOOL, Bool)
        COPY_REPEATED_VALUE(INT32, Int32)
        COPY_REPEATED_VALUE(INT64, Int64)
        COPY_REPEATED_VALUE(UINT32, UInt32)
        COPY_REPEATED_VALUE(UINT64, UInt64)
        COPY_REPEATED_VALUE(FLOAT, Float)
        COPY_REPEATED_VALUE(DOUBLE, Double)
        COPY_REPEATED_VALUE(ENUM, Enum)
        COPY_REPEATED_VALUE(STRING, String)
#undef COPY_REPEATED_VALUE
        case FieldDescriptor::CPPTYPE_MESSAGE: {
          int size = source_reflection->FieldSize(source, field);
          for (int i = 0; i < size; ++i) {
            destination_reflection->AddMessage(destination, field)
                ->MergeFrom(
                    source_reflection->GetRepeatedMessage(source, field, i));
          }
          break;
        }
      }
    }
  }
}

void FieldMaskTree::AddRequiredFieldPath(
    Node* node, const Descriptor* descriptor) {
  const int32 field_count = descriptor->field_count();
  for (int index = 0; index < field_count; ++index) {
    const FieldDescriptor* field = descriptor->field(index);
    if (field->is_required()) {
      const string& node_name = field->name();
      Node*& child = node->children[node_name];
      if (child == NULL) {
        // Add required field path to the tree
        child = new Node();
      } else if (child->children.empty()){
        // If the required field is in the tree and does not have any children,
        // do nothing.
        continue;
      }
      // Add required field in the children to the tree if the field is message.
      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
        AddRequiredFieldPath(child, field->message_type());
      }
    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
      std::map<string, Node*>::const_iterator it =
          node->children.find(field->name());
      if (it != node->children.end()) {
        // Add required fields in the children to the
        // tree if the field is a message and present in the tree.
        Node* child = it->second;
        if (!child->children.empty()) {
          AddRequiredFieldPath(child, field->message_type());
        }
      }
    }
  }
}

void FieldMaskTree::TrimMessage(const Node* node, Message* message) {
  GOOGLE_DCHECK(!node->children.empty());
  const Reflection* reflection = message->GetReflection();
  const Descriptor* descriptor = message->GetDescriptor();
  const int32 field_count = descriptor->field_count();
  for (int index = 0; index < field_count; ++index) {
    const FieldDescriptor* field = descriptor->field(index);
    std::map<string, Node*>::const_iterator it =
        node->children.find(field->name());
    if (it == node->children.end()) {
      reflection->ClearField(message, field);
    } else {
      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
        Node* child = it->second;
        if (!child->children.empty() && reflection->HasField(*message, field)) {
          TrimMessage(child, reflection->MutableMessage(message, field));
        }
      }
    }
  }
}

}  // namespace

void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) {
  FieldMaskTree tree;
  tree.MergeFromFieldMask(mask);
  out->Clear();
  tree.MergeToFieldMask(out);
}

void FieldMaskUtil::Union(const FieldMask& mask1, const FieldMask& mask2,
                          FieldMask* out) {
  FieldMaskTree tree;
  tree.MergeFromFieldMask(mask1);
  tree.MergeFromFieldMask(mask2);
  out->Clear();
  tree.MergeToFieldMask(out);
}

void FieldMaskUtil::Intersect(const FieldMask& mask1, const FieldMask& mask2,
                              FieldMask* out) {
  FieldMaskTree tree, intersection;
  tree.MergeFromFieldMask(mask1);
  for (int i = 0; i < mask2.paths_size(); ++i) {
    tree.IntersectPath(mask2.paths(i), &intersection);
  }
  out->Clear();
  intersection.MergeToFieldMask(out);
}

void FieldMaskUtil::InternalSubtract(const Descriptor* descriptor,
                                     const FieldMask& mask1,
                                     const FieldMask& mask2, FieldMask* out) {
  if (mask1.paths().empty()) {
    out->Clear();
    return;
  }
  FieldMaskTree tree;
  tree.MergeFromFieldMask(mask1);
  for (int i = 0; i < mask2.paths_size(); ++i) {
    tree.RemovePath(mask2.paths(i), descriptor);
  }
  out->Clear();
  tree.MergeToFieldMask(out);
}

bool FieldMaskUtil::IsPathInFieldMask(StringPiece path, const FieldMask& mask) {
  for (int i = 0; i < mask.paths_size(); ++i) {
    const string& mask_path = mask.paths(i);
    if (path == mask_path) {
      return true;
    } else if (mask_path.length() < path.length()) {
      // Also check whether mask.paths(i) is a prefix of path.
      if (path.substr(0, mask_path.length() + 1).compare(mask_path + ".") ==
          0) {
        return true;
      }
    }
  }
  return false;
}

void FieldMaskUtil::MergeMessageTo(const Message& source, const FieldMask& mask,
                                   const MergeOptions& options,
                                   Message* destination) {
  GOOGLE_CHECK(source.GetDescriptor() == destination->GetDescriptor());
  // Build a FieldMaskTree and walk through the tree to merge all specified
  // fields.
  FieldMaskTree tree;
  tree.MergeFromFieldMask(mask);
  tree.MergeMessage(source, options, destination);
}

void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination) {
  // Build a FieldMaskTree and walk through the tree to merge all specified
  // fields.
  FieldMaskTree tree;
  tree.MergeFromFieldMask(mask);
  tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination));
}

void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination,
                                const TrimOptions& options) {
  // Build a FieldMaskTree and walk through the tree to merge all specified
  // fields.
  FieldMaskTree tree;
  tree.MergeFromFieldMask(mask);
  // If keep_required_fields is true, implicitely add required fields of
  // a message present in the tree to prevent from trimming.
  if (options.keep_required_fields()) {
    tree.AddRequiredFieldPath(GOOGLE_CHECK_NOTNULL(destination->GetDescriptor()));
  }
  tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination));
}

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


text:
// Adapted from the patch of kenton@google.com (Kenton Varda)
// See https://github.com/google/protobuf/pull/710 for details.

#ifndef GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__
#define GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__

#include <ostream>

#include <google/protobuf/message_lite.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>

namespace google {
namespace protobuf {
namespace util {

// Write a single size-delimited message from the given stream. Delimited
// format allows a single file or stream to contain multiple messages,
// whereas normally writing multiple non-delimited messages to the same
// stream would cause them to be merged. A delimited message is a varint
// encoding the message size followed by a message of exactly that size.
//
// Note that if you want to *read* a delimited message from a file descriptor
// or istream, you will need to construct an io::FileInputStream or
// io::OstreamInputStream (implementations of io::ZeroCopyStream) and use the
// utility function ParseDelimitedFromZeroCopyStream(). You must then
// continue to use the same ZeroCopyInputStream to read all further data from
// the stream until EOF. This is because these ZeroCopyInputStream
// implementations are buffered: they read a big chunk of data at a time,
// then parse it. As a result, they may read past the end of the delimited
// message. There is no way for them to push the extra data back into the
// underlying source, so instead you must keep using the same stream object.
bool LIBPROTOBUF_EXPORT SerializeDelimitedToFileDescriptor(const MessageLite& message, int file_descriptor);

bool LIBPROTOBUF_EXPORT SerializeDelimitedToOstream(const MessageLite& message, ostream* output);

// Read a single size-delimited message from the given stream. Delimited
// format allows a single file or stream to contain multiple messages,
// whereas normally parsing consumes the entire input. A delimited message
// is a varint encoding the message size followed by a message of exactly
// that size.
//
// If |clean_eof| is not NULL, then it will be set to indicate whether the
// stream ended cleanly. That is, if the stream ends without this method
// having read any data at all from it, then *clean_eof will be set true,
// otherwise it will be set false. Note that these methods return false
// on EOF, but they also return false on other errors, so |clean_eof| is
// needed to distinguish a clean end from errors.
bool LIBPROTOBUF_EXPORT ParseDelimitedFromZeroCopyStream(MessageLite* message, io::ZeroCopyInputStream* input, bool* clean_eof);

bool LIBPROTOBUF_EXPORT ParseDelimitedFromCodedStream(MessageLite* message, io::CodedInputStream* input, bool* clean_eof);

// Write a single size-delimited message from the given stream. Delimited
// format allows a single file or stream to contain multiple messages,
// whereas normally writing multiple non-delimited messages to the same
// stream would cause them to be merged. A delimited message is a varint
// encoding the message size followed by a message of exactly that size.
bool LIBPROTOBUF_EXPORT SerializeDelimitedToZeroCopyStream(const MessageLite& message, io::ZeroCopyOutputStream* output);

bool LIBPROTOBUF_EXPORT SerializeDelimitedToCodedStream(const MessageLite& message, io::CodedOutputStream* output);

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

#endif  // GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_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.

#include <google/protobuf/util/type_resolver_util.h>

#include <google/protobuf/type.pb.h>
#include <google/protobuf/wrappers.pb.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/status.h>

namespace google {
namespace protobuf {
namespace util {
namespace {
using google::protobuf::BoolValue;
using google::protobuf::Enum;
using google::protobuf::EnumValue;
using google::protobuf::Field;
using google::protobuf::Option;
using google::protobuf::Type;

using util::Status;
using util::error::INVALID_ARGUMENT;
using util::error::NOT_FOUND;

class DescriptorPoolTypeResolver : public TypeResolver {
 public:
  DescriptorPoolTypeResolver(const string& url_prefix,
                             const DescriptorPool* pool)
      : url_prefix_(url_prefix), pool_(pool) {}

  Status ResolveMessageType(const string& type_url, Type* type) {
    string type_name;
    Status status = ParseTypeUrl(type_url, &type_name);
    if (!status.ok()) {
      return status;
    }

    const Descriptor* descriptor = pool_->FindMessageTypeByName(type_name);
    if (descriptor == NULL) {
      return Status(NOT_FOUND, "Invalid type URL, unknown type: " + type_name);
    }
    ConvertDescriptor(descriptor, type);
    return Status();
  }

  Status ResolveEnumType(const string& type_url, Enum* enum_type) {
    string type_name;
    Status status = ParseTypeUrl(type_url, &type_name);
    if (!status.ok()) {
      return status;
    }

    const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name);
    if (descriptor == NULL) {
      return Status(NOT_FOUND, "Invalid type URL, unknown type: " + type_name);
    }
    ConvertEnumDescriptor(descriptor, enum_type);
    return Status();
  }

 private:
  void ConvertDescriptor(const Descriptor* descriptor, Type* type) {
    type->Clear();
    type->set_name(descriptor->full_name());
    for (int i = 0; i < descriptor->field_count(); ++i) {
      const FieldDescriptor* field = descriptor->field(i);
      if (field->type() == FieldDescriptor::TYPE_GROUP) {
        // Group fields cannot be represented with Type. We discard them.
        continue;
      }
      ConvertFieldDescriptor(descriptor->field(i), type->add_fields());
    }
    for (int i = 0; i < descriptor->oneof_decl_count(); ++i) {
      type->add_oneofs(descriptor->oneof_decl(i)->name());
    }
    type->mutable_source_context()->set_file_name(descriptor->file()->name());
    ConvertMessageOptions(descriptor->options(), type->mutable_options());
  }

  void ConvertMessageOptions(const MessageOptions& options,
                             RepeatedPtrField<Option>* output) {
    if (options.map_entry()) {
      Option* option = output->Add();
      option->set_name("map_entry");
      BoolValue value;
      value.set_value(true);
      option->mutable_value()->PackFrom(value);
    }

    // TODO(xiaofeng): Set other "options"?
  }

  void ConvertFieldDescriptor(const FieldDescriptor* descriptor, Field* field) {
    field->set_kind(static_cast<Field::Kind>(descriptor->type()));
    switch (descriptor->label()) {
      case FieldDescriptor::LABEL_OPTIONAL:
        field->set_cardinality(Field::CARDINALITY_OPTIONAL);
        break;
      case FieldDescriptor::LABEL_REPEATED:
        field->set_cardinality(Field::CARDINALITY_REPEATED);
        break;
      case FieldDescriptor::LABEL_REQUIRED:
        field->set_cardinality(Field::CARDINALITY_REQUIRED);
        break;
    }
    field->set_number(descriptor->number());
    field->set_name(descriptor->name());
    field->set_json_name(descriptor->json_name());
    if (descriptor->has_default_value()) {
      field->set_default_value(DefaultValueAsString(descriptor));
    }
    if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
      field->set_type_url(GetTypeUrl(descriptor->message_type()));
    } else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
      field->set_type_url(GetTypeUrl(descriptor->enum_type()));
    }
    if (descriptor->containing_oneof() != NULL) {
      field->set_oneof_index(descriptor->containing_oneof()->index() + 1);
    }
    if (descriptor->is_packed()) {
      field->set_packed(true);
    }

    // TODO(xiaofeng): Set other field "options"?
  }

  void ConvertEnumDescriptor(const EnumDescriptor* descriptor,
                             Enum* enum_type) {
    enum_type->Clear();
    enum_type->set_name(descriptor->full_name());
    enum_type->mutable_source_context()->set_file_name(
        descriptor->file()->name());
    for (int i = 0; i < descriptor->value_count(); ++i) {
      const EnumValueDescriptor* value_descriptor = descriptor->value(i);
      EnumValue* value = enum_type->mutable_enumvalue()->Add();
      value->set_name(value_descriptor->name());
      value->set_number(value_descriptor->number());

      // TODO(xiaofeng): Set EnumValue options.
    }
    // TODO(xiaofeng): Set Enum "options".
  }

  string GetTypeUrl(const Descriptor* descriptor) {
    return url_prefix_ + "/" + descriptor->full_name();
  }

  string GetTypeUrl(const EnumDescriptor* descriptor) {
    return url_prefix_ + "/" + descriptor->full_name();
  }

  Status ParseTypeUrl(const string& type_url, string* type_name) {
    if (type_url.substr(0, url_prefix_.size() + 1) != url_prefix_ + "/") {
      return Status(INVALID_ARGUMENT,
                    StrCat("Invalid type URL, type URLs must be of the form '",
                           url_prefix_, "/<typename>', got: ", type_url));
    }
    *type_name = type_url.substr(url_prefix_.size() + 1);
    return Status();
  }

  string DefaultValueAsString(const FieldDescriptor* descriptor) {
    switch (descriptor->cpp_type()) {
      case FieldDescriptor::CPPTYPE_INT32:
        return SimpleItoa(descriptor->default_value_int32());
        break;
      case FieldDescriptor::CPPTYPE_INT64:
        return SimpleItoa(descriptor->default_value_int64());
        break;
      case FieldDescriptor::CPPTYPE_UINT32:
        return SimpleItoa(descriptor->default_value_uint32());
        break;
      case FieldDescriptor::CPPTYPE_UINT64:
        return SimpleItoa(descriptor->default_value_uint64());
        break;
      case FieldDescriptor::CPPTYPE_FLOAT:
        return SimpleFtoa(descriptor->default_value_float());
        break;
      case FieldDescriptor::CPPTYPE_DOUBLE:
        return SimpleDtoa(descriptor->default_value_double());
        break;
      case FieldDescriptor::CPPTYPE_BOOL:
        return descriptor->default_value_bool() ? "true" : "false";
        break;
      case FieldDescriptor::CPPTYPE_STRING:
        if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
          return CEscape(descriptor->default_value_string());
        } else {
          return descriptor->default_value_string();
        }
        break;
      case FieldDescriptor::CPPTYPE_ENUM:
        return descriptor->default_value_enum()->name();
        break;
      case FieldDescriptor::CPPTYPE_MESSAGE:
        GOOGLE_LOG(DFATAL) << "Messages can't have default values!";
        break;
    }
    return "";
  }

  string url_prefix_;
  const DescriptorPool* pool_;
};

}  // namespace

TypeResolver* NewTypeResolverForDescriptorPool(const string& url_prefix,
                                               const DescriptorPool* pool) {
  return new DescriptorPoolTypeResolver(url_prefix, pool);
}

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

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.
//
// This file contains messages for testing repeated field comparison

syntax = "proto2";
package protobuf_unittest;

option optimize_for = SPEED;

message TestField {
  optional int32 a = 3;
  optional int32 b = 4;
  optional int32 c = 1;
  repeated int32 rc = 2;
  optional TestField m = 5;

  extend TestDiffMessage {
    optional TestField tf = 100;
  }
}

message TestDiffMessage {
  repeated group Item = 1 {
    optional int32  a  =  2;     // Test basic repeated field comparison.
    optional string b  =  4;     // Test basic repeated field comparison.
    repeated int32  ra =  3;     // Test SetOfSet Comparison.
    repeated string rb =  5;     // Test TreatAsMap when key is repeated
    optional TestField m  = 6;   // Test TreatAsMap when key is a message
    repeated TestField rm = 7;   // Test TreatAsMap when key is a repeated
                                 // message
  }

  optional int32  v  = 13 [deprecated = true];
  optional string w  = 14;
  optional TestField m  = 15;
  repeated int32  rv = 11;       // Test for combinations
  repeated string rw = 10;       // Test for combinations
  repeated TestField rm = 12 [deprecated = true];    // Test for combinations

  extensions 100 to 199;
}


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.

// Author: ksroka@google.com (Krzysztof Sroka)

#include <google/protobuf/util/field_comparator.h>

#include <string>

#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/mathlimits.h>
#include <google/protobuf/stubs/mathutil.h>

namespace google {
namespace protobuf {
namespace util {

FieldComparator::FieldComparator() {}
FieldComparator::~FieldComparator() {}

DefaultFieldComparator::DefaultFieldComparator()
    : float_comparison_(EXACT),
      treat_nan_as_equal_(false),
      has_default_tolerance_(false) {
}

DefaultFieldComparator::~DefaultFieldComparator() {}

FieldComparator::ComparisonResult DefaultFieldComparator::Compare(
      const google::protobuf::Message& message_1,
      const google::protobuf::Message& message_2,
      const google::protobuf::FieldDescriptor* field,
      int index_1, int index_2,
      const google::protobuf::util::FieldContext* field_context) {
  const Reflection* reflection_1 = message_1.GetReflection();
  const Reflection* reflection_2 = message_2.GetReflection();

  switch (field->cpp_type()) {
#define COMPARE_FIELD(METHOD)                                              \
    if (field->is_repeated()) {                                            \
      return ResultFromBoolean(Compare##METHOD(                            \
          *field,                                                          \
          reflection_1->GetRepeated##METHOD(message_1, field, index_1),    \
          reflection_2->GetRepeated##METHOD(message_2, field, index_2)));  \
    } else {                                                               \
      return ResultFromBoolean(Compare##METHOD(                            \
          *field,                                                          \
          reflection_1->Get##METHOD(message_1, field),                     \
          reflection_2->Get##METHOD(message_2, field)));                   \
    }                                                                      \
    break;  // Make sure no fall-through is introduced.

    case FieldDescriptor::CPPTYPE_BOOL:
      COMPARE_FIELD(Bool);
    case FieldDescriptor::CPPTYPE_DOUBLE:
      COMPARE_FIELD(Double);
    case FieldDescriptor::CPPTYPE_ENUM:
      COMPARE_FIELD(Enum);
    case FieldDescriptor::CPPTYPE_FLOAT:
      COMPARE_FIELD(Float);
    case FieldDescriptor::CPPTYPE_INT32:
      COMPARE_FIELD(Int32);
    case FieldDescriptor::CPPTYPE_INT64:
      COMPARE_FIELD(Int64);
    case FieldDescriptor::CPPTYPE_STRING:
      if (field->is_repeated()) {
        // Allocate scratch strings to store the result if a conversion is
        // needed.
        string scratch1;
        string scratch2;
        return ResultFromBoolean(
            CompareString(*field, reflection_1->GetRepeatedStringReference(
                                      message_1, field, index_1, &scratch1),
                          reflection_2->GetRepeatedStringReference(
                              message_2, field, index_2, &scratch2)));
      } else {
        // Allocate scratch strings to store the result if a conversion is
        // needed.
        string scratch1;
        string scratch2;
        return ResultFromBoolean(CompareString(
            *field,
            reflection_1->GetStringReference(message_1, field, &scratch1),
            reflection_2->GetStringReference(message_2, field, &scratch2)));
      }
      break;
    case FieldDescriptor::CPPTYPE_UINT32:
      COMPARE_FIELD(UInt32);
    case FieldDescriptor::CPPTYPE_UINT64:
      COMPARE_FIELD(UInt64);

#undef COMPARE_FIELD

    case FieldDescriptor::CPPTYPE_MESSAGE:
      return RECURSE;

    default:
      GOOGLE_LOG(FATAL) << "No comparison code for field " << field->full_name()
                 << " of CppType = " << field->cpp_type();
      return DIFFERENT;
  }
}

void DefaultFieldComparator::SetDefaultFractionAndMargin(double fraction,
                                                         double margin) {
  default_tolerance_ = Tolerance(fraction, margin);
  has_default_tolerance_ = true;
}

void DefaultFieldComparator::SetFractionAndMargin(const FieldDescriptor* field,
                                                  double fraction,
                                                  double margin) {
  GOOGLE_CHECK(FieldDescriptor::CPPTYPE_FLOAT == field->cpp_type() ||
        FieldDescriptor::CPPTYPE_DOUBLE == field->cpp_type())
      << "Field has to be float or double type. Field name is: "
      << field->full_name();
  map_tolerance_[field] = Tolerance(fraction, margin);
}

bool DefaultFieldComparator::CompareDouble(const FieldDescriptor& field,
                                           double value_1, double value_2) {
  return CompareDoubleOrFloat(field, value_1, value_2);
}

bool DefaultFieldComparator::CompareEnum(const FieldDescriptor& field,
                                         const EnumValueDescriptor* value_1,
                                         const EnumValueDescriptor* value_2) {
  return value_1->number() == value_2->number();
}

bool DefaultFieldComparator::CompareFloat(const FieldDescriptor& field,
                                          float value_1, float value_2) {
  return CompareDoubleOrFloat(field, value_1, value_2);
}

template<typename T>
bool DefaultFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field,
                                                  T value_1, T value_2) {
  if (value_1 == value_2) {
    // Covers +inf and -inf (which are not within margin or fraction of
    // themselves), and is a shortcut for finite values.
    return true;
  } else if (float_comparison_ == EXACT) {
    if (treat_nan_as_equal_ &&
        MathLimits<T>::IsNaN(value_1) && MathLimits<T>::IsNaN(value_2)) {
      return true;
    }
    return false;
  } else {
    if (treat_nan_as_equal_ &&
        MathLimits<T>::IsNaN(value_1) && MathLimits<T>::IsNaN(value_2)) {
      return true;
    }
    // float_comparison_ == APPROXIMATE covers two use cases.
    Tolerance* tolerance = FindOrNull(map_tolerance_, &field);
    if (tolerance == NULL && has_default_tolerance_) {
      tolerance = &default_tolerance_;
    }
    if (tolerance == NULL) {
      return MathUtil::AlmostEquals(value_1, value_2);
    } else {
      // Use user-provided fraction and margin. Since they are stored as
      // doubles, we explicitly cast them to types of values provided. This
      // is very likely to fail if provided values are not numeric.
      return MathUtil::WithinFractionOrMargin(
          value_1, value_2, static_cast<T>(tolerance->fraction),
          static_cast<T>(tolerance->margin));
    }
  }
}

FieldComparator::ComparisonResult DefaultFieldComparator::ResultFromBoolean(
    bool boolean_result) const {
  return boolean_result ? FieldComparator::SAME : FieldComparator::DIFFERENT;
}

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

#include <google/protobuf/util/json_util.h>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/util/internal/default_value_objectwriter.h>
#include <google/protobuf/util/internal/error_listener.h>
#include <google/protobuf/util/internal/json_objectwriter.h>
#include <google/protobuf/util/internal/json_stream_parser.h>
#include <google/protobuf/util/internal/protostream_objectsource.h>
#include <google/protobuf/util/internal/protostream_objectwriter.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/util/type_resolver_util.h>
#include <google/protobuf/stubs/bytestream.h>
#include <google/protobuf/stubs/status_macros.h>

namespace google {
namespace protobuf {
namespace util {

namespace internal {
ZeroCopyStreamByteSink::~ZeroCopyStreamByteSink() {
  stream_->BackUp(buffer_size_);
}

void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) {
  while (true) {
    if (len <= buffer_size_) {
      memcpy(buffer_, bytes, len);
      buffer_ = static_cast<char*>(buffer_) + len;
      buffer_size_ -= len;
      return;
    }
    if (buffer_size_ > 0) {
      memcpy(buffer_, bytes, buffer_size_);
      bytes += buffer_size_;
      len -= buffer_size_;
    }
    if (!stream_->Next(&buffer_, &buffer_size_)) {
      // There isn't a way for ByteSink to report errors.
      buffer_size_ = 0;
      return;
    }
  }
}
}  // namespace internal

util::Status BinaryToJsonStream(TypeResolver* resolver,
                                  const string& type_url,
                                  io::ZeroCopyInputStream* binary_input,
                                  io::ZeroCopyOutputStream* json_output,
                                  const JsonPrintOptions& options) {
  io::CodedInputStream in_stream(binary_input);
  google::protobuf::Type type;
  RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
  converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type);
  proto_source.set_use_ints_for_enums(options.always_print_enums_as_ints);
  proto_source.set_preserve_proto_field_names(
      options.preserve_proto_field_names);
  io::CodedOutputStream out_stream(json_output);
  converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "",
                                          &out_stream);
  if (options.always_print_primitive_fields) {
    converter::DefaultValueObjectWriter default_value_writer(
        resolver, type, &json_writer);
    default_value_writer.set_preserve_proto_field_names(
        options.preserve_proto_field_names);
    return proto_source.WriteTo(&default_value_writer);
  } else {
    return proto_source.WriteTo(&json_writer);
  }
}

util::Status BinaryToJsonString(TypeResolver* resolver,
                                  const string& type_url,
                                  const string& binary_input,
                                  string* json_output,
                                  const JsonPrintOptions& options) {
  io::ArrayInputStream input_stream(binary_input.data(), binary_input.size());
  io::StringOutputStream output_stream(json_output);
  return BinaryToJsonStream(resolver, type_url, &input_stream, &output_stream,
                            options);
}

namespace {
class StatusErrorListener : public converter::ErrorListener {
 public:
  StatusErrorListener() {}
  virtual ~StatusErrorListener() {}

  util::Status GetStatus() { return status_; }

  virtual void InvalidName(const converter::LocationTrackerInterface& loc,
                           StringPiece unknown_name, StringPiece message) {
    status_ = util::Status(util::error::INVALID_ARGUMENT,
                             loc.ToString() + ": " + message.ToString());
  }

  virtual void InvalidValue(const converter::LocationTrackerInterface& loc,
                            StringPiece type_name, StringPiece value) {
    status_ =
        util::Status(util::error::INVALID_ARGUMENT,
                       loc.ToString() + ": invalid value " + value.ToString() +
                           " for type " + type_name.ToString());
  }

  virtual void MissingField(const converter::LocationTrackerInterface& loc,
                            StringPiece missing_name) {
    status_ = util::Status(
        util::error::INVALID_ARGUMENT,
        loc.ToString() + ": missing field " + missing_name.ToString());
  }

 private:
  util::Status status_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StatusErrorListener);
};
}  // namespace

util::Status JsonToBinaryStream(TypeResolver* resolver,
                                  const string& type_url,
                                  io::ZeroCopyInputStream* json_input,
                                  io::ZeroCopyOutputStream* binary_output,
                                  const JsonParseOptions& options) {
  google::protobuf::Type type;
  RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
  internal::ZeroCopyStreamByteSink sink(binary_output);
  StatusErrorListener listener;
  converter::ProtoStreamObjectWriter::Options proto_writer_options;
  proto_writer_options.ignore_unknown_fields = options.ignore_unknown_fields;
  converter::ProtoStreamObjectWriter proto_writer(resolver, type, &sink,
                                                  &listener,
                                                  proto_writer_options);

  converter::JsonStreamParser parser(&proto_writer);
  const void* buffer;
  int length;
  while (json_input->Next(&buffer, &length)) {
    if (length == 0) continue;
    RETURN_IF_ERROR(
        parser.Parse(StringPiece(static_cast<const char*>(buffer), length)));
  }
  RETURN_IF_ERROR(parser.FinishParse());

  return listener.GetStatus();
}

util::Status JsonToBinaryString(TypeResolver* resolver,
                                  const string& type_url,
                                  const string& json_input,
                                  string* binary_output,
                                  const JsonParseOptions& options) {
  io::ArrayInputStream input_stream(json_input.data(), json_input.size());
  io::StringOutputStream output_stream(binary_output);
  return JsonToBinaryStream(
      resolver, type_url, &input_stream, &output_stream, options);
}

namespace {
const char* kTypeUrlPrefix = "type.googleapis.com";
TypeResolver* generated_type_resolver_ = NULL;
GOOGLE_PROTOBUF_DECLARE_ONCE(generated_type_resolver_init_);

string GetTypeUrl(const Message& message) {
  return string(kTypeUrlPrefix) + "/" + message.GetDescriptor()->full_name();
}

void DeleteGeneratedTypeResolver() { delete generated_type_resolver_; }

void InitGeneratedTypeResolver() {
  generated_type_resolver_ = NewTypeResolverForDescriptorPool(
      kTypeUrlPrefix, DescriptorPool::generated_pool());
  ::google::protobuf::internal::OnShutdown(&DeleteGeneratedTypeResolver);
}

TypeResolver* GetGeneratedTypeResolver() {
  ::google::protobuf::GoogleOnceInit(&generated_type_resolver_init_, &InitGeneratedTypeResolver);
  return generated_type_resolver_;
}
}  // namespace

util::Status MessageToJsonString(const Message& message, string* output,
                                   const JsonOptions& options) {
  const DescriptorPool* pool = message.GetDescriptor()->file()->pool();
  TypeResolver* resolver =
      pool == DescriptorPool::generated_pool()
          ? GetGeneratedTypeResolver()
          : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool);
  util::Status result =
      BinaryToJsonString(resolver, GetTypeUrl(message),
                         message.SerializeAsString(), output, options);
  if (pool != DescriptorPool::generated_pool()) {
    delete resolver;
  }
  return result;
}

util::Status JsonStringToMessage(const string& input, Message* message,
                                   const JsonParseOptions& options) {
  const DescriptorPool* pool = message->GetDescriptor()->file()->pool();
  TypeResolver* resolver =
      pool == DescriptorPool::generated_pool()
          ? GetGeneratedTypeResolver()
          : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool);
  string binary;
  util::Status result = JsonToBinaryString(
      resolver, GetTypeUrl(*message), input, &binary, options);
  if (result.ok() && !message->ParseFromString(binary)) {
    result =
        util::Status(util::error::INVALID_ARGUMENT,
                       "JSON transcoder produced invalid protobuf output.");
  }
  if (pool != DescriptorPool::generated_pool()) {
    delete resolver;
  }
  return result;
}

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

// This file exists solely to document the google::protobuf::util namespace.
// It is not compiled into anything, but it may be read by an automated
// documentation generator.

namespace google {

namespace protobuf {

// Utility classes.
//
// This package contains various utilities for message comprasion, JSON
// conversion, well known types, etc.
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.

// Defines utilities for the TypeResolver.

#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__

#include <string>

#include <google/protobuf/stubs/common.h>
namespace google {
namespace protobuf {
class DescriptorPool;
namespace util {
class TypeResolver;

// Creates a TypeResolver that serves type information in the given descriptor
// pool. Caller takes ownership of the returned TypeResolver.
LIBPROTOBUF_EXPORT TypeResolver* NewTypeResolverForDescriptorPool(
    const string& url_prefix, const DescriptorPool* pool);

}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_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/time_util.h>

#include <ctime>

#include <google/protobuf/timestamp.pb.h>
#include <google/protobuf/duration.pb.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>

namespace google {
namespace protobuf {
namespace util {

using google::protobuf::Timestamp;
using google::protobuf::Duration;

namespace {

TEST(TimeUtilTest, TimestampStringFormat) {
  Timestamp begin, end;
  EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
  EXPECT_EQ(TimeUtil::kTimestampMinSeconds, begin.seconds());
  EXPECT_EQ(0, begin.nanos());
  EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
  EXPECT_EQ(TimeUtil::kTimestampMaxSeconds, end.seconds());
  EXPECT_EQ(999999999, end.nanos());
  EXPECT_EQ("0001-01-01T00:00:00Z", TimeUtil::ToString(begin));
  EXPECT_EQ("9999-12-31T23:59:59.999999999Z", TimeUtil::ToString(end));

  // Test negative timestamps.
  Timestamp time = TimeUtil::NanosecondsToTimestamp(-1);
  EXPECT_EQ(-1, time.seconds());
  // Timestamp's nano part is always non-negative.
  EXPECT_EQ(999999999, time.nanos());
  EXPECT_EQ("1969-12-31T23:59:59.999999999Z", TimeUtil::ToString(time));

  // Generated output should contain 3, 6, or 9 fractional digits.
  EXPECT_EQ("1970-01-01T00:00:00Z",
            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(0)));
  EXPECT_EQ("1970-01-01T00:00:00.010Z",
            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(10000000)));
  EXPECT_EQ("1970-01-01T00:00:00.000010Z",
            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(10000)));
  EXPECT_EQ("1970-01-01T00:00:00.000000010Z",
            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(10)));

  // Parsing accepts an fractional digits as long as they fit into nano
  // precision.
  EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00.1Z", &time));
  EXPECT_EQ(100000000, TimeUtil::TimestampToNanoseconds(time));
  EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00.0001Z", &time));
  EXPECT_EQ(100000, TimeUtil::TimestampToNanoseconds(time));
  EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00.0000001Z", &time));
  EXPECT_EQ(100, TimeUtil::TimestampToNanoseconds(time));

  // Also accpets offsets.
  EXPECT_TRUE(TimeUtil::FromString("1970-01-01T00:00:00-08:00", &time));
  EXPECT_EQ(8 * 3600, TimeUtil::TimestampToSeconds(time));
}

TEST(TimeUtilTest, DurationStringFormat) {
  Timestamp begin, end;
  EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
  EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));

  EXPECT_EQ("315537897599.999999999s", TimeUtil::ToString(end - begin));
  EXPECT_EQ(999999999, (end - begin).nanos());
  EXPECT_EQ("-315537897599.999999999s", TimeUtil::ToString(begin - end));
  EXPECT_EQ(-999999999, (begin - end).nanos());

  // Generated output should contain 3, 6, or 9 fractional digits.
  EXPECT_EQ("1s", TimeUtil::ToString(TimeUtil::SecondsToDuration(1)));
  EXPECT_EQ("0.010s", TimeUtil::ToString(TimeUtil::MillisecondsToDuration(10)));
  EXPECT_EQ("0.000010s",
            TimeUtil::ToString(TimeUtil::MicrosecondsToDuration(10)));
  EXPECT_EQ("0.000000010s",
            TimeUtil::ToString(TimeUtil::NanosecondsToDuration(10)));

  // Parsing accepts an fractional digits as long as they fit into nano
  // precision.
  Duration d;
  EXPECT_TRUE(TimeUtil::FromString("0.1s", &d));
  EXPECT_EQ(100, TimeUtil::DurationToMilliseconds(d));
  EXPECT_TRUE(TimeUtil::FromString("0.0001s", &d));
  EXPECT_EQ(100, TimeUtil::DurationToMicroseconds(d));
  EXPECT_TRUE(TimeUtil::FromString("0.0000001s", &d));
  EXPECT_EQ(100, TimeUtil::DurationToNanoseconds(d));

  // Duration must support range from -315,576,000,000s to +315576000000s
  // which includes negative values.
  EXPECT_TRUE(TimeUtil::FromString("315576000000.999999999s", &d));
  EXPECT_EQ(315576000000LL, d.seconds());
  EXPECT_EQ(999999999, d.nanos());
  EXPECT_TRUE(TimeUtil::FromString("-315576000000.999999999s", &d));
  EXPECT_EQ(-315576000000LL, d.seconds());
  EXPECT_EQ(-999999999, d.nanos());
}

TEST(TimeUtilTest, GetEpoch) {
  EXPECT_EQ(0, TimeUtil::TimestampToNanoseconds(TimeUtil::GetEpoch()));
}

TEST(TimeUtilTest, DurationIntegerConversion) {
  EXPECT_EQ("0.000000001s",
            TimeUtil::ToString(TimeUtil::NanosecondsToDuration(1)));
  EXPECT_EQ("-0.000000001s",
            TimeUtil::ToString(TimeUtil::NanosecondsToDuration(-1)));
  EXPECT_EQ("0.000001s",
            TimeUtil::ToString(TimeUtil::MicrosecondsToDuration(1)));
  EXPECT_EQ("-0.000001s",
            TimeUtil::ToString(TimeUtil::MicrosecondsToDuration(-1)));
  EXPECT_EQ("0.001s", TimeUtil::ToString(TimeUtil::MillisecondsToDuration(1)));
  EXPECT_EQ("-0.001s",
            TimeUtil::ToString(TimeUtil::MillisecondsToDuration(-1)));
  EXPECT_EQ("1s", TimeUtil::ToString(TimeUtil::SecondsToDuration(1)));
  EXPECT_EQ("-1s", TimeUtil::ToString(TimeUtil::SecondsToDuration(-1)));
  EXPECT_EQ("60s", TimeUtil::ToString(TimeUtil::MinutesToDuration(1)));
  EXPECT_EQ("-60s", TimeUtil::ToString(TimeUtil::MinutesToDuration(-1)));
  EXPECT_EQ("3600s", TimeUtil::ToString(TimeUtil::HoursToDuration(1)));
  EXPECT_EQ("-3600s", TimeUtil::ToString(TimeUtil::HoursToDuration(-1)));

  EXPECT_EQ(
      1, TimeUtil::DurationToNanoseconds(TimeUtil::NanosecondsToDuration(1)));
  EXPECT_EQ(
      -1, TimeUtil::DurationToNanoseconds(TimeUtil::NanosecondsToDuration(-1)));
  EXPECT_EQ(
      1, TimeUtil::DurationToMicroseconds(TimeUtil::MicrosecondsToDuration(1)));
  EXPECT_EQ(-1, TimeUtil::DurationToMicroseconds(
                    TimeUtil::MicrosecondsToDuration(-1)));
  EXPECT_EQ(
      1, TimeUtil::DurationToMilliseconds(TimeUtil::MillisecondsToDuration(1)));
  EXPECT_EQ(-1, TimeUtil::DurationToMilliseconds(
                    TimeUtil::MillisecondsToDuration(-1)));
  EXPECT_EQ(1, TimeUtil::DurationToSeconds(TimeUtil::SecondsToDuration(1)));
  EXPECT_EQ(-1, TimeUtil::DurationToSeconds(TimeUtil::SecondsToDuration(-1)));
  EXPECT_EQ(1, TimeUtil::DurationToMinutes(TimeUtil::MinutesToDuration(1)));
  EXPECT_EQ(-1, TimeUtil::DurationToMinutes(TimeUtil::MinutesToDuration(-1)));
  EXPECT_EQ(1, TimeUtil::DurationToHours(TimeUtil::HoursToDuration(1)));
  EXPECT_EQ(-1, TimeUtil::DurationToHours(TimeUtil::HoursToDuration(-1)));

  // Test truncation behavior.
  EXPECT_EQ(1, TimeUtil::DurationToMicroseconds(
                   TimeUtil::NanosecondsToDuration(1999)));
  // For negative values, Duration will be rounded towards 0.
  EXPECT_EQ(-1, TimeUtil::DurationToMicroseconds(
                    TimeUtil::NanosecondsToDuration(-1999)));
}

TEST(TestUtilTest, TimestampIntegerConversion) {
  EXPECT_EQ("1970-01-01T00:00:00.000000001Z",
            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(1)));
  EXPECT_EQ("1969-12-31T23:59:59.999999999Z",
            TimeUtil::ToString(TimeUtil::NanosecondsToTimestamp(-1)));
  EXPECT_EQ("1970-01-01T00:00:00.000001Z",
            TimeUtil::ToString(TimeUtil::MicrosecondsToTimestamp(1)));
  EXPECT_EQ("1969-12-31T23:59:59.999999Z",
            TimeUtil::ToString(TimeUtil::MicrosecondsToTimestamp(-1)));
  EXPECT_EQ("1970-01-01T00:00:00.001Z",
            TimeUtil::ToString(TimeUtil::MillisecondsToTimestamp(1)));
  EXPECT_EQ("1969-12-31T23:59:59.999Z",
            TimeUtil::ToString(TimeUtil::MillisecondsToTimestamp(-1)));
  EXPECT_EQ("1970-01-01T00:00:01Z",
            TimeUtil::ToString(TimeUtil::SecondsToTimestamp(1)));
  EXPECT_EQ("1969-12-31T23:59:59Z",
            TimeUtil::ToString(TimeUtil::SecondsToTimestamp(-1)));

  EXPECT_EQ(
      1, TimeUtil::TimestampToNanoseconds(TimeUtil::NanosecondsToTimestamp(1)));
  EXPECT_EQ(-1, TimeUtil::TimestampToNanoseconds(
                    TimeUtil::NanosecondsToTimestamp(-1)));
  EXPECT_EQ(1, TimeUtil::TimestampToMicroseconds(
                   TimeUtil::MicrosecondsToTimestamp(1)));
  EXPECT_EQ(-1, TimeUtil::TimestampToMicroseconds(
                    TimeUtil::MicrosecondsToTimestamp(-1)));
  EXPECT_EQ(1, TimeUtil::TimestampToMilliseconds(
                   TimeUtil::MillisecondsToTimestamp(1)));
  EXPECT_EQ(-1, TimeUtil::TimestampToMilliseconds(
                    TimeUtil::MillisecondsToTimestamp(-1)));
  EXPECT_EQ(1, TimeUtil::TimestampToSeconds(TimeUtil::SecondsToTimestamp(1)));
  EXPECT_EQ(-1, TimeUtil::TimestampToSeconds(TimeUtil::SecondsToTimestamp(-1)));

  // Test truncation behavior.
  EXPECT_EQ(1, TimeUtil::TimestampToMicroseconds(
                   TimeUtil::NanosecondsToTimestamp(1999)));
  // For negative values, Timestamp will be rounded down.
  // For example, "1969-12-31T23:59:59.5Z" (i.e., -0.5s) rounded to seconds
  // will be "1969-12-31T23:59:59Z" (i.e., -1s) rather than
  // "1970-01-01T00:00:00Z" (i.e., 0s).
  EXPECT_EQ(-2, TimeUtil::TimestampToMicroseconds(
                    TimeUtil::NanosecondsToTimestamp(-1999)));
}

TEST(TimeUtilTest, TimeTConversion) {
  time_t value = time(NULL);
  EXPECT_EQ(value,
            TimeUtil::TimestampToTimeT(TimeUtil::TimeTToTimestamp(value)));
  EXPECT_EQ(
      1, TimeUtil::TimestampToTimeT(TimeUtil::MillisecondsToTimestamp(1999)));
}

TEST(TimeUtilTest, TimevalConversion) {
  timeval value = TimeUtil::TimestampToTimeval(
      TimeUtil::NanosecondsToTimestamp(1999999999));
  EXPECT_EQ(1, value.tv_sec);
  EXPECT_EQ(999999, value.tv_usec);
  value = TimeUtil::TimestampToTimeval(
      TimeUtil::NanosecondsToTimestamp(-1999999999));
  EXPECT_EQ(-2, value.tv_sec);
  EXPECT_EQ(0, value.tv_usec);

  value =
      TimeUtil::DurationToTimeval(TimeUtil::NanosecondsToDuration(1999999999));
  EXPECT_EQ(1, value.tv_sec);
  EXPECT_EQ(999999, value.tv_usec);
  value =
      TimeUtil::DurationToTimeval(TimeUtil::NanosecondsToDuration(-1999999999));
  EXPECT_EQ(-2, value.tv_sec);
  EXPECT_EQ(1, value.tv_usec);
}

TEST(TimeUtilTest, DurationOperators) {
  Duration one_second = TimeUtil::SecondsToDuration(1);
  Duration one_nano = TimeUtil::NanosecondsToDuration(1);

  // Test +/-
  Duration a = one_second;
  a += one_second;
  a -= one_nano;
  EXPECT_EQ("1.999999999s", TimeUtil::ToString(a));
  Duration b = -a;
  EXPECT_EQ("-1.999999999s", TimeUtil::ToString(b));
  EXPECT_EQ("3.999999998s", TimeUtil::ToString(a + a));
  EXPECT_EQ("0s", TimeUtil::ToString(a + b));
  EXPECT_EQ("0s", TimeUtil::ToString(b + a));
  EXPECT_EQ("-3.999999998s", TimeUtil::ToString(b + b));
  EXPECT_EQ("3.999999998s", TimeUtil::ToString(a - b));
  EXPECT_EQ("0s", TimeUtil::ToString(a - a));
  EXPECT_EQ("0s", TimeUtil::ToString(b - b));
  EXPECT_EQ("-3.999999998s", TimeUtil::ToString(b - a));

  // Test *
  EXPECT_EQ(a + a, a * 2);
  EXPECT_EQ(b + b, a * (-2));
  EXPECT_EQ(b + b, b * 2);
  EXPECT_EQ(a + a, b * (-2));
  EXPECT_EQ("0.999999999s", TimeUtil::ToString(a * 0.5));
  EXPECT_EQ("-0.999999999s", TimeUtil::ToString(b * 0.5));
  // Multiplication should not overflow if the result fits into the supported
  // range of Duration (intermediate result may be larger than int64).
  EXPECT_EQ("315575999684.424s",
            TimeUtil::ToString((one_second - one_nano) * 315576000000LL));
  EXPECT_EQ("-315575999684.424s",
            TimeUtil::ToString((one_nano - one_second) * 315576000000LL));
  EXPECT_EQ("-315575999684.424s",
            TimeUtil::ToString((one_second - one_nano) * (-315576000000LL)));

  // Test / and %
  EXPECT_EQ("0.999999999s", TimeUtil::ToString(a / 2));
  EXPECT_EQ("-0.999999999s", TimeUtil::ToString(b / 2));
  Duration large = TimeUtil::SecondsToDuration(315576000000LL) - one_nano;
  // We have to handle division with values beyond 64 bits.
  EXPECT_EQ("0.999999999s", TimeUtil::ToString(large / 315576000000LL));
  EXPECT_EQ("-0.999999999s", TimeUtil::ToString((-large) / 315576000000LL));
  EXPECT_EQ("-0.999999999s", TimeUtil::ToString(large / (-315576000000LL)));
  Duration large2 = large + one_nano;
  EXPECT_EQ(large, large % large2);
  EXPECT_EQ(-large, (-large) % large2);
  EXPECT_EQ(large, large % (-large2));
  EXPECT_EQ(one_nano, large2 % large);
  EXPECT_EQ(-one_nano, (-large2) % large);
  EXPECT_EQ(one_nano, large2 % (-large));
  // Some corner cases about negative values.
  //
  // (-5) / 2 = -2, remainder = -1
  // (-5) / (-2) = 2, remainder = -1
  a = TimeUtil::NanosecondsToDuration(-5);
  EXPECT_EQ(TimeUtil::NanosecondsToDuration(-2), a / 2);
  EXPECT_EQ(TimeUtil::NanosecondsToDuration(2), a / (-2));
  b = TimeUtil::NanosecondsToDuration(2);
  EXPECT_EQ(-2, a / b);
  EXPECT_EQ(TimeUtil::NanosecondsToDuration(-1), a % b);
  EXPECT_EQ(2, a / (-b));
  EXPECT_EQ(TimeUtil::NanosecondsToDuration(-1), a % (-b));

  // Test relational operators.
  EXPECT_TRUE(one_nano < one_second);
  EXPECT_FALSE(one_second < one_second);
  EXPECT_FALSE(one_second < one_nano);
  EXPECT_FALSE(-one_nano < -one_second);
  EXPECT_FALSE(-one_second < -one_second);
  EXPECT_TRUE(-one_second < -one_nano);
  EXPECT_TRUE(-one_nano < one_nano);
  EXPECT_FALSE(one_nano < -one_nano);

  EXPECT_FALSE(one_nano > one_second);
  EXPECT_FALSE(one_nano > one_nano);
  EXPECT_TRUE(one_second > one_nano);

  EXPECT_FALSE(one_nano >= one_second);
  EXPECT_TRUE(one_nano >= one_nano);
  EXPECT_TRUE(one_second >= one_nano);

  EXPECT_TRUE(one_nano <= one_second);
  EXPECT_TRUE(one_nano <= one_nano);
  EXPECT_FALSE(one_second <= one_nano);

  EXPECT_TRUE(one_nano == one_nano);
  EXPECT_FALSE(one_nano == one_second);

  EXPECT_FALSE(one_nano != one_nano);
  EXPECT_TRUE(one_nano != one_second);
}

TEST(TimeUtilTest, TimestampOperators) {
  Timestamp begin, end;
  EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
  EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
  Duration d = end - begin;
  EXPECT_TRUE(end == begin + d);
  EXPECT_TRUE(end == d + begin);
  EXPECT_TRUE(begin == end - d);

  // Test relational operators
  Timestamp t1 = begin + d / 4;
  Timestamp t2 = end - d / 4;
  EXPECT_TRUE(t1 < t2);
  EXPECT_FALSE(t1 < t1);
  EXPECT_FALSE(t2 < t1);
  EXPECT_FALSE(t1 > t2);
  EXPECT_FALSE(t1 > t1);
  EXPECT_TRUE(t2 > t1);
  EXPECT_FALSE(t1 >= t2);
  EXPECT_TRUE(t1 >= t1);
  EXPECT_TRUE(t2 >= t1);
  EXPECT_TRUE(t1 <= t2);
  EXPECT_TRUE(t1 <= t1);
  EXPECT_FALSE(t2 <= t1);

  EXPECT_FALSE(t1 == t2);
  EXPECT_TRUE(t1 == t1);
  EXPECT_FALSE(t2 == t1);
  EXPECT_TRUE(t1 != t2);
  EXPECT_FALSE(t1 != t1);
  EXPECT_TRUE(t2 != t1);
}

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

syntax = "proto3";

package proto3;

option java_package = "com.google.protobuf.util";
option java_outer_classname = "JsonFormatProto3";

import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/any.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/unittest.proto";

enum EnumType {
  FOO = 0;
  BAR = 1;
}

message MessageType {
  int32 value = 1;
}

message TestMessage {
  bool bool_value = 1;
  int32 int32_value = 2;
  int64 int64_value = 3;
  uint32 uint32_value = 4;
  uint64 uint64_value = 5;
  float float_value = 6;
  double double_value = 7;
  string string_value = 8;
  bytes bytes_value = 9;
  EnumType enum_value = 10;
  MessageType message_value = 11;

  repeated bool repeated_bool_value = 21;
  repeated int32 repeated_int32_value = 22;
  repeated int64 repeated_int64_value = 23;
  repeated uint32 repeated_uint32_value = 24;
  repeated uint64 repeated_uint64_value = 25;
  repeated float repeated_float_value = 26;
  repeated double repeated_double_value = 27;
  repeated string repeated_string_value = 28;
  repeated bytes repeated_bytes_value = 29;
  repeated EnumType repeated_enum_value = 30;
  repeated MessageType repeated_message_value = 31;
}

message TestOneof {
  // In JSON format oneof fields behave mostly the same as optional
  // fields except that:
  //   1. Oneof fields have field presence information and will be
  //      printed if it's set no matter whether it's the default value.
  //   2. Multiple oneof fields in the same oneof cannot appear at the
  //      same time in the input.
  oneof oneof_value {
    int32 oneof_int32_value = 1;
    string oneof_string_value = 2;
    bytes oneof_bytes_value = 3;
    EnumType oneof_enum_value = 4;
    MessageType oneof_message_value = 5;
  }
}

message TestMap {
  map<bool, int32> bool_map = 1;
  map<int32, int32> int32_map = 2;
  map<int64, int32> int64_map = 3;
  map<uint32, int32> uint32_map = 4;
  map<uint64, int32> uint64_map = 5;
  map<string, int32> string_map = 6;
}

message TestNestedMap {
  map<bool, int32> bool_map = 1;
  map<int32, int32> int32_map = 2;
  map<int64, int32> int64_map = 3;
  map<uint32, int32> uint32_map = 4;
  map<uint64, int32> uint64_map = 5;
  map<string, int32> string_map = 6;
  map<string, TestNestedMap> map_map = 7;
}

message TestWrapper {
  google.protobuf.BoolValue bool_value = 1;
  google.protobuf.Int32Value int32_value = 2;
  google.protobuf.Int64Value int64_value = 3;
  google.protobuf.UInt32Value uint32_value = 4;
  google.protobuf.UInt64Value uint64_value = 5;
  google.protobuf.FloatValue float_value = 6;
  google.protobuf.DoubleValue double_value = 7;
  google.protobuf.StringValue string_value = 8;
  google.protobuf.BytesValue bytes_value = 9;

  repeated google.protobuf.BoolValue repeated_bool_value = 11;
  repeated google.protobuf.Int32Value repeated_int32_value = 12;
  repeated google.protobuf.Int64Value repeated_int64_value = 13;
  repeated google.protobuf.UInt32Value repeated_uint32_value = 14;
  repeated google.protobuf.UInt64Value repeated_uint64_value = 15;
  repeated google.protobuf.FloatValue repeated_float_value = 16;
  repeated google.protobuf.DoubleValue repeated_double_value = 17;
  repeated google.protobuf.StringValue repeated_string_value = 18;
  repeated google.protobuf.BytesValue repeated_bytes_value = 19;
}

message TestTimestamp {
  google.protobuf.Timestamp value = 1;
  repeated google.protobuf.Timestamp repeated_value = 2;
}

message TestDuration {
  google.protobuf.Duration value = 1;
  repeated google.protobuf.Duration repeated_value = 2;
}

message TestFieldMask {
  google.protobuf.FieldMask value = 1;
}

message TestStruct {
  google.protobuf.Struct value = 1;
  repeated google.protobuf.Struct repeated_value = 2;
}

message TestAny {
  google.protobuf.Any value = 1;
  repeated google.protobuf.Any repeated_value = 2;
}

message TestValue {
  google.protobuf.Value value = 1;
  repeated google.protobuf.Value repeated_value = 2;
}

message TestListValue {
  google.protobuf.ListValue value = 1;
  repeated google.protobuf.ListValue repeated_value = 2;
}

message TestBoolValue {
  bool bool_value = 1;
  map<bool, int32> bool_map = 2;
}

message TestCustomJsonName {
  int32 value = 1 [json_name = "@value"];
}

message TestExtensions {
  .protobuf_unittest.TestAllExtensions extensions = 1;
}


text:
// Adapted from the patch of kenton@google.com (Kenton Varda)
// See https://github.com/google/protobuf/pull/710 for details.

#include <google/protobuf/util/delimited_message_util.h>

#include <sstream>

#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>

namespace google {
namespace protobuf {
namespace util {

TEST(DelimitedMessageUtilTest, DelimitedMessages) {
  std::stringstream stream;

  {
    protobuf_unittest::TestAllTypes message1;
    TestUtil::SetAllFields(&message1);
    EXPECT_TRUE(SerializeDelimitedToOstream(message1, &stream));

    protobuf_unittest::TestPackedTypes message2;
    TestUtil::SetPackedFields(&message2);
    EXPECT_TRUE(SerializeDelimitedToOstream(message2, &stream));
  }

  {
    bool clean_eof;
    io::IstreamInputStream zstream(&stream);

    protobuf_unittest::TestAllTypes message1;
    clean_eof = true;
    EXPECT_TRUE(ParseDelimitedFromZeroCopyStream(&message1,
        &zstream, &clean_eof));
    EXPECT_FALSE(clean_eof);
    TestUtil::ExpectAllFieldsSet(message1);

    protobuf_unittest::TestPackedTypes message2;
    clean_eof = true;
    EXPECT_TRUE(ParseDelimitedFromZeroCopyStream(&message2,
        &zstream, &clean_eof));
    EXPECT_FALSE(clean_eof);
    TestUtil::ExpectPackedFieldsSet(message2);

    clean_eof = false;
    EXPECT_FALSE(ParseDelimitedFromZeroCopyStream(&message2,
        &zstream, &clean_eof));
    EXPECT_TRUE(clean_eof);
  }
}

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

// Defines a TypeResolver for the Any message.

#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__
#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__

#include <string>

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

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

namespace protobuf {
class DescriptorPool;
namespace util {

// Abstract interface for a type resovler.
//
// Implementations of this interface must be thread-safe.
class LIBPROTOBUF_EXPORT TypeResolver {
 public:
  TypeResolver() {}
  virtual ~TypeResolver() {}

  // Resolves a type url for a message type.
  virtual util::Status ResolveMessageType(
      const string& type_url, google::protobuf::Type* message_type) = 0;

  // Resolves a type url for an enum type.
  virtual util::Status ResolveEnumType(const string& type_url,
                                         google::protobuf::Enum* enum_type) = 0;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeResolver);
};

}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__