void FieldGenerator::addMethod(google::protobuf::io::Printer& p) {
  p.Print(variables_,
          "$i$$type$.prototype.add$capital_name$ = function(value) {\n"
          "$i$  if (typeof value == 'undefined') {\n"
          "$i$    throw new TypeError('Cannot add undefined.');\n"
          "$i$  }\n");

  if (is_message_) {
    p.Print(variables_,
            "$i$  var msg = "
            "this._maybeConvertToMessage($message_scope$$message_type$, "
            "value);\n"
            "$i$  this._$name$.push(msg);\n"
            "$i$  this._fields[$index$].push(msg._raw);\n");
    messageAssertLength(p);
  } else if (is_typed_array_) {
    p.Print(variables_,
            "$i$  var newArray = this._ensureLength(this._fields[$index$]);\n"
            "$i$  if (newArray) {\n"
            "$i$    this._fields[$index$] = newArray;\n"
            "$i$  }\n"
            "$i$  this._fields[$index$][this._fields[$index$].length - 1] "
            "= value;\n");
  } else {
    p.Print(variables_, "$i$  this._fields[$index$].push(value);\n");
  }

  p.Print(variables_, "$i$};\n");
}
void FieldGenerator::genClear(google::protobuf::io::Printer& p) {
  if (is_message_) {
    p.Print(variables_,
            "$i$this._fields[$index$] = undefined;\n"
            "$i$this._$name$ = undefined;\n");
  } else {
    p.Print(variables_, "$i$this._fields[$index$] = $default$;\n");
  }
}
void FieldGenerator::genGet(google::protobuf::io::Printer& p) {
  if (is_message_) {
    p.Print(variables_, "$i$return this._$name$;\n");
  } else {
    p.Print(variables_,
            "$i$return typeof this._fields[$index$] == 'undefined' ? "
            "$default$ : this._fields[$index$];\n");
  }
}
void RpcGenerator::generateCallMethod(const google::protobuf::ServiceDescriptor *descriptor,
                                   google::protobuf::io::Printer &printer) const
{
  printer.Print("void $service$::callMethod(const string &methodName, const Message* request, Message* response, Closure* done)\n",
                "service", descriptor->full_name());
  printer.Print("{\n");
  printer.Print("\n");
  printer.Print("}\n");
}
void FieldGenerator::generateOptionalProperty(
    google::protobuf::io::Printer& p) {
  p.Print(variables_, "$i$$type$.prototype.get$capital_name$ = function() {\n");

  if (oneof_) {
    p.Print(variables_,
            "$i$  if (this.$oneof_camel$Case != "
            "type.$oneof_capital$Case.$all_capital_name$) {\n"
            "$i$    return undefined;\n"
            "$i$  } else {\n");
    indentUp();
    indentUp();
    genGet(p);
    indentDown();
    indentDown();
    // TODO: Currently, if undefined is passed to oneof field, the entire oneof
    // is cleared. It may better to ignore undefined value if the4 field is not
    // the active value at the time.
    p.Print(variables_,
            "    }\n"
            "  };\n"
            "$i$$type$.prototype.set$capital_name$ = function(value) {\n"
            "$i$  this.clear$oneof_capital$();\n"
            "$i$  this._oneofs[$oneof_index$] = "
            "type.$oneof_capital$Case.$all_capital_name$;\n");
  } else {
    indentUp();
    genGet(p);
    indentDown();
    p.Print(variables_,
            "$i$}\n"
            "$i$$type$.prototype.set$capital_name$ = function(value) {\n");
  }

  indentUp();
  genSet(p);
  indentDown();

  p.Print(variables_,
          "$i$};\n"
          "$i$$type$.prototype.clear$capital_name$ = function() {\n");
  indentUp();
  genClear(p);
  indentDown();
  if (oneof_) {
    p.Print(variables_,
            "$i$  if (this.$oneof_camel$Case == "
            "type.$oneof_capital$Case.$all_capital_name$) {\n"
            "$i$    this._oneofs[$oneof_index$] = "
            "type.$oneof_capital$Case.$oneof_all_capital$_NOT_SET;\n"
            "$i$  }\n");
  }
  p.Print(variables_,
          "$i$};\n"
          "$i$Object.defineProperty(type.prototype, '$name$', {\n"
          "$i$  get: $type$.prototype.get$capital_name$,\n"
          "$i$  set: $type$.prototype.set$capital_name$,\n"
          "$i$});\n\n");
}
void FieldGenerator::reserveMethod(google::protobuf::io::Printer& p) {
  p.Print(variables_,
          "$i$$type$.prototype.reserve$capital_name$ = function(len) {\n");

  if (is_typed_array_) {
    p.Print(variables_,
            "$i$  var blen = len * $typed_array$.BYTES_PER_ELEMENT;\n"
            "$i$  if (this._fields[$index$].buffer.byteLength < blen) {\n"
            "$i$    var buf = new ArrayBuffer(blen);\n"
            "$i$    var newArray = new $typed_array$(buf, 0, "
            "this._fields[$index$].length);\n"
            "$i$    newArray.set(this._fields[$index$]);\n"
            "$i$    this._fields[$index$] = newArray;\n"
            "$i$  }\n");
  } else {
    p.Print(variables_, "$i$  // NOOP");
  }
  p.Print(variables_, "$i$};\n");
}
void FieldGenerator::genSet(google::protobuf::io::Printer& p) {
  if (is_message_) {
    p.Print(
        variables_,
        "$i$var msg = "
        "this._maybeConvertToMessage($message_scope$$message_type$, value);\n"
        "$i$this._$name$ = msg;\n"
        "$i$this._fields[$index$] = msg._raw;\n");
  } else {
    // TODO: Emit error if the argument is not of correct type.
    p.Print(variables_,
            // We check for undefined in getters
            //"$i$if (typeof value == 'undefined') {\n"
            //"$i$  this._fields[$index$] = $default$;\n"
            //"$i$} else {\n"
            //"$i$  this._fields[$index$] = value;\n"
            //"$i$}\n");
            "$i$  this._fields[$index$] = value;\n");
  }
}
void FieldGenerator::resizeMethod(google::protobuf::io::Printer& p) {
  p.Print(variables_,
          "$i$$type$.prototype.resize$capital_name$ = function(len) {\n");

  if (is_typed_array_) {
    p.Print(
        variables_,
        "$i$  var newArray = this._ensureLength(this._fields[$index$], len);\n"
        "$i$  if (newArray) {\n"
        "$i$    newArray.set(this._fields[$index$]);\n"
        "$i$    this._fields[$index$] = newArray;\n"
        "$i$  }\n"
        "$i$  console.assert(this._fields[$index$].length >= len);\n");
  } else if (!is_message_) {
    p.Print(variables_, "$i$  this._fields[$index$].length = values.length;\n");
  } else {
    p.Print(variables_, "$i$  // NOOP");
  }
  p.Print(variables_, "$i$};\n");
}
void FieldGenerator::countMethod(google::protobuf::io::Printer& p) {
  p.Print(variables_, "$i$var $name$Count = function() {\n");

  if (is_message_) {
    if (is_message_) messageAssertLength(p);
    p.Print(variables_, "$i$  return this._$name$.length;\n");
  } else {
    p.Print(variables_, "$i$  return this._fields[$index$].length;\n");
  }

  p.Print(variables_,
          "$i$};\n"
          "$i$Object.defineProperties($type$.prototype, {\n"
          "$i$  $name$Count: { get: $name$Count },\n"
          "$i$  $name$Size: { get: $name$Count },\n"
          "$i$  $name$Length: { get: $name$Count },\n"
          "$i$});\n"
          "$i$$type$.prototype.get$capital_name$Count = $name$Count;\n"
          "$i$$type$.prototype.get$capital_name$Size = $name$Count;\n"
          "$i$$type$.prototype.get$capital_name$Length = $name$Count;\n");
}
void RpcGenerator::generateSentVtkBlock(const string &variableName,
    const string &channelName, const google::protobuf::Descriptor *descriptor,
    google::protobuf::io::Printer &printer) const
{
  for(int i=0; i< descriptor->field_count(); i++) {
    const FieldDescriptor *field = descriptor->field(i);

    if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
      string messageTypeName = field->message_type()->full_name();

      if (messageTypeName.find("vtk.") == 0) {
        string vtkType = messageTypeName.substr(4);

        std::ostringstream stream;
        stream << "obj" << i;
        string var = stream.str();
        printer.Print("if ($variableName$->has_$fieldName$()) {\n",
          "variableName", variableName, "fieldName", field->lowercase_name());
        printer.Indent();
        printer.Print("$vtkType$ *$var$ = ", "vtkType", vtkType, "var", var);
        printer.Print("$variableName$->$fieldName$().get();\n", "variableName",
            variableName, "fieldName", field->lowercase_name());

        printer.Print("if ($var$) {\n", "var", var);
        printer.Indent();

        std::map<string, string> variables;
        variables["var"] = var;
        variables["channelName"] = channelName;

        this->generateErrorCheck("$channelName$->send($var$)", variables,
            printer);
        printer.Outdent();
        printer.Print("}\n");
        printer.Outdent();
        printer.Print("}\n");
      }
    }
  }
}
void RpcGenerator::generateErrorCheck(const char *call,
    std::map< string, string > &variables,
    google::protobuf::io::Printer &printer,  const char *blockText) const
{
  string code;
  io::StringOutputStream stream(&code);
  io::Printer tmpPrinter(&stream, '$');
  tmpPrinter.Print("if (!$call$) {\n", "call", call);
  tmpPrinter.Indent();

  if (blockText)
    tmpPrinter.Print("$blockText$", "blockText", blockText);
  else
    tmpPrinter.Print("return;\n");

  tmpPrinter.Outdent();
  tmpPrinter.Print("}\n");

  printer.Print(variables, code.c_str());
}
void RpcGenerator::generateReceiveExternalBlock(const string &variableName,
    const string &channelName, const google::protobuf::Descriptor *descriptor,
    google::protobuf::io::Printer &printer) const
{
  bool hasExternalTypes = false;

  string code;
  io::StringOutputStream stream(&code);
  io::Printer tmpPrinter(&stream, '$');

  for(int i=0; i< descriptor->field_count(); i++) {
    const FieldDescriptor *field = descriptor->field(i);

    if (field->type() == FieldDescriptor::TYPE_MESSAGE)
    {
      string messageTypeName = field->message_type()->full_name();

      if (messageTypeName.find("external.") == 0) {
        hasExternalTypes = true;

        string externalClass = externalTypeToClass(messageTypeName);

        std::ostringstream objStream;
        objStream << "obj" << i;
        string objVar = objStream.str();

        std::ostringstream deserializerStream;
        deserializerStream << "deserializer" << i;
        string deserializerVar = deserializerStream.str();

        std::ostringstream dataStream;
        dataStream << "data" << i;
        string dataVar = dataStream.str();

        tmpPrinter.Print("if ($variableName$->has_$fieldName$()) {\n",
          "variableName", "tmp", "fieldName", field->lowercase_name());
        tmpPrinter.Indent();

        tmpPrinter.Print("::ProtoCall::Runtime::RpcVoidData $data$;\n", "data",
                         dataVar);

        std::map<string, string> variables;
        variables["var"] = dataVar;
        variables["channelName"] = channelName;
        this->generateErrorCheck("$channelName$->receive(&$var$)", variables,
                    tmpPrinter);

        tmpPrinter.Print("$externalClass$ *$objVar$ = tmp->$field$().get();\n",
            "externalClass", externalClass, "objVar", objVar, "field", field->lowercase_name());
        tmpPrinter.Print("bool allocated = false;\n");
        tmpPrinter.Print("if (!$objVar$) {\n", "objVar", objVar);
        tmpPrinter.Indent();
        tmpPrinter.Print("$objVar$ = new $externalClass$();\n",
            "objVar", objVar, "externalClass", externalClass);
        tmpPrinter.Print("allocated = true;\n");
        tmpPrinter.Outdent();
        tmpPrinter.Print("}\n");

        tmpPrinter.Print("$externalClass$Deserializer $deserializerVar$($objVar$);\n",
            "externalClass", externalClass, "deserializerVar", deserializerVar,
            "objVar", objVar);
        variables["deserializerVar"] = deserializerVar;
        this->generateErrorCheck("$deserializerVar$.deserialize($var$.data(), $var$.size())", variables,
            tmpPrinter, "$channelName$->setErrorString(\"Deserialization failed\");return;\n");

        variables.clear();
        variables["var"] = objVar;
        variables["channelName"] = channelName;
        variables["objVar"] = objVar;

        tmpPrinter.Print("if (allocated)\n");
        tmpPrinter.Indent();
        tmpPrinter.Print("tmp->mutable_$field$()->set_allocated($objVar$);\n",
            "field", field->lowercase_name(), "objVar", objVar);
        tmpPrinter.Outdent();
        tmpPrinter.Outdent();
        tmpPrinter.Print("}\n");
      }
    }
  }

  if (hasExternalTypes) {
    printer.Print("::google::protobuf::Message *mutableRequest "
        "= const_cast< google::protobuf::Message *>($variableName$);\n",
        "variableName", variableName);
    printer.Print("$inputType$ *tmp ="
        "static_cast<$inputType$ *>(mutableRequest);\n",
        "inputType", descriptor->name());
    printer.Print(code.c_str());
  }
}
void RpcGenerator::generateSentExternalBlock(const string &variableName,
    const string &channelName, const google::protobuf::Descriptor *descriptor,
    google::protobuf::io::Printer &printer) const
{
  for(int i=0; i< descriptor->field_count(); i++) {
    const FieldDescriptor *field = descriptor->field(i);

    if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
      string messageTypeName = field->message_type()->full_name();

      if (messageTypeName.find("external.") == 0) {
        string externalClass = externalTypeToClass(messageTypeName);

        std::ostringstream stream;
        stream << "obj" << i;
        string var = stream.str();
        printer.Print("if ($variableName$->has_$fieldName$()) {\n",
          "variableName", variableName, "fieldName", field->lowercase_name());
        printer.Indent();
        printer.Print("$externalClass$ *$var$ = ", "externalClass", externalClass, "var", var);
        printer.Print("$variableName$->$fieldName$().get();\n", "variableName",
            variableName, "fieldName", field->lowercase_name());

        printer.Print("if ($var$) {\n", "var", var);
        printer.Indent();

        printer.Print("$externalClass$Serializer serializer($var$);\n",
            "externalClass", externalClass, "var", var);
        printer.Print("const size_t size = serializer.size();\n");
        std::map<string, string> variables;
        variables["channelName"] = channelName;
        printer.Print("::ProtoCall::Runtime::RpcVoidData data(size);\n");
        this->generateErrorCheck("serializer.serialize(data.data(), size)", variables,
            printer, "$channelName$->setErrorString(\"Serialization failed\");return;\n");

        this->generateErrorCheck("$channelName$->send(&data)", variables,
            printer);
        printer.Outdent();
        printer.Print("}\n");
        printer.Outdent();
        printer.Print("}\n");
      }
    }
  }
}
void RpcGenerator::generateReceiveVtkBlock(const string &variableName,
    const string &channelName, const google::protobuf::Descriptor *descriptor,
    google::protobuf::io::Printer &printer) const
{
  bool hasVtkTypes = false;

  string code;
  io::StringOutputStream stream(&code);
  io::Printer tmpPrinter(&stream, '$');

  for(int i=0; i< descriptor->field_count(); i++) {
    const FieldDescriptor *field = descriptor->field(i);

    if (field->type() == FieldDescriptor::TYPE_MESSAGE)
    {
      string messageTypeName = field->message_type()->full_name();

      if (messageTypeName.find("vtk.") == 0) {
        hasVtkTypes = true;

        string vtkType = messageTypeName.substr(4);

        std::ostringstream stream;
        stream << "obj" << i;
        string var = stream.str();

        tmpPrinter.Print("if ($variableName$->has_$fieldName$()) {\n",
          "variableName", "tmp", "fieldName", field->lowercase_name());
        tmpPrinter.Indent();
        tmpPrinter.Print("$vtkType$ *$var$ = tmp->$fieldName$().get();\n",
            "var", var, "vtkType", vtkType, "fieldName", field->lowercase_name());
        tmpPrinter.Print("bool allocated = false;\n");
        tmpPrinter.Print("if (!$var$) {\n", "var", var);
        tmpPrinter.Indent();
        tmpPrinter.Print("$var$ = $vtkType$::New();\n",
            "var", var, "vtkType", vtkType);
        tmpPrinter.Print("allocated = true;\n");
        tmpPrinter.Outdent();
        tmpPrinter.Print("}");

        std::map<string, string> variables;
        variables["var"] = var;
        variables["channelName"] = channelName;
        this->generateErrorCheck("$channelName$->receive($var$)", variables,
            tmpPrinter, "$var$->Delete();return;\n");

        tmpPrinter.Print("if (allocated)\n");
        tmpPrinter.Indent();
        tmpPrinter.Print("tmp->mutable_$field$()->set_allocated($var$);\n",
            "field", field->lowercase_name(), "var", var);
        tmpPrinter.Outdent();
        tmpPrinter.Outdent();
        tmpPrinter.Print("}\n");
      }
    }
  }

  if (hasVtkTypes) {
    printer.Print("::google::protobuf::Message *mut "
        "= const_cast< google::protobuf::Message *>($variableName$);\n",
        "variableName", variableName);
    printer.Print("$inputType$ *tmp ="
        "static_cast<$inputType$ *>(mut);\n",
        "inputType", descriptor->name());
    printer.Print(code.c_str());
  }
}
void RpcGenerator::generateRelyMethod(
    const google::protobuf::ServiceDescriptor *descriptor,
    google::protobuf::io::Printer &printer) const
{
  printer.Print("void $service$_Dispatcher::$replySignature$\n{\n",
      "service", descriptor->full_name(), "replySignature",
      replySignature);

  printer.Indent();

  printer.Print("switch(info.methodId) {\n");
  printer.Indent();

  for(int j=0; j<descriptor->method_count(); j++) {
    const MethodDescriptor *method = descriptor->method(j);
    string methodName = method->full_name();
    int methodId = RpcPlugin::generateExtensionNumber(methodName);
    string inputTypeName = method->input_type()->name();
    string outputTypeName = method->output_type()->name();

    if (isVoidType(outputTypeName))
      continue;

    ostringstream methodIdStr;
    methodIdStr << methodId;
    printer.Print("case $methodId$ : {\n", "methodId", methodIdStr.str());
    printer.Indent();
    printer.Print("// $methodName$\n", "methodName",  methodName);

    printer.Print("// Prepare the response\n");
    printer.Print("rpc::Message msg;\n");
    printer.Print("rpc::Response *response = msg.mutable_response();\n");
    printer.Print("uint64 requestId = info.requestMessageEnvelope->request().id();\n");
    printer.Print("response->set_id(requestId);\n");
    string extensionName = toExtensionName(method->full_name());
    std::ostringstream var;
    var << "tmp" << j;

    printer.Print("$responseType$ *$var$ = static_cast<$responseType$ *>(info.response);\n",
        "responseType", outputTypeName, "var", var.str());

    // Add error info
    printer.Print("if ($var$->hasError()) {\n", "var", var.str());
    printer.Indent();
    printer.Print("response->set_errorstring($var$->errorString());\n", "var", var.str());
    printer.Print("response->set_errorcode($var$->errorCode());\n", "var", var.str());
    printer.Outdent();
    printer.Print("}\n");
    printer.Print("response->SetAllocatedExtension($extensionName$, $var$);\n",
        "extensionName", extensionName + "_response", "var", var.str());
    printer.Print("// Make sure request is cleaned up\n");
    printer.Print("std::auto_ptr<rpc::Message> request;\n");
    printer.Print("request.reset(info.requestMessageEnvelope);\n");
    this->generateErrorCheck("info.replyChannel->send(&msg)", printer);

    // send any VTK object we need to.
    this->generateSentVtkBlock(var.str(), "info.replyChannel",
        method->output_type(), printer);

    // send any external objects we need to.
    this->generateSentExternalBlock(var.str(), "info.replyChannel",
        method->output_type(), printer);

    printer.Outdent();
    printer.Print("break;\n");
    printer.Print("}\n");
  }

  printer.Print("default:\n");
  printer.Indent();
  printer.Print("// TODO error case\n");
  printer.Print("info.replyChannel->setErrorString(\"No reply case for messageId: \" + info.methodId);\n");
  printer.Outdent();
  printer.Outdent();
  printer.Print("}\n");
  printer.Outdent();
  printer.Print("}\n");
}
void RpcGenerator::generateImplementsMethod(const google::protobuf::ServiceDescriptor *descriptor,
    google::protobuf::io::Printer &printer) const
{
  printer.PrintRaw(implementsReturnType);


  printer.Print(" $serviceName$_Dispatcher::$implementsSignature$\n{\n",
      "serviceName", descriptor->name(),
      "implementsSignature",  implementsSignature);
  printer.Indent();
  printer.Print("// This is NOT thread safe ...\n");
  printer.Print("static $implementsReturnType$ methodIds;\n",
      "implementsReturnType", implementsReturnType);
  printer.Print("static bool init = true;\n");
  printer.Print("if (init) {\n");
  printer.Indent();
  for(int j=0; j<descriptor->method_count(); j++) {
    const MethodDescriptor *method = descriptor->method(j);
    string methodName = method->full_name();
    int methodId = RpcPlugin::generateExtensionNumber(methodName);
    ostringstream methodIdStr;
    methodIdStr << methodId;

    printer.Print("methodIds.push_back($methodId$);\n", "methodId",
        methodIdStr.str());
  }
  printer.Print("init = false;\n");
  printer.Outdent();
  printer.Print("}\n");
  printer.Print("return methodIds;\n");
  printer.Outdent();
  printer.Print("}\n");
}
void RpcGenerator::generateDispatchMethodBody(
    const google::protobuf::ServiceDescriptor *descriptor,
    google::protobuf::io::Printer &printer) const
{
  printer.Indent();

  printer.Print("switch(methodId) { \n");
  printer.Indent();

  for(int j=0; j<descriptor->method_count(); j++) {
    const MethodDescriptor *method = descriptor->method(j);
    string methodName = method->full_name();
    int methodId = RpcPlugin::generateExtensionNumber(methodName);
    string inputTypeName = method->input_type()->name();
    string outputTypeName = method->output_type()->name();
    ostringstream methodIdStr;
    methodIdStr << methodId;
    printer.Print("case $methodId$ : {\n", "methodId", methodIdStr.str());
    printer.Indent();
    printer.Print("// $methodName$\n", "methodName",  methodName);

    if (!isVoidType(inputTypeName)) {
      printer.Print("const $inputType$ *in = static_cast<const $inputType$ *>(request);\n",
          "inputType", inputTypeName);

      // Receive any VTK types that might be on the wire ...
      generateReceiveVtkBlock("request", "replyChannel",
          method->input_type(),printer);

      // Receive any external type that might be on the wire ...
      generateReceiveExternalBlock("request", "replyChannel",
          method->input_type(),printer);
    }

    if (!isVoidType(outputTypeName)) {
      printer.Print("$outputType$ *out = new $outputType$();\n",
          "outputType", outputTypeName);
      printer.Print("ProtoCall::Runtime::ReplyInfo info;\n");
      printer.Print("info.methodId = $methodId$;\n", "methodId", methodIdStr.str());
      printer.Print("info.requestMessageEnvelope = requestMessageEnvelope;\n");
      printer.Print("info.response = out;\n");
      printer.Print("info.replyChannel = replyChannel;\n");
      string dispatcherName = descriptor->name() + "_Dispatcher";
      printer.Print("::google::protobuf::Closure *done = "
          "::google::protobuf::NewCallback(this, &$dispatcherName$::reply, info);\n",
          "dispatcherName", dispatcherName);
    }
    else {
      printer.Print("::google::protobuf::Closure *done = google::protobuf::NewCallback(&google::protobuf::DoNothing);\n");
    }

    printer.Print("static_cast<$service$ *>(m_service)->$methodName$(", "service",
        descriptor->name(), "methodName", method->name());

    if (!isVoidType(inputTypeName))
      printer.Print("in");

    if (!isVoidType(inputTypeName) && !isVoidType(outputTypeName))
      printer.Print(", ");

    if (!isVoidType(outputTypeName))
      printer.Print("out");

    if (!isVoidType(inputTypeName) || !isVoidType(outputTypeName))
      printer.Print(", ");

    printer.Print("done);\n");


    printer.Outdent();

    printer.Print("break;\n");
    printer.Print("}\n");
  }

  printer.Print("default:\n");
  printer.Indent();
  printer.Print("replyChannel->setErrorString(\"No case for messageId: \" +  methodId);");
  printer.Outdent();
  printer.Outdent();
  printer.Print("}\n");


  printer.Outdent();

}
void RpcGenerator::printHeaderGuardEnd(google::protobuf::io::Printer &printer,
    const string &define) const
{
  printer.Print("#endif /* $define$ */\n", "define", define);
}
void RpcGenerator::printHeaderGuardStart(google::protobuf::io::Printer &printer,
    const string &define) const
{
  printer.Print("#ifndef $define$\n"
                "#define $define$\n\n", "define", define);
}
void FieldGenerator::generateRepeatedProperty(
    google::protobuf::io::Printer& p) {
  p.Print(variables_,
          "$i$  // Replacement setter\n"
          "$i$$type$.prototype.set$capital_name$ = function(values) {\n");
  if (is_typed_array_) {
    p.Print(variables_,
            // Omit type checks for performance
            // "$i$  if (values instanceof $typed_array$ || values "
            // "instanceof Array "
            // "|| values instanceof ArrayBuffer) {\n"
            "$i$    if (!values.BYTES_PER_ELEMENT) {\n"
            "$i$      values = new $typed_array$(values);;\n"
            "$i$    }\n"
            "$i$    var newArray = this._ensureLength(this._fields[$index$], "
            "values.length);\n"
            "$i$    if (newArray) {\n"
            "$i$      this._fields[$index$] = newArray;\n"
            "$i$    }\n"
            "$i$    this._fields[$index$].set(values);\n"
            // "$i$  } else {\n"
            // "$i$    throw new TypeError();\n"
            // "$i$  }\n"
            );
  } else {
    p.Print(variables_,
            "$i$  if (!(values instanceof Array)) {\n"
            "$i$    throw new TypeError();\n"
            "$i$  }\n");
    if (is_message_) {
      p.Print(variables_,
              "$i$  this._fields[$index$].length = values.length;\n"
              "$i$   this._$name$.length = values.length;\n"
              "$i$   for (var i = 0; i < values.length; ++i) {\n"
              "$i$     var msg = new "
              "$message_scope$$message_type$(values[i]);\n"
              "$i$     this._$name$[i] = msg;\n"
              "$i$     this._fields[$index$][i] = msg._raw;\n"
              "$i$   }\n");
    } else {
      p.Print(variables_, "$i$    this._fields[$index$] = values.slice();\n");
    }
  }
  p.Print(variables_,
          "$i$};\n"
          "$i$// Single value setter\n"
          "$i$$type$.prototype.set$capital_name$At = function(index, value) "
          "{\n"
          // Type checks are expensive for V4 engine.
          //"$i$  if (typeof index != 'number') {\n"
          //"$i$    throw new TypeError('Index should be a number: ' + typeof "
          //"index);\n"
          //"$i$  }\n"
          //"$i$  if(this._fields[$index$].length <= index) {\n"
          //"$i$    throw new RangeError();\n"
          //"$i$  }\n");
          );
  if (is_message_) {
    p.Print(variables_,
            "$i$  var msg = "
            "this._maybeConvertToMessage($message_scope$$message_type$, "
            "value);\n"
            "$i$  this._$name$[index] = msg;\n"
            "$i$  this._fields[$index$][index] = msg._raw;\n");
  } else if (is_typed_array_) {
    p.Print(variables_, "$i$  this._fields[$index$][index] = value;\n");
  } else {
    p.Print(variables_, "$i$  this._fields[$index$][index] = value;\n");
  }
  p.Print(variables_,
          "$i$};\n"
          "$i$// Getter\n"
          "$i$$type$.prototype.get$capital_name$At = function(index) {\n"
          "$i$  if (typeof index != 'number') {\n"
          "$i$    throw new TypeError('Index should be a number: ' + typeof "
          "index);\n"
          "$i$  }\n"
          "$i$  if(this._fields[$index$].length < index) {\n"
          "$i$    throw new RangeError();\n"
          "$i$  }\n");
  if (is_message_) {
    p.Print(variables_, "$i$  return this._$name$[index];\n");
  } else {
    p.Print(variables_, "$i$  return this._fields[$index$][index];\n");
  }
  p.Print(variables_,
          "$i$};\n"
          "$i$$type$.prototype.get$capital_name$AsArray = function() {\n");
  if (is_message_) {
    p.Print(variables_, "$i$  return this._$name$.slice();\n");
  } else if (is_typed_array_) {
    p.Print(variables_,
            "$i$  var array = [];\n"
            "$i$  for (var i = 0; i < this._fields[$index$].length; ++i) {\n"
            "$i$    array.push(this._fields[$index$][i]);\n"
            "$i$  }\n"
            "$i$  return array;\n");
  } else {
    p.Print(variables_, "$i$  return this._fields[$index$].slice();\n");
  }
  p.Print(variables_, "$i$};\n");

  p.Print(variables_,
          "$i$$type$.prototype.$name$ = function(indexOrValues, value) {\n"
          "$i$  if (typeof indexOrValues == 'undefined') {\n"
          "$i$    throw new TypeError('Not enough arguments');\n"
          "$i$  } else if (typeof indexOrValues == 'number') {\n"
          "$i$    if (typeof value == 'undefined') {\n"
          "$i$      return this.get$capital_name$At(indexOrValues);\n"
          "$i$    } else {\n"
          "$i$      this.set$capital_name$At(indexOrValues, value);\n"
          "$i$    }\n"
          "$i$  } else {\n"
          "$i$    this.set$capital_name$(indexOrValues);\n"
          "$i$  }\n"
          "$i$};\n");

  countMethod(p);
  addMethod(p);
  if (is_typed_array_) {
    reserveMethod(p);
  }
  if (!is_message_) {
    resizeMethod(p);
  }

  p.Print(variables_,
          "$i$$type$.prototype.remove$capital_name$ = function(index) {\n"
          "$i$  if (typeof index != 'number') {\n"
          "$i$    throw new TypeError('Index should be a number: ' + typeof "
          "index);\n"
          "$i$  }\n"
          "$i$  this._fields[$index$].splice(index, 1);\n");

  if (is_message_) {
    p.Print(variables_, "$i$  this._$name$.splice(index, 1);\n");
    messageAssertLength(p);
  }

  p.Print(variables_,
          "$i$};\n"
          "$i$$type$.prototype.clear$capital_name$ = function() {\n");

  if (is_typed_array_) {
    p.Print(variables_,
            "$i$  this._fields[$index$] = new "
            "$typed_array$(this._fields[$index$].buffer, 0, 0);\n");
  } else {
    p.Print(variables_, "$i$  this._fields[$index$].length = 0;\n");

    if (is_message_) {
      p.Print(variables_, "$i$  this._$name$.length = 0;\n");
      messageAssertLength(p);
    }
  }

  p.Print(variables_, "$i$};\n");
}
Exemple #21
0
void EnumGenerator::generateNestedAlias(google::protobuf::io::Printer& p) {
  p.Print("$i$type.$name$ = $name$;\n", "name", t_->name(), "i", indent_);
}