text:
#include "google/protobuf/compiler/js/well_known_types_embed.h"
struct FileToc well_known_types_js[] = {
{"any.js",
  "// Protocol Buffers - Google's data interchange format\n"
  "// Copyright 2008 Google Inc.  All rights reserved.\n"
  "// https://developers.google.com/protocol-buffers/\n"
  "//\n"
  "// Redistribution and use in source and binary forms, with or without\n"
  "// modification, are permitted provided that the following conditions are\n"
  "// met:\n"
  "//\n"
  "//     * Redistributions of source code must retain the above copyright\n"
  "// notice, this list of conditions and the following disclaimer.\n"
  "//     * Redistributions in binary form must reproduce the above\n"
  "// copyright notice, this list of conditions and the following disclaimer\n"
  "// in the documentation and/or other materials provided with the\n"
  "// distribution.\n"
  "//     * Neither the name of Google Inc. nor the names of its\n"
  "// contributors may be used to endorse or promote products derived from\n"
  "// this software without specific prior written permission.\n"
  "//\n"
  "// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
  "// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
  "// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
  "// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
  "// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
  "// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
  "// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
  "// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
  "// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
  "// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
  "// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  "\n"
  "/* This code will be inserted into generated code for\n"
  " * google/protobuf/any.proto. */\n"
  "\n"
  "/**\n"
  " * Returns the type name contained in this instance, if any.\n"
  " * @return {string|undefined}\n"
  " */\n"
  "proto.google.protobuf.Any.prototype.getTypeName = function() {\n"
  "  return this.getTypeUrl().split('/').pop();\n"
  "};\n"
  "\n"
  "\n"
  "/**\n"
  " * Packs the given message instance into this Any.\n"
  " * @param {!Uint8Array} serialized The serialized data to pack.\n"
  " * @param {string} name The type name of this message object.\n"
  " * @param {string=} opt_typeUrlPrefix the type URL prefix.\n"
  " */\n"
  "proto.google.protobuf.Any.prototype.pack = function(serialized, name,\n"
  "                                                    opt_typeUrlPrefix) {\n"
  "  if (!opt_typeUrlPrefix) {\n"
  "    opt_typeUrlPrefix = 'type.googleapis.com/';\n"
  "  }\n"
  "\n"
  "  if (opt_typeUrlPrefix.substr(-1) != '/') {\n"
  "    this.setTypeUrl(opt_typeUrlPrefix + '/' + name);\n"
  "  } else {\n"
  "    this.setTypeUrl(opt_typeUrlPrefix + name);\n"
  "  }\n"
  "\n"
  "  this.setValue(serialized);\n"
  "};\n"
  "\n"
  "\n"
  "/**\n"
  " * @template T\n"
  " * Unpacks this Any into the given message object.\n"
  " * @param {function(Uint8Array):T} deserialize Function that will deserialize\n"
  " *     the binary data properly.\n"
  " * @param {string} name The expected type name of this message object.\n"
  " * @return {?T} If the name matched the expected name, returns the deserialized\n"
  " *     object, otherwise returns null.\n"
  " */\n"
  "proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) {\n"
  "  if (this.getTypeName() == name) {\n"
  "    return deserialize(this.getValue_asU8());\n"
  "  } else {\n"
  "    return null;\n"
  "  }\n"
  "};\n"
},
{"struct.js",
  "// Protocol Buffers - Google's data interchange format\n"
  "// Copyright 2008 Google Inc.  All rights reserved.\n"
  "// https://developers.google.com/protocol-buffers/\n"
  "//\n"
  "// Redistribution and use in source and binary forms, with or without\n"
  "// modification, are permitted provided that the following conditions are\n"
  "// met:\n"
  "//\n"
  "//     * Redistributions of source code must retain the above copyright\n"
  "// notice, this list of conditions and the following disclaimer.\n"
  "//     * Redistributions in binary form must reproduce the above\n"
  "// copyright notice, this list of conditions and the following disclaimer\n"
  "// in the documentation and/or other materials provided with the\n"
  "// distribution.\n"
  "//     * Neither the name of Google Inc. nor the names of its\n"
  "// contributors may be used to endorse or promote products derived from\n"
  "// this software without specific prior written permission.\n"
  "//\n"
  "// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
  "// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
  "// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
  "// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
  "// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
  "// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
  "// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
  "// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
  "// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
  "// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
  "// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  "\n"
  "/* This code will be inserted into generated code for\n"
  " * google/protobuf/struct.proto. */\n"
  "\n"
  "/**\n"
  " * Typedef representing plain JavaScript values that can go into a\n"
  " *     Struct.\n"
  " * @typedef {null|number|string|boolean|Array|Object}\n"
  " */\n"
  "proto.google.protobuf.JavaScriptValue;\n"
  "\n"
  "\n"
  "/**\n"
  " * Converts this Value object to a plain JavaScript value.\n"
  " * @return {?proto.google.protobuf.JavaScriptValue} a plain JavaScript\n"
  " *     value representing this Struct.\n"
  " */\n"
  "proto.google.protobuf.Value.prototype.toJavaScript = function() {\n"
  "  var kindCase = proto.google.protobuf.Value.KindCase;\n"
  "  switch (this.getKindCase()) {\n"
  "    case kindCase.NULL_VALUE:\n"
  "      return null;\n"
  "    case kindCase.NUMBER_VALUE:\n"
  "      return this.getNumberValue();\n"
  "    case kindCase.STRING_VALUE:\n"
  "      return this.getStringValue();\n"
  "    case kindCase.BOOL_VALUE:\n"
  "      return this.getBoolValue();\n"
  "    case kindCase.STRUCT_VALUE:\n"
  "      return this.getStructValue().toJavaScript();\n"
  "    case kindCase.LIST_VALUE:\n"
  "      return this.getListValue().toJavaScript();\n"
  "    default:\n"
  "      throw new Error('Unexpected struct type');\n"
  "  }\n"
  "};\n"
  "\n"
  "\n"
  "/**\n"
  " * Converts this JavaScript value to a new Value proto.\n"
  " * @param {!proto.google.protobuf.JavaScriptValue} value The value to\n"
  " *     convert.\n"
  " * @return {!proto.google.protobuf.Value} The newly constructed value.\n"
  " */\n"
  "proto.google.protobuf.Value.fromJavaScript = function(value) {\n"
  "  var ret = new proto.google.protobuf.Value();\n"
  "  switch (goog.typeOf(value)) {\n"
  "    case 'string':\n"
  "      ret.setStringValue(/** @type {string} */ (value));\n"
  "      break;\n"
  "    case 'number':\n"
  "      ret.setNumberValue(/** @type {number} */ (value));\n"
  "      break;\n"
  "    case 'boolean':\n"
  "      ret.setBoolValue(/** @type {boolean} */ (value));\n"
  "      break;\n"
  "    case 'null':\n"
  "      ret.setNullValue(proto.google.protobuf.NullValue.NULL_VALUE);\n"
  "      break;\n"
  "    case 'array':\n"
  "      ret.setListValue(proto.google.protobuf.ListValue.fromJavaScript(\n"
  "          /** @type{!Array} */ (value)));\n"
  "      break;\n"
  "    case 'object':\n"
  "      ret.setStructValue(proto.google.protobuf.Struct.fromJavaScript(\n"
  "          /** @type{!Object} */ (value)));\n"
  "      break;\n"
  "    default:\n"
  "      throw new Error('Unexpected struct type.');\n"
  "  }\n"
  "\n"
  "  return ret;\n"
  "};\n"
  "\n"
  "\n"
  "/**\n"
  " * Converts this ListValue object to a plain JavaScript array.\n"
  " * @return {!Array} a plain JavaScript array representing this List.\n"
  " */\n"
  "proto.google.protobuf.ListValue.prototype.toJavaScript = function() {\n"
  "  var ret = [];\n"
  "  var values = this.getValuesList();\n"
  "\n"
  "  for (var i = 0; i < values.length; i++) {\n"
  "    ret[i] = values[i].toJavaScript();\n"
  "  }\n"
  "\n"
  "  return ret;\n"
  "};\n"
  "\n"
  "\n"
  "/**\n"
  " * Constructs a ListValue protobuf from this plain JavaScript array.\n"
  " * @param {!Array} array a plain JavaScript array\n"
  " * @return {proto.google.protobuf.ListValue} a new ListValue object\n"
  " */\n"
  "proto.google.protobuf.ListValue.fromJavaScript = function(array) {\n"
  "  var ret = new proto.google.protobuf.ListValue();\n"
  "\n"
  "  for (var i = 0; i < array.length; i++) {\n"
  "    ret.addValues(proto.google.protobuf.Value.fromJavaScript(array[i]));\n"
  "  }\n"
  "\n"
  "  return ret;\n"
  "};\n"
  "\n"
  "\n"
  "/**\n"
  " * Converts this Struct object to a plain JavaScript object.\n"
  " * @return {!Object<string, !proto.google.protobuf.JavaScriptValue>} a plain\n"
  " *     JavaScript object representing this Struct.\n"
  " */\n"
  "proto.google.protobuf.Struct.prototype.toJavaScript = function() {\n"
  "  var ret = {};\n"
  "\n"
  "  this.getFieldsMap().forEach(function(value, key) {\n"
  "    ret[key] = value.toJavaScript();\n"
  "  });\n"
  "\n"
  "  return ret;\n"
  "};\n"
  "\n"
  "\n"
  "/**\n"
  " * Constructs a Struct protobuf from this plain JavaScript object.\n"
  " * @param {!Object} obj a plain JavaScript object\n"
  " * @return {proto.google.protobuf.Struct} a new Struct object\n"
  " */\n"
  "proto.google.protobuf.Struct.fromJavaScript = function(obj) {\n"
  "  var ret = new proto.google.protobuf.Struct();\n"
  "  var map = ret.getFieldsMap();\n"
  "\n"
  "  for (var property in obj) {\n"
  "    var val = obj[property];\n"
  "    map.set(property, proto.google.protobuf.Value.fromJavaScript(val));\n"
  "  }\n"
  "\n"
  "  return ret;\n"
  "};\n"
},
{"timestamp.js",
  "// Protocol Buffers - Google's data interchange format\n"
  "// Copyright 2008 Google Inc.  All rights reserved.\n"
  "// https://developers.google.com/protocol-buffers/\n"
  "//\n"
  "// Redistribution and use in source and binary forms, with or without\n"
  "// modification, are permitted provided that the following conditions are\n"
  "// met:\n"
  "//\n"
  "//     * Redistributions of source code must retain the above copyright\n"
  "// notice, this list of conditions and the following disclaimer.\n"
  "//     * Redistributions in binary form must reproduce the above\n"
  "// copyright notice, this list of conditions and the following disclaimer\n"
  "// in the documentation and/or other materials provided with the\n"
  "// distribution.\n"
  "//     * Neither the name of Google Inc. nor the names of its\n"
  "// contributors may be used to endorse or promote products derived from\n"
  "// this software without specific prior written permission.\n"
  "//\n"
  "// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
  "// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
  "// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
  "// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
  "// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
  "// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
  "// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
  "// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
  "// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
  "// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
  "// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  "\n"
  "/* This code will be inserted into generated code for\n"
  " * google/protobuf/timestamp.proto. */\n"
  "\n"
  "/**\n"
  " * Returns a JavaScript 'Date' object corresponding to this Timestamp.\n"
  " * @return {!Date}\n"
  " */\n"
  "proto.google.protobuf.Timestamp.prototype.toDate = function() {\n"
  "  var seconds = this.getSeconds();\n"
  "  var nanos = this.getNanos();\n"
  "\n"
  "  return new Date((seconds * 1000) + (nanos / 1000000));\n"
  "};\n"
  "\n"
  "\n"
  "/**\n"
  " * Sets the value of this Timestamp object to be the given Date.\n"
  " * @param {!Date} value The value to set.\n"
  " */\n"
  "proto.google.protobuf.Timestamp.prototype.fromDate = function(value) {\n"
  "  this.setSeconds(Math.floor(value.getTime() / 1000));\n"
  "  this.setNanos(value.getMilliseconds() * 1000000);\n"
  "};\n"
},
  {NULL, NULL}  // Terminate the list.
};

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_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__
#define GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_H__

#include <stddef.h>

struct FileToc {
  const char* name;
  const char* data;
};

extern struct FileToc well_known_types_js[];

#endif  // GOOGLE_PROTOBUF_COMPILER_JS_WELL_KNOWN_TYPES_EMBED_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 <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>

const char output_file[] = "well_known_types_embed.cc";

static bool AsciiIsPrint(unsigned char c) {
  return c >= 32 && c < 127;
}

static char ToDecimalDigit(int num) {
  assert(num < 10);
  return '0' + num;
}

static std::string CEscape(const std::string& str) {
  std::string dest;

  for (size_t i = 0; i < str.size(); ++i) {
    unsigned char ch = str[i];
    switch (ch) {
      case '\n': dest += "\\n"; break;
      case '\r': dest += "\\r"; break;
      case '\t': dest += "\\t"; break;
      case '\"': dest += "\\\""; break;
      case '\\': dest += "\\\\"; break;
      default:
        if (AsciiIsPrint(ch)) {
          dest += ch;
        } else {
          dest += "\\";
          dest += ToDecimalDigit(ch / 64);
          dest += ToDecimalDigit((ch % 64) / 8);
          dest += ToDecimalDigit(ch % 8);
        }
        break;
    }
  }

  return dest;
}

static void AddFile(const char* name, std::basic_ostream<char>* out) {
  std::ifstream in(name);

  if (!in.is_open()) {
    std::cerr << "Couldn't open input file: " << name << "\n";
    std::exit(EXIT_FAILURE);
  }

  // Make canonical name only include the final element.
  for (const char *p = name; *p; p++) {
    if (*p == '/') {
      name = p + 1;
    }
  }

  *out << "{\"" << CEscape(name) << "\",\n";

  for (std::string line; std::getline(in, line); ) {
    *out << "  \"" << CEscape(line) << "\\n\"\n";
  }

  *out << "},\n";
}

int main(int argc, char *argv[]) {
  std::cout << "#include "
               "\"google/protobuf/compiler/js/well_known_types_embed.h\"\n";
  std::cout << "struct FileToc well_known_types_js[] = {\n";

  for (int i = 1; i < argc; i++) {
    AddFile(argv[i], &std::cout);
  }

  std::cout << "  {NULL, NULL}  // Terminate the list.\n";
  std::cout << "};\n";

  return EXIT_SUCCESS;
}


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 code will be inserted into generated code for
 * google/protobuf/any.proto. */

/**
 * Returns the type name contained in this instance, if any.
 * @return {string|undefined}
 */
proto.google.protobuf.Any.prototype.getTypeName = function() {
  return this.getTypeUrl().split('/').pop();
};

/**
 * Packs the given message instance into this Any.
 * @param {!Uint8Array} serialized The serialized data to pack.
 * @param {string} name The type name of this message object.
 * @param {string=} opt_typeUrlPrefix the type URL prefix.
 */
proto.google.protobuf.Any.prototype.pack = function(serialized, name,
                                                    opt_typeUrlPrefix) {
  if (!opt_typeUrlPrefix) {
    opt_typeUrlPrefix = 'type.googleapis.com/';
  }

  if (opt_typeUrlPrefix.substr(-1) != '/') {
    this.setTypeUrl(opt_typeUrlPrefix + '/' + name);
  } else {
    this.setTypeUrl(opt_typeUrlPrefix + name);
  }

  this.setValue(serialized);
};

/**
 * @template T
 * Unpacks this Any into the given message object.
 * @param {function(Uint8Array):T} deserialize Function that will deserialize
 *     the binary data properly.
 * @param {string} name The expected type name of this message object.
 * @return {?T} If the name matched the expected name, returns the deserialized
 *     object, otherwise returns null.
 */
proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) {
  if (this.getTypeName() == name) {
    return deserialize(this.getValue_asU8());
  } else {
    return null;
  }
};


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 code will be inserted into generated code for
 * google/protobuf/struct.proto. */

/**
 * Typedef representing plain JavaScript values that can go into a
 *     Struct.
 * @typedef {null|number|string|boolean|Array|Object}
 */
proto.google.protobuf.JavaScriptValue;

/**
 * Converts this Value object to a plain JavaScript value.
 * @return {?proto.google.protobuf.JavaScriptValue} a plain JavaScript
 *     value representing this Struct.
 */
proto.google.protobuf.Value.prototype.toJavaScript = function() {
  var kindCase = proto.google.protobuf.Value.KindCase;
  switch (this.getKindCase()) {
    case kindCase.NULL_VALUE:
      return null;
    case kindCase.NUMBER_VALUE:
      return this.getNumberValue();
    case kindCase.STRING_VALUE:
      return this.getStringValue();
    case kindCase.BOOL_VALUE:
      return this.getBoolValue();
    case kindCase.STRUCT_VALUE:
      return this.getStructValue().toJavaScript();
    case kindCase.LIST_VALUE:
      return this.getListValue().toJavaScript();
    default:
      throw new Error('Unexpected struct type');
  }
};

/**
 * Converts this JavaScript value to a new Value proto.
 * @param {!proto.google.protobuf.JavaScriptValue} value The value to
 *     convert.
 * @return {!proto.google.protobuf.Value} The newly constructed value.
 */
proto.google.protobuf.Value.fromJavaScript = function(value) {
  var ret = new proto.google.protobuf.Value();
  switch (goog.typeOf(value)) {
    case 'string':
      ret.setStringValue(/** @type {string} */ (value));
      break;
    case 'number':
      ret.setNumberValue(/** @type {number} */ (value));
      break;
    case 'boolean':
      ret.setBoolValue(/** @type {boolean} */ (value));
      break;
    case 'null':
      ret.setNullValue(proto.google.protobuf.NullValue.NULL_VALUE);
      break;
    case 'array':
      ret.setListValue(proto.google.protobuf.ListValue.fromJavaScript(
          /** @type{!Array} */ (value)));
      break;
    case 'object':
      ret.setStructValue(proto.google.protobuf.Struct.fromJavaScript(
          /** @type{!Object} */ (value)));
      break;
    default:
      throw new Error('Unexpected struct type.');
  }

  return ret;
};

/**
 * Converts this ListValue object to a plain JavaScript array.
 * @return {!Array} a plain JavaScript array representing this List.
 */
proto.google.protobuf.ListValue.prototype.toJavaScript = function() {
  var ret = [];
  var values = this.getValuesList();

  for (var i = 0; i < values.length; i++) {
    ret[i] = values[i].toJavaScript();
  }

  return ret;
};

/**
 * Constructs a ListValue protobuf from this plain JavaScript array.
 * @param {!Array} array a plain JavaScript array
 * @return {proto.google.protobuf.ListValue} a new ListValue object
 */
proto.google.protobuf.ListValue.fromJavaScript = function(array) {
  var ret = new proto.google.protobuf.ListValue();

  for (var i = 0; i < array.length; i++) {
    ret.addValues(proto.google.protobuf.Value.fromJavaScript(array[i]));
  }

  return ret;
};

/**
 * Converts this Struct object to a plain JavaScript object.
 * @return {!Object<string, !proto.google.protobuf.JavaScriptValue>} a plain
 *     JavaScript object representing this Struct.
 */
proto.google.protobuf.Struct.prototype.toJavaScript = function() {
  var ret = {};

  this.getFieldsMap().forEach(function(value, key) {
    ret[key] = value.toJavaScript();
  });

  return ret;
};

/**
 * Constructs a Struct protobuf from this plain JavaScript object.
 * @param {!Object} obj a plain JavaScript object
 * @return {proto.google.protobuf.Struct} a new Struct object
 */
proto.google.protobuf.Struct.fromJavaScript = function(obj) {
  var ret = new proto.google.protobuf.Struct();
  var map = ret.getFieldsMap();

  for (var property in obj) {
    var val = obj[property];
    map.set(property, proto.google.protobuf.Value.fromJavaScript(val));
  }

  return ret;
};


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 code will be inserted into generated code for
 * google/protobuf/timestamp.proto. */

/**
 * Returns a JavaScript 'Date' object corresponding to this Timestamp.
 * @return {!Date}
 */
proto.google.protobuf.Timestamp.prototype.toDate = function() {
  var seconds = this.getSeconds();
  var nanos = this.getNanos();

  return new Date((seconds * 1000) + (nanos / 1000000));
};

/**
 * Sets the value of this Timestamp object to be the given Date.
 * @param {!Date} value The value to set.
 */
proto.google.protobuf.Timestamp.prototype.fromDate = function(value) {
  this.setSeconds(Math.floor(value.getTime() / 1000));
  this.setNanos(value.getMilliseconds() * 1000000);
};


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.

#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {

using internal::WireFormatLite;

namespace {

// For encodings with fixed sizes, returns that size in bytes.  Otherwise
// returns -1.
int FixedSize(FieldDescriptor::Type type) {
  switch (type) {
    case FieldDescriptor::TYPE_INT32   : return -1;
    case FieldDescriptor::TYPE_INT64   : return -1;
    case FieldDescriptor::TYPE_UINT32  : return -1;
    case FieldDescriptor::TYPE_UINT64  : return -1;
    case FieldDescriptor::TYPE_SINT32  : return -1;
    case FieldDescriptor::TYPE_SINT64  : return -1;
    case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
    case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
    case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
    case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
    case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
    case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;

    case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
    case FieldDescriptor::TYPE_ENUM    : return -1;

    case FieldDescriptor::TYPE_STRING  : return -1;
    case FieldDescriptor::TYPE_BYTES   : return -1;
    case FieldDescriptor::TYPE_GROUP   : return -1;
    case FieldDescriptor::TYPE_MESSAGE : return -1;

    // No default because we want the compiler to complain if any new
    // types are added.
  }
  GOOGLE_LOG(FATAL) << "Can't get here.";
  return -1;
}

void SetPrimitiveVariables(const FieldDescriptor* descriptor,
                           std::map<string, string>* variables,
                           const Options& options) {
  SetCommonFieldVariables(descriptor, variables, options);
  (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
  (*variables)["default"] = DefaultValue(descriptor);
  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
  int fixed_size = FixedSize(descriptor->type());
  if (fixed_size != -1) {
    (*variables)["fixed_size"] = SimpleItoa(fixed_size);
  }
  (*variables)["wire_format_field_type"] =
      "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
          static_cast<FieldDescriptorProto_Type>(descriptor->type()));
  (*variables)["full_name"] = descriptor->full_name();
}

}  // namespace

// ===================================================================

PrimitiveFieldGenerator::PrimitiveFieldGenerator(
    const FieldDescriptor* descriptor, const Options& options)
    : FieldGenerator(options), descriptor_(descriptor) {
  SetPrimitiveVariables(descriptor, &variables_, options);
}

PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}

void PrimitiveFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
  printer->Print(variables_, "$type$ $name$_;\n");
}

void PrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
  printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n");
  printer->Annotate("name", descriptor_);
  printer->Print(variables_,
                 "$deprecated_attr$void ${$set_$name$$}$($type$ value);\n");
  printer->Annotate("{", "}", descriptor_);
}

void PrimitiveFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
  printer->Print(variables_,
    "inline $type$ $classname$::$name$() const {\n"
    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
    "  return $name$_;\n"
    "}\n"
    "inline void $classname$::set_$name$($type$ value) {\n"
    "  $set_hasbit$\n"
    "  $name$_ = value;\n"
    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
    "}\n");
}

void PrimitiveFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_ = $default$;\n");
}

void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  printer->Print(variables_, "set_$name$(from.$name$());\n");
}

void PrimitiveFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
  printer->Print(variables_, "swap($name$_, other->$name$_);\n");
}

void PrimitiveFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_ = $default$;\n");
}

void PrimitiveFieldGenerator::
GenerateCopyConstructorCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_ = from.$name$_;\n");
}

void PrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
  printer->Print(variables_,
    "$set_hasbit$\n"
    "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
    "         $type$, $wire_format_field_type$>(\n"
    "       input, &$name$_)));\n");
}

void PrimitiveFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
  printer->Print(variables_,
    "::google::protobuf::internal::WireFormatLite::Write$declared_type$("
      "$number$, this->$name$(), output);\n");
}

void PrimitiveFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
  printer->Print(variables_,
    "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray("
      "$number$, this->$name$(), target);\n");
}

void PrimitiveFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
  int fixed_size = FixedSize(descriptor_->type());
  if (fixed_size == -1) {
    printer->Print(variables_,
      "total_size += $tag_size$ +\n"
      "  ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
      "    this->$name$());\n");
  } else {
    printer->Print(variables_,
      "total_size += $tag_size$ + $fixed_size$;\n");
  }
}

// ===================================================================

PrimitiveOneofFieldGenerator::
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
                             const Options& options)
  : PrimitiveFieldGenerator(descriptor, options) {
  SetCommonOneofFieldVariables(descriptor, &variables_);
}

PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}

void PrimitiveOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
  printer->Print(variables_,
    "inline $type$ $classname$::$name$() const {\n"
    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
    "  if (has_$name$()) {\n"
    "    return $oneof_prefix$$name$_;\n"
    "  }\n"
    "  return $default$;\n"
    "}\n"
    "inline void $classname$::set_$name$($type$ value) {\n"
    "  if (!has_$name$()) {\n"
    "    clear_$oneof_name$();\n"
    "    set_has_$name$();\n"
    "  }\n"
    "  $oneof_prefix$$name$_ = value;\n"
    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
    "}\n");
}

void PrimitiveOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
  printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
}

void PrimitiveOneofFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
  // Don't print any swapping code. Swapping the union will swap this field.
}

void PrimitiveOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
  printer->Print(variables_,
                 "$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
}

void PrimitiveOneofFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
  printer->Print(variables_,
    "clear_$oneof_name$();\n"
    "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
    "         $type$, $wire_format_field_type$>(\n"
    "       input, &$oneof_prefix$$name$_)));\n"
    "set_has_$name$();\n");
}

// ===================================================================

RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
    const FieldDescriptor* descriptor, const Options& options)
    : FieldGenerator(options), descriptor_(descriptor) {
  SetPrimitiveVariables(descriptor, &variables_, options);

  if (descriptor->is_packed()) {
    variables_["packed_reader"] = "ReadPackedPrimitive";
    variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
  } else {
    variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
    variables_["repeated_reader"] = "ReadRepeatedPrimitive";
  }
}

RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}

void RepeatedPrimitiveFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
  printer->Print(variables_,
    "::google::protobuf::RepeatedField< $type$ > $name$_;\n");
  if (descriptor_->is_packed() &&
      HasGeneratedMethods(descriptor_->file(), options_)) {
    printer->Print(variables_,
      "mutable int _$name$_cached_byte_size_;\n");
  }
}

void RepeatedPrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
  printer->Print(variables_,
                 "$deprecated_attr$$type$ $name$(int index) const;\n");
  printer->Annotate("name", descriptor_);
  printer->Print(
      variables_,
      "$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n");
  printer->Annotate("{", "}", descriptor_);
  printer->Print(variables_,
                 "$deprecated_attr$void ${$add_$name$$}$($type$ value);\n");
  printer->Annotate("{", "}", descriptor_);
  printer->Print(variables_,
                 "$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n"
                 "    $name$() const;\n");
  printer->Annotate("name", descriptor_);
  printer->Print(variables_,
                 "$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n"
                 "    ${$mutable_$name$$}$();\n");
  printer->Annotate("{", "}", descriptor_);
}

void RepeatedPrimitiveFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
  printer->Print(variables_,
    "inline $type$ $classname$::$name$(int index) const {\n"
    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
    "  return $name$_.Get(index);\n"
    "}\n"
    "inline void $classname$::set_$name$(int index, $type$ value) {\n"
    "  $name$_.Set(index, value);\n"
    "  // @@protoc_insertion_point(field_set:$full_name$)\n"
    "}\n"
    "inline void $classname$::add_$name$($type$ value) {\n"
    "  $name$_.Add(value);\n"
    "  // @@protoc_insertion_point(field_add:$full_name$)\n"
    "}\n"
    "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
    "$classname$::$name$() const {\n"
    "  // @@protoc_insertion_point(field_list:$full_name$)\n"
    "  return $name$_;\n"
    "}\n"
    "inline ::google::protobuf::RepeatedField< $type$ >*\n"
    "$classname$::mutable_$name$() {\n"
    "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
    "  return &$name$_;\n"
    "}\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_.Clear();\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
  // Not needed for repeated fields.
}

void RepeatedPrimitiveFieldGenerator::
GenerateCopyConstructorCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_.CopyFrom(from.$name$_);\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
  printer->Print(variables_,
    "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
    "         $type$, $wire_format_field_type$>(\n"
    "       $tag_size$, $tag$u, input, this->mutable_$name$())));\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
  printer->Print(variables_,
    "DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n"
    "         $type$, $wire_format_field_type$>(\n"
    "       input, this->mutable_$name$())));\n");
}

void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
  bool array_written = false;
  if (descriptor_->is_packed()) {
    // Write the tag and the size.
    printer->Print(variables_,
      "if (this->$name$_size() > 0) {\n"
      "  ::google::protobuf::internal::WireFormatLite::WriteTag("
          "$number$, "
          "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
          "output);\n"
      "  output->WriteVarint32(static_cast< ::google::protobuf::uint32>(\n"
      "      _$name$_cached_byte_size_));\n");

    if (FixedSize(descriptor_->type()) > 0) {
      // TODO(ckennelly): Use RepeatedField<T>::unsafe_data() via
      // WireFormatLite to access the contents of this->$name$_ to save a branch
      // here.
      printer->Print(variables_,
        "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$Array(\n"
        "    this->$name$().data(), this->$name$_size(), output);\n");
      array_written = true;  // Wrote array all at once
    }
    printer->Print(variables_, "}\n");
  }
  if (!array_written) {
    printer->Print(variables_,
        "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n");
    if (descriptor_->is_packed()) {
      printer->Print(variables_,
        "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
        "    this->$name$(i), output);\n");
    } else {
      printer->Print(variables_,
        "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
        "    $number$, this->$name$(i), output);\n");
    }
    printer->Print("}\n");
  }
}

void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
  if (descriptor_->is_packed()) {
    // Write the tag and the size.
    printer->Print(variables_,
      "if (this->$name$_size() > 0) {\n"
      "  target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
      "    $number$,\n"
      "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
      "    target);\n"
      "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
      "      static_cast< ::google::protobuf::int32>(\n"
      "          _$name$_cached_byte_size_), target);\n"
      "  target = ::google::protobuf::internal::WireFormatLite::\n"
      "    Write$declared_type$NoTagToArray(this->$name$_, target);\n"
      "}\n");
  } else {
    printer->Print(variables_,
      "target = ::google::protobuf::internal::WireFormatLite::\n"
      "  Write$declared_type$ToArray($number$, this->$name$_, target);\n");
  }
}

void RepeatedPrimitiveFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
  printer->Print(variables_, "{\n");
  printer->Indent();
  int fixed_size = FixedSize(descriptor_->type());
  if (fixed_size == -1) {
    printer->Print(variables_,
      "size_t data_size = ::google::protobuf::internal::WireFormatLite::\n"
      "  $declared_type$Size(this->$name$_);\n");
  } else {
    printer->Print(variables_,
      "unsigned int count = static_cast<unsigned int>(this->$name$_size());\n"
      "size_t data_size = $fixed_size$UL * count;\n");
  }

  if (descriptor_->is_packed()) {
    printer->Print(variables_,
      "if (data_size > 0) {\n"
      "  total_size += $tag_size$ +\n"
      "    ::google::protobuf::internal::WireFormatLite::Int32Size(\n"
      "        static_cast< ::google::protobuf::int32>(data_size));\n"
      "}\n"
      "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
      "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
      "_$name$_cached_byte_size_ = cached_size;\n"
      "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
      "total_size += data_size;\n");
  } else {
    printer->Print(variables_,
      "total_size += $tag_size$ *\n"
      "              ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
      "total_size += data_size;\n");
  }
  printer->Outdent();
  printer->Print("}\n");
}

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

#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__

#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <set>
#include <string>
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
#include <google/protobuf/compiler/cpp/cpp_options.h>

namespace google {
namespace protobuf {
  namespace io {
    class Printer;             // printer.h
  }
}

namespace protobuf {
namespace compiler {
namespace cpp {

class EnumGenerator;           // enum.h
class ExtensionGenerator;      // extension.h

class MessageGenerator {
 public:
  // See generator.cc for the meaning of dllexport_decl.
  MessageGenerator(const Descriptor* descriptor, int index_in_file_messages,
                   const Options& options, SCCAnalyzer* scc_analyzer);
  ~MessageGenerator();

  // Append the two types of nested generators to the corresponding vector.
  void AddGenerators(std::vector<EnumGenerator*>* enum_generators,
                     std::vector<ExtensionGenerator*>* extension_generators);

  // Header stuff.

  // Return names for forward declarations of this class and all its nested
  // types. A given key in {class,enum}_names will map from a class name to the
  // descriptor that was responsible for its inclusion in the map. This can be
  // used to associate the descriptor with the code generated for it.
  void FillMessageForwardDeclarations(
      std::map<string, const Descriptor*>* class_names);

  // Generate definitions for this class and all its nested types.
  void GenerateClassDefinition(io::Printer* printer);

  // Generate definitions of inline methods (placed at the end of the header
  // file).
  void GenerateInlineMethods(io::Printer* printer);

  // Dependent methods are always inline.
  void GenerateDependentInlineMethods(io::Printer* printer);

  // Source file stuff.

  // Generate extra fields
  void GenerateExtraDefaultFields(io::Printer* printer);

  // Generates code that creates default instances for fields.
  void GenerateFieldDefaultInstances(io::Printer* printer);

  // Generates code that initializes the message's default instance.  This
  // is separate from allocating because all default instances must be
  // allocated before any can be initialized.
  void GenerateDefaultInstanceInitializer(io::Printer* printer);

  // Generate all non-inline methods for this class.
  void GenerateClassMethods(io::Printer* printer);

 private:
  // Generate declarations and definitions of accessors for fields.
  void GenerateDependentBaseClassDefinition(io::Printer* printer);
  void GenerateDependentFieldAccessorDeclarations(io::Printer* printer);
  void GenerateFieldAccessorDeclarations(io::Printer* printer);
  void GenerateDependentFieldAccessorDefinitions(io::Printer* printer);
  void GenerateFieldAccessorDefinitions(io::Printer* printer);

  // Generate the table-driven parsing array.  Returns the number of entries
  // generated.
  size_t GenerateParseOffsets(io::Printer* printer);
  size_t GenerateParseAuxTable(io::Printer* printer);
  // Generates a ParseTable entry.  Returns whether the proto uses table-driven
  // parsing.
  bool GenerateParseTable(io::Printer* printer, size_t offset,
                          size_t aux_offset);

  // Generate the field offsets array.  Returns the a pair of the total numer
  // of entries generated and the index of the first has_bit entry.
  std::pair<size_t, size_t> GenerateOffsets(io::Printer* printer);
  void GenerateSchema(io::Printer* printer, int offset, int has_offset);
  // For each field generates a table entry describing the field for the
  // table driven serializer.
  int GenerateFieldMetadata(io::Printer* printer);

  // Generate constructors and destructor.
  void GenerateStructors(io::Printer* printer);

  // The compiler typically generates multiple copies of each constructor and
  // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
  // Placing common code in a separate method reduces the generated code size.
  //
  // Generate the shared constructor code.
  void GenerateSharedConstructorCode(io::Printer* printer);
  // Generate the shared destructor code.
  void GenerateSharedDestructorCode(io::Printer* printer);
  // Generate the arena-specific destructor code.
  void GenerateArenaDestructorCode(io::Printer* printer);

  // Helper for GenerateClear and others.  Optionally emits a condition that
  // assumes the existence of the cached_has_bits variable, and returns true if
  // the condition was printed.
  bool MaybeGenerateOptionalFieldCondition(io::Printer* printer,
                                           const FieldDescriptor* field,
                                           int expected_has_bits_index);

  // Generate standard Message methods.
  void GenerateClear(io::Printer* printer);
  void GenerateOneofClear(io::Printer* printer);
  void GenerateMergeFromCodedStream(io::Printer* printer);
  void GenerateSerializeWithCachedSizes(io::Printer* printer);
  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
  void GenerateSerializeWithCachedSizesBody(io::Printer* printer,
                                            bool to_array);
  void GenerateByteSize(io::Printer* printer);
  void GenerateMergeFrom(io::Printer* printer);
  void GenerateCopyFrom(io::Printer* printer);
  void GenerateSwap(io::Printer* printer);
  void GenerateIsInitialized(io::Printer* printer);

  // Helpers for GenerateSerializeWithCachedSizes().
  //
  // cached_has_bit_index maintains that:
  //   cached_has_bits = _has_bits_[cached_has_bit_index]
  // for cached_has_bit_index >= 0
  void GenerateSerializeOneField(io::Printer* printer,
                                 const FieldDescriptor* field,
                                 bool unbounded,
                                 int cached_has_bits_index);
  // Generate a switch statement to serialize 2+ fields from the same oneof.
  // Or, if fields.size() == 1, just call GenerateSerializeOneField().
  void GenerateSerializeOneofFields(
      io::Printer* printer, const std::vector<const FieldDescriptor*>& fields,
      bool to_array);
  void GenerateSerializeOneExtensionRange(
      io::Printer* printer, const Descriptor::ExtensionRange* range,
      bool unbounded);

  // Generates has_foo() functions and variables for singular field has-bits.
  void GenerateSingularFieldHasBits(const FieldDescriptor* field,
                                    std::map<string, string> vars,
                                    io::Printer* printer);
  // Generates has_foo() functions and variables for oneof field has-bits.
  void GenerateOneofHasBits(io::Printer* printer);
  // Generates has_foo_bar() functions for oneof members.
  void GenerateOneofMemberHasBits(const FieldDescriptor* field,
                                  const std::map<string, string>& vars,
                                  io::Printer* printer);
  // Generates the clear_foo() method for a field.
  void GenerateFieldClear(const FieldDescriptor* field,
                          const std::map<string, string>& vars,
                          bool is_inline,
                          io::Printer* printer);

  void GenerateConstructorBody(io::Printer* printer,
                               std::vector<bool> already_processed,
                               bool copy_constructor) const;

  size_t HasBitsSize() const;
  std::vector<uint32> RequiredFieldsBitMask() const;

  const Descriptor* descriptor_;
  int index_in_file_messages_;
  string classname_;
  Options options_;
  FieldGeneratorMap field_generators_;
  // optimized_order_ is the order we layout the message's fields in the class.
  // This is reused to initialize the fields in-order for cache efficiency.
  //
  // optimized_order_ excludes oneof fields and weak fields.
  std::vector<const FieldDescriptor *> optimized_order_;
  std::vector<int> has_bit_indices_;
  int max_has_bit_index_;
  google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
  google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
  int num_required_fields_;
  bool use_dependent_base_;
  int num_weak_fields_;
  // table_driven_ indicates the generated message uses table-driven parsing.
  bool table_driven_;

  google::protobuf::scoped_ptr<MessageLayoutHelper> message_layout_helper_;

  SCCAnalyzer* scc_analyzer_;
  string scc_name_;

  friend class FileGenerator;
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
};

}  // namespace cpp
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_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.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__

#include <map>
#include <string>
#include <google/protobuf/compiler/cpp/cpp_field.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {

class StringFieldGenerator : public FieldGenerator {
 public:
  StringFieldGenerator(const FieldDescriptor* descriptor,
                       const Options& options);
  ~StringFieldGenerator();

  // implements FieldGenerator ---------------------------------------
  void GeneratePrivateMembers(io::Printer* printer) const;
  void GenerateStaticMembers(io::Printer* printer) const;
  void GenerateAccessorDeclarations(io::Printer* printer) const;
  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
  void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
  void GenerateClearingCode(io::Printer* printer) const;
  void GenerateMessageClearingCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateSwappingCode(io::Printer* printer) const;
  void GenerateConstructorCode(io::Printer* printer) const;
  void GenerateCopyConstructorCode(io::Printer* printer) const;
  void GenerateDestructorCode(io::Printer* printer) const;
  void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
  void GenerateMergeFromCodedStream(io::Printer* printer) const;
  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
  void GenerateByteSize(io::Printer* printer) const;

 protected:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;
  const bool lite_;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
};

class StringOneofFieldGenerator : public StringFieldGenerator {
 public:
  StringOneofFieldGenerator(const FieldDescriptor* descriptor,
                            const Options& options);
  ~StringOneofFieldGenerator();

  // implements FieldGenerator ---------------------------------------
  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
  void GenerateClearingCode(io::Printer* printer) const;

  // StringFieldGenerator, from which we inherit, overrides this so we need to
  // override it as well.
  void GenerateMessageClearingCode(io::Printer* printer) const;
  void GenerateSwappingCode(io::Printer* printer) const;
  void GenerateConstructorCode(io::Printer* printer) const;
  void GenerateDestructorCode(io::Printer* printer) const;
  void GenerateMergeFromCodedStream(io::Printer* printer) const;

 private:
  const bool dependent_field_;
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
};

class RepeatedStringFieldGenerator : public FieldGenerator {
 public:
  RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
                               const Options& options);
  ~RepeatedStringFieldGenerator();

  // implements FieldGenerator ---------------------------------------
  void GeneratePrivateMembers(io::Printer* printer) const;
  void GenerateAccessorDeclarations(io::Printer* printer) const;
  void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
  void GenerateClearingCode(io::Printer* printer) const;
  void GenerateMergingCode(io::Printer* printer) const;
  void GenerateSwappingCode(io::Printer* printer) const;
  void GenerateConstructorCode(io::Printer* printer) const;
  void GenerateCopyConstructorCode(io::Printer* printer) const;
  void GenerateMergeFromCodedStream(io::Printer* printer) const;
  void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
  void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
  void GenerateByteSize(io::Printer* printer) const;

 private:
  const FieldDescriptor* descriptor_;
  std::map<string, string> variables_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
};

}  // namespace cpp
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_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/compiler/cpp/cpp_map_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>

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

namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {

bool IsProto3Field(const FieldDescriptor* field_descriptor) {
  const FileDescriptor* file_descriptor = field_descriptor->file();
  return file_descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
}

void SetMessageVariables(const FieldDescriptor* descriptor,
                         std::map<string, string>* variables,
                         const Options& options) {
  SetCommonFieldVariables(descriptor, variables, options);
  (*variables)["type"] = ClassName(descriptor->message_type(), false);
  (*variables)["file_namespace"] =
      FileLevelNamespace(descriptor->file()->name());
  (*variables)["stream_writer"] =
      (*variables)["declared_type"] +
      (HasFastArraySerialization(descriptor->message_type()->file(), options)
           ? "MaybeToArray"
           : "");
  (*variables)["full_name"] = descriptor->full_name();

  const FieldDescriptor* key =
      descriptor->message_type()->FindFieldByName("key");
  const FieldDescriptor* val =
      descriptor->message_type()->FindFieldByName("value");
  (*variables)["key_cpp"] = PrimitiveTypeName(key->cpp_type());
  switch (val->cpp_type()) {
    case FieldDescriptor::CPPTYPE_MESSAGE:
      (*variables)["val_cpp"] = FieldMessageTypeName(val);
      (*variables)["wrapper"] = "EntryWrapper";
      break;
    case FieldDescriptor::CPPTYPE_ENUM:
      (*variables)["val_cpp"] = ClassName(val->enum_type(), true);
      (*variables)["wrapper"] = "EnumEntryWrapper";
      break;
    default:
      (*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type());
      (*variables)["wrapper"] = "EntryWrapper";
  }
  (*variables)["key_wire_type"] =
      "::google::protobuf::internal::WireFormatLite::TYPE_" +
      ToUpper(DeclaredTypeMethodName(key->type()));
  (*variables)["val_wire_type"] =
      "::google::protobuf::internal::WireFormatLite::TYPE_" +
      ToUpper(DeclaredTypeMethodName(val->type()));
  (*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
  (*variables)["number"] = SimpleItoa(descriptor->number());
  (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));

  if (HasDescriptorMethods(descriptor->file(), options)) {
    (*variables)["lite"] = "";
  } else {
    (*variables)["lite"] = "Lite";
  }

  if (!IsProto3Field(descriptor) &&
      val->type() == FieldDescriptor::TYPE_ENUM) {
    const EnumValueDescriptor* default_value = val->default_value_enum();
    (*variables)["default_enum_value"] = Int32ToString(default_value->number());
  } else {
    (*variables)["default_enum_value"] = "0";
  }
}

MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
                                     const Options& options)
    : FieldGenerator(options),
      descriptor_(descriptor),
      dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
  SetMessageVariables(descriptor, &variables_, options);
}

MapFieldGenerator::~MapFieldGenerator() {}

void MapFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
  printer->Print(variables_,
                 "::google::protobuf::internal::MapField$lite$<\n"
                 "    $map_classname$,\n"
                 "    $key_cpp$, $val_cpp$,\n"
                 "    $key_wire_type$,\n"
                 "    $val_wire_type$,\n"
                 "    $default_enum_value$ > $name$_;\n");
}

void MapFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
  printer->Print(
      variables_,
      "$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
      "    $name$() const;\n");
  printer->Annotate("name", descriptor_);
  printer->Print(variables_,
                 "$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
                 "    ${$mutable_$name$$}$();\n");
  printer->Annotate("{", "}", descriptor_);
}

void MapFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
  printer->Print(variables_,
      "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
      "$classname$::$name$() const {\n"
      "  // @@protoc_insertion_point(field_map:$full_name$)\n"
      "  return $name$_.GetMap();\n"
      "}\n"
      "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
      "$classname$::mutable_$name$() {\n"
      "  // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
      "  return $name$_.MutableMap();\n"
      "}\n");
}

void MapFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_.Clear();\n");
}

void MapFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
}

void MapFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
  printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
}

void MapFieldGenerator::
GenerateCopyConstructorCode(io::Printer* printer) const {
  GenerateConstructorCode(printer);
  GenerateMergingCode(printer);
}

void MapFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
    const FieldDescriptor* key_field =
        descriptor_->message_type()->FindFieldByName("key");
  const FieldDescriptor* value_field =
      descriptor_->message_type()->FindFieldByName("value");
  bool using_entry = false;
  string key;
  string value;
  if (IsProto3Field(descriptor_) ||
      value_field->type() != FieldDescriptor::TYPE_ENUM) {
    printer->Print(
        variables_,
        "$map_classname$::Parser< ::google::protobuf::internal::MapField$lite$<\n"
        "    $map_classname$,\n"
        "    $key_cpp$, $val_cpp$,\n"
        "    $key_wire_type$,\n"
        "    $val_wire_type$,\n"
        "    $default_enum_value$ >,\n"
        "  ::google::protobuf::Map< $key_cpp$, $val_cpp$ > >"
        " parser(&$name$_);\n"
        "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
        "    input, &parser));\n");
    key = "parser.key()";
    value = "parser.value()";
  } else {
    using_entry = true;
    key = "entry->key()";
    value = "entry->value()";
    printer->Print(variables_,
        "::google::protobuf::scoped_ptr<$map_classname$> entry($name$_.NewEntry());\n");
    printer->Print(variables_,
        "{\n"
        "  ::std::string data;\n"
        "  DO_(::google::protobuf::internal::WireFormatLite::ReadString(input, &data));\n"
        "  DO_(entry->ParseFromString(data));\n"
        "  if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
        "    (*mutable_$name$())[entry->key()] =\n"
        "        static_cast< $val_cpp$ >(*entry->mutable_value());\n"
        "  } else {\n");
    if (HasDescriptorMethods(descriptor_->file(), options_)) {
      printer->Print(variables_,
          "    mutable_unknown_fields()"
          "->AddLengthDelimited($number$, data);\n");
    } else {
      printer->Print(variables_,
          "    unknown_fields_stream.WriteVarint32($tag$u);\n"
          "    unknown_fields_stream.WriteVarint32(\n"
          "        static_cast< ::google::protobuf::uint32>(data.size()));\n"
          "    unknown_fields_stream.WriteString(data);\n");
    }

    printer->Print(variables_,
        "  }\n"
        "}\n");
  }

  if (key_field->type() == FieldDescriptor::TYPE_STRING) {
    GenerateUtf8CheckCodeForString(
        key_field, options_, true, variables_,
        StrCat(key, ".data(), static_cast<int>(", key, ".length()),\n").data(),
        printer);
  }
  if (value_field->type() == FieldDescriptor::TYPE_STRING) {
    GenerateUtf8CheckCodeForString(
        value_field, options_, true, variables_,
        StrCat(value, ".data(), static_cast<int>(", value, ".length()),\n")
            .data(),
        printer);
  }

  // If entry is allocated by arena, its desctructor should be avoided.
  if (using_entry && SupportsArenas(descriptor_)) {
    printer->Print(variables_,
        "if (entry->GetArena() != NULL) entry.release();\n");
  }
}

static void GenerateSerializationLoop(io::Printer* printer,
                                      const std::map<string, string>& variables,
                                      bool supports_arenas,
                                      const string& utf8_check,
                                      const string& loop_header,
                                      const string& ptr,
                                      bool loop_via_iterators) {
  printer->Print(variables,
      StrCat("::google::protobuf::scoped_ptr<$map_classname$> entry;\n",
             loop_header, " {\n").c_str());
  printer->Indent();

  printer->Print(variables, StrCat(
      "entry.reset($name$_.New$wrapper$(\n"
      "    ", ptr, "->first, ", ptr, "->second));\n"
      "$write_entry$;\n").c_str());

  // If entry is allocated by arena, its desctructor should be avoided.
  if (supports_arenas) {
    printer->Print(
        "if (entry->GetArena() != NULL) {\n"
        "  entry.release();\n"
        "}\n");
  }

  if (!utf8_check.empty()) {
    // If loop_via_iterators is true then ptr is actually an iterator, and we
    // create a pointer by prefixing it with "&*".
    printer->Print(
        StrCat(utf8_check, "(", (loop_via_iterators ? "&*" : ""), ptr, ");\n")
            .c_str());
  }

  printer->Outdent();
  printer->Print(
      "}\n");
}

void MapFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
  std::map<string, string> variables(variables_);
  variables["write_entry"] = "::google::protobuf::internal::WireFormatLite::Write" +
                             variables["stream_writer"] + "(\n            " +
                             variables["number"] + ", *entry, output)";
  variables["deterministic"] = "output->IsSerializationDeterministic()";
  GenerateSerializeWithCachedSizes(printer, variables);
}

void MapFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
  std::map<string, string> variables(variables_);
  variables["write_entry"] =
      "target = ::google::protobuf::internal::WireFormatLite::\n"
      "                   InternalWrite" + variables["declared_type"] +
      "NoVirtualToArray(\n                       " + variables["number"] +
      ", *entry, deterministic, target);\n";
  variables["deterministic"] = "deterministic";
  GenerateSerializeWithCachedSizes(printer, variables);
}

void MapFieldGenerator::GenerateSerializeWithCachedSizes(
    io::Printer* printer, const std::map<string, string>& variables) const {
  printer->Print(variables,
      "if (!this->$name$().empty()) {\n");
  printer->Indent();
  const FieldDescriptor* key_field =
      descriptor_->message_type()->FindFieldByName("key");
  const FieldDescriptor* value_field =
      descriptor_->message_type()->FindFieldByName("value");
  const bool string_key = key_field->type() == FieldDescriptor::TYPE_STRING;
  const bool string_value = value_field->type() == FieldDescriptor::TYPE_STRING;

  printer->Print(variables,
      "typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_pointer\n"
      "    ConstPtr;\n");
  if (string_key) {
    printer->Print(variables,
        "typedef ConstPtr SortItem;\n"
        "typedef ::google::protobuf::internal::"
        "CompareByDerefFirst<SortItem> Less;\n");
  } else {
    printer->Print(variables,
        "typedef ::google::protobuf::internal::SortItem< $key_cpp$, ConstPtr > "
        "SortItem;\n"
        "typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;\n");
  }
  string utf8_check;
  if (string_key || string_value) {
    printer->Print(
        "struct Utf8Check {\n"
        "  static void Check(ConstPtr p) {\n");
    printer->Indent();
    printer->Indent();
    if (string_key) {
      GenerateUtf8CheckCodeForString(
          key_field, options_, false, variables,
          "p->first.data(), static_cast<int>(p->first.length()),\n", printer);
    }
    if (string_value) {
      GenerateUtf8CheckCodeForString(
          value_field, options_, false, variables,
          "p->second.data(), static_cast<int>(p->second.length()),\n", printer);
    }
    printer->Outdent();
    printer->Outdent();
    printer->Print(
        "  }\n"
        "};\n");
    utf8_check = "Utf8Check::Check";
  }

  printer->Print(variables,
      "\n"
      "if ($deterministic$ &&\n"
      "    this->$name$().size() > 1) {\n"
      "  ::google::protobuf::scoped_array<SortItem> items(\n"
      "      new SortItem[this->$name$().size()]);\n"
      "  typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n"
      "  size_type n = 0;\n"
      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
      "      it = this->$name$().begin();\n"
      "      it != this->$name$().end(); ++it, ++n) {\n"
      "    items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);\n"
      "  }\n"
      "  ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n");
  printer->Indent();
  GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_),
      utf8_check, "for (size_type i = 0; i < n; i++)",
      string_key ? "items[static_cast<ptrdiff_t>(i)]" :
                   "items[static_cast<ptrdiff_t>(i)].second", false);
  printer->Outdent();
  printer->Print(
      "} else {\n");
  printer->Indent();
  GenerateSerializationLoop(
      printer, variables, SupportsArenas(descriptor_), utf8_check,
      "for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
      "    it = this->$name$().begin();\n"
      "    it != this->$name$().end(); ++it)",
      "it", true);
  printer->Outdent();
  printer->Print("}\n");
  printer->Outdent();
  printer->Print("}\n");
}

void MapFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
  printer->Print(variables_,
      "total_size += $tag_size$ *\n"
      "    ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
      "{\n"
      "  ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
      "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
      "      it = this->$name$().begin();\n"
      "      it != this->$name$().end(); ++it) {\n");

  // If entry is allocated by arena, its desctructor should be avoided.
  if (SupportsArenas(descriptor_)) {
    printer->Print(variables_,
        "    if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
        "      entry.release();\n"
        "    }\n");
  }

  printer->Print(variables_,
      "    entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
      "    total_size += ::google::protobuf::internal::WireFormatLite::\n"
      "        $declared_type$SizeNoVirtual(*entry);\n"
      "  }\n");

  // If entry is allocated by arena, its desctructor should be avoided.
  if (SupportsArenas(descriptor_)) {
    printer->Print(variables_,
        "  if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
        "    entry.release();\n"
        "  }\n");
  }

  printer->Print("}\n");
}

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

// Test that proto2 compiler can generate valid code when the enum value
// is INT_MAX. Note that this is a compile-only test and this proto is not
// referenced in any C++ code.
syntax = "proto2";

package protobuf_unittest;

message TestLargeEnumValue {
  enum EnumWithLargeValue {
    VALUE_1 = 1;
    VALUE_MAX = 0x7fffffff;
  }
}


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.

#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__

#include <map>
#include <string>
#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.h>

namespace google {
namespace protobuf {
  namespace io {
    class Printer;             // printer.h
  }
}

namespace protobuf {
namespace compiler {
namespace cpp {

class ServiceGenerator {
 public:
  // See generator.cc for the meaning of dllexport_decl.
  explicit ServiceGenerator(const ServiceDescriptor* descriptor,
                            const Options& options);
  ~ServiceGenerator();

  // Header stuff.

  // Generate the class definitions for the service's interface and the
  // stub implementation.
  void GenerateDeclarations(io::Printer* printer);

  // Source file stuff.

  // Generate code that initializes the global variable storing the service's
  // descriptor.
  void GenerateDescriptorInitializer(io::Printer* printer, int index);

  // Generate implementations of everything declared by GenerateDeclarations().
  void GenerateImplementation(io::Printer* printer);

 private:
  enum RequestOrResponse { REQUEST, RESPONSE };
  enum VirtualOrNon { VIRTUAL, NON_VIRTUAL };

  // Header stuff.

  // Generate the service abstract interface.
  void GenerateInterface(io::Printer* printer);

  // Generate the stub class definition.
  void GenerateStubDefinition(io::Printer* printer);

  // Prints signatures for all methods in the
  void GenerateMethodSignatures(VirtualOrNon virtual_or_non,
                                io::Printer* printer);

  // Source file stuff.

  // Generate the default implementations of the service methods, which
  // produce a "not implemented" error.
  void GenerateNotImplementedMethods(io::Printer* printer);

  // Generate the CallMethod() method of the service.
  void GenerateCallMethod(io::Printer* printer);

  // Generate the Get{Request,Response}Prototype() methods.
  void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);

  // Generate the stub's implementations of the service methods.
  void GenerateStubMethods(io::Printer* printer);

  const ServiceDescriptor* descriptor_;
  std::map<string, string> vars_;

  int index_in_metadata_;

  friend class FileGenerator;
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
};

}  // namespace cpp
}  // namespace compiler
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_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.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#include <google/protobuf/compiler/cpp/cpp_generator.h>

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

#include <google/protobuf/compiler/cpp/cpp_file.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>

namespace google {
namespace protobuf {
namespace compiler {
namespace cpp {

CppGenerator::CppGenerator() {}
CppGenerator::~CppGenerator() {}

bool CppGenerator::Generate(const FileDescriptor* file,
                            const string& parameter,
                            GeneratorContext* generator_context,
                            string* error) const {
  std::vector<std::pair<string, string> > options;
  ParseGeneratorParameter(parameter, &options);

  // -----------------------------------------------------------------
  // parse generator options

  // TODO(kenton):  If we ever have more options, we may want to create a
  //   class that encapsulates them which we can pass down to all the
  //   generator classes.  Currently we pass dllexport_decl down to all of
  //   them via the constructors, but we don't want to have to add another
  //   constructor parameter for every option.

  // If the dllexport_decl option is passed to the compiler, we need to write
  // it in front of every symbol that should be exported if this .proto is
  // compiled into a Windows DLL.  E.g., if the user invokes the protocol
  // compiler as:
  //   protoc --cpp_out=dllexport_decl=FOO_EXPORT:outdir foo.proto
  // then we'll define classes like this:
  //   class FOO_EXPORT Foo {
  //     ...
  //   }
  // FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
  // __declspec(dllimport) depending on what is being compiled.
  //
  Options file_options;
  bool split_source = false;
  for (int i = 0; i < options.size(); i++) {
    if (options[i].first == "dllexport_decl") {
      file_options.dllexport_decl = options[i].second;
    } else if (options[i].first == "safe_boundary_check") {
      file_options.safe_boundary_check = true;
    } else if (options[i].first == "annotate_headers") {
      file_options.annotate_headers = true;
    } else if (options[i].first == "annotation_pragma_name") {
      file_options.annotation_pragma_name = options[i].second;
    } else if (options[i].first == "annotation_guard_name") {
      file_options.annotation_guard_name = options[i].second;
    } else if (options[i].first == "lite") {
      file_options.enforce_lite = true;
    } else if (options[i].first == "lite_implicit_weak_fields") {
      file_options.lite_implicit_weak_fields = true;
    } else if (options[i].first == "table_driven_parsing") {
      file_options.table_driven_parsing = true;
    } else if (options[i].first == "table_driven_serialization") {
      file_options.table_driven_serialization = true;
    } else if (options[i].first == "split_source") {
      split_source = true;
    } else {
      *error = "Unknown generator option: " + options[i].first;
      return false;
    }
  }

  // -----------------------------------------------------------------

  string basename = StripProto(file->name());

  FileGenerator file_generator(file, file_options);

  // Generate header(s).
  if (file_options.proto_h) {
    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
        generator_context->Open(basename + ".proto.h"));
    GeneratedCodeInfo annotations;
    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
        &annotations);
    string info_path = basename + ".proto.h.meta";
    io::Printer printer(output.get(), '$', file_options.annotate_headers
                                               ? &annotation_collector
                                               : NULL);
    file_generator.GenerateProtoHeader(
        &printer, file_options.annotate_headers ? info_path : "");
    if (file_options.annotate_headers) {
      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
          generator_context->Open(info_path));
      annotations.SerializeToZeroCopyStream(info_output.get());
    }
  }

  {
    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
        generator_context->Open(basename + ".pb.h"));
    GeneratedCodeInfo annotations;
    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
        &annotations);
    string info_path = basename + ".pb.h.meta";
    io::Printer printer(output.get(), '$', file_options.annotate_headers
                                               ? &annotation_collector
                                               : NULL);
    file_generator.GeneratePBHeader(
        &printer, file_options.annotate_headers ? info_path : "");
    if (file_options.annotate_headers) {
      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
          generator_context->Open(info_path));
      annotations.SerializeToZeroCopyStream(info_output.get());
    }
  }

  // Generate cc file.
  if (split_source) {
    {
      // This is the global .cc file, containing enum/services/tables/reflection
      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
          generator_context->Open(basename + ".pb.cc"));
      io::Printer printer(output.get(), '$');
      file_generator.GenerateGlobalSource(&printer);
    }
    for (int i = 0; i < file_generator.NumMessages(); i++) {
      // TODO(gerbens) Agree on naming scheme.
      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
          generator_context->Open(basename + "." + SimpleItoa(i) + ".cc"));
      io::Printer printer(output.get(), '$');
      file_generator.GenerateSourceForMessage(i, &printer);
    }
  } else {
    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
        generator_context->Open(basename + ".pb.cc"));
    io::Printer printer(output.get(), '$');
    file_generator.GenerateSource(&printer);
  }

  return true;
}

}  // namespace cpp
}  // namespace compiler
}  // namespace protobuf
}  // namespace google