Browse Source

Escape C++ Trigraphs.

liujisi@google.com 15 years ago
parent
commit
5c20ca1fcc

+ 1 - 0
java/src/test/java/com/google/protobuf/GeneratedMessageTest.java

@@ -410,6 +410,7 @@ public class GeneratedMessageTest extends TestCase {
     assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat());
     assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat());
     assertTrue(Float.isNaN(message.getNanFloat()));
+    assertEquals("? ? ?? ?? ??? ??/ ??-", message.getCppTrigraph());
   }
 
   public void testClear() throws Exception {

+ 1 - 0
python/google/protobuf/internal/generator_test.py

@@ -100,6 +100,7 @@ class GeneratorTest(unittest.TestCase):
     self.assertTrue(isinf(message.neg_inf_float))
     self.assertTrue(message.neg_inf_float < 0)
     self.assertTrue(isnan(message.nan_float))
+    self.assertEqual("? ? ?? ?? ??? ??/ ??-", message.cpp_trigraph)
 
   def testHasDefaultValues(self):
     desc = unittest_pb2.TestAllTypes.DESCRIPTOR

+ 1 - 1
src/google/protobuf/compiler/cpp/cpp_file.cc

@@ -541,7 +541,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
     static const int kBytesPerLine = 40;
     for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
       printer->Print("\n  \"$data$\"",
-        "data", CEscape(file_data.substr(i, kBytesPerLine)));
+        "data", EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine))));
     }
     printer->Print(
       ", $size$);\n",

+ 7 - 1
src/google/protobuf/compiler/cpp/cpp_helpers.cc

@@ -292,7 +292,8 @@ string DefaultValue(const FieldDescriptor* field) {
           ClassName(field->enum_type(), true),
           field->default_value_enum()->number());
     case FieldDescriptor::CPPTYPE_STRING:
-      return "\"" + CEscape(field->default_value_string()) + "\"";
+      return "\"" + EscapeTrigraphs(CEscape(field->default_value_string())) +
+             "\"";
     case FieldDescriptor::CPPTYPE_MESSAGE:
       return FieldMessageTypeName(field) + "::default_instance()";
   }
@@ -335,6 +336,11 @@ string GlobalShutdownFileName(const string& filename) {
   return "protobuf_ShutdownFile_" + FilenameIdentifier(filename);
 }
 
+// Escape C++ trigraphs by escaping question marks to \?
+string EscapeTrigraphs(const string& to_escape) {
+  return StringReplace(to_escape, "?", "\\?", true);
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf

+ 3 - 0
src/google/protobuf/compiler/cpp/cpp_helpers.h

@@ -112,6 +112,9 @@ string GlobalAssignDescriptorsName(const string& filename);
 // Return the name of the ShutdownFile() function for a given file.
 string GlobalShutdownFileName(const string& filename);
 
+// Escape C++ trigraphs by escaping question marks to \?
+string EscapeTrigraphs(const string& to_escape);
+
 // Do message classes in this file keep track of unknown fields?
 inline bool HasUnknownFields(const FileDescriptor *file) {
   return file->options().optimize_for() != FileOptions::LITE_RUNTIME;

+ 1 - 2
src/google/protobuf/compiler/cpp/cpp_string_field.cc

@@ -48,8 +48,7 @@ namespace {
 void SetStringVariables(const FieldDescriptor* descriptor,
                         map<string, string>* variables) {
   SetCommonFieldVariables(descriptor, variables);
-  (*variables)["default"] =
-    "\"" + CEscape(descriptor->default_value_string()) + "\"";
+  (*variables)["default"] = DefaultValue(descriptor);
   (*variables)["default_variable"] = descriptor->default_value_string().empty()
       ? "::google::protobuf::internal::kEmptyString"
       : "_default_" + FieldName(descriptor) + "_";

+ 7 - 0
src/google/protobuf/compiler/cpp/cpp_unittest.cc

@@ -167,6 +167,13 @@ TEST(GeneratedMessageTest, FloatingPointDefaults) {
   EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float());
 }
 
+TEST(GeneratedMessageTest, Trigraph) {
+  const unittest::TestExtremeDefaultValues& extreme_default =
+      unittest::TestExtremeDefaultValues::default_instance();
+
+  EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph());
+}
+
 TEST(GeneratedMessageTest, Accessors) {
   // Set every field to a unique value then go back and check all those
   // values.

+ 7 - 0
src/google/protobuf/unittest.proto

@@ -493,6 +493,13 @@ message TestExtremeDefaultValues {
   optional float inf_float = 17 [default = inf];
   optional float neg_inf_float = 18 [default = -inf];
   optional float nan_float = 19 [default = nan];
+
+  // Tests for C++ trigraphs.
+  // Trigraphs should be escaped in C++ generated files, but they should not be
+  // escaped for other languages.
+  // Note that in .proto file, "\?" is a valid way to escape ? in string
+  // literals.
+  optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"];
 }
 
 message SparseEnumMessage {