objectivec_helpers.cc 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #ifndef _MSC_VER
  31. #include <unistd.h>
  32. #endif
  33. #include <climits>
  34. #include <errno.h>
  35. #include <fcntl.h>
  36. #include <fstream>
  37. #include <iostream>
  38. #include <sstream>
  39. #include <stdlib.h>
  40. #include <unordered_set>
  41. #include <vector>
  42. #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
  43. #include <google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h>
  44. #include <google/protobuf/descriptor.pb.h>
  45. #include <google/protobuf/io/coded_stream.h>
  46. #include <google/protobuf/io/printer.h>
  47. #include <google/protobuf/io/zero_copy_stream_impl.h>
  48. #include <google/protobuf/io/io_win32.h>
  49. #include <google/protobuf/port.h>
  50. #include <google/protobuf/stubs/common.h>
  51. #include <google/protobuf/stubs/strutil.h>
  52. // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
  53. // error cases, so it seems to be ok to use as a back door for errors.
  54. namespace google {
  55. namespace protobuf {
  56. namespace compiler {
  57. namespace objectivec {
  58. // <io.h> is transitively included in this file. Import the functions explicitly
  59. // in this port namespace to avoid ambiguous definition.
  60. namespace posix {
  61. #ifdef _WIN32
  62. using ::google::protobuf::io::win32::open;
  63. #else
  64. using ::open;
  65. #endif
  66. } // namespace port
  67. Options::Options() {
  68. // Default is the value of the env for the package prefixes.
  69. const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
  70. if (file_path) {
  71. expected_prefixes_path = file_path;
  72. }
  73. const char* suppressions = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS");
  74. if (suppressions) {
  75. expected_prefixes_suppressions =
  76. Split(suppressions, ";", true);
  77. }
  78. }
  79. namespace {
  80. std::unordered_set<string> MakeWordsMap(const char* const words[], size_t num_words) {
  81. std::unordered_set<string> result;
  82. for (int i = 0; i < num_words; i++) {
  83. result.insert(words[i]);
  84. }
  85. return result;
  86. }
  87. const char* const kUpperSegmentsList[] = {"url", "http", "https"};
  88. std::unordered_set<string> kUpperSegments =
  89. MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList));
  90. bool ascii_isnewline(char c) {
  91. return c == '\n' || c == '\r';
  92. }
  93. // Internal helper for name handing.
  94. // Do not expose this outside of helpers, stick to having functions for specific
  95. // cases (ClassName(), FieldName()), so there is always consistent suffix rules.
  96. string UnderscoresToCamelCase(const string& input, bool first_capitalized) {
  97. std::vector<string> values;
  98. string current;
  99. bool last_char_was_number = false;
  100. bool last_char_was_lower = false;
  101. bool last_char_was_upper = false;
  102. for (int i = 0; i < input.size(); i++) {
  103. char c = input[i];
  104. if (ascii_isdigit(c)) {
  105. if (!last_char_was_number) {
  106. values.push_back(current);
  107. current = "";
  108. }
  109. current += c;
  110. last_char_was_number = last_char_was_lower = last_char_was_upper = false;
  111. last_char_was_number = true;
  112. } else if (ascii_islower(c)) {
  113. // lowercase letter can follow a lowercase or uppercase letter
  114. if (!last_char_was_lower && !last_char_was_upper) {
  115. values.push_back(current);
  116. current = "";
  117. }
  118. current += c; // already lower
  119. last_char_was_number = last_char_was_lower = last_char_was_upper = false;
  120. last_char_was_lower = true;
  121. } else if (ascii_isupper(c)) {
  122. if (!last_char_was_upper) {
  123. values.push_back(current);
  124. current = "";
  125. }
  126. current += ascii_tolower(c);
  127. last_char_was_number = last_char_was_lower = last_char_was_upper = false;
  128. last_char_was_upper = true;
  129. } else {
  130. last_char_was_number = last_char_was_lower = last_char_was_upper = false;
  131. }
  132. }
  133. values.push_back(current);
  134. string result;
  135. bool first_segment_forces_upper = false;
  136. for (std::vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
  137. string value = *i;
  138. bool all_upper = (kUpperSegments.count(value) > 0);
  139. if (all_upper && (result.length() == 0)) {
  140. first_segment_forces_upper = true;
  141. }
  142. for (int j = 0; j < value.length(); j++) {
  143. if (j == 0 || all_upper) {
  144. value[j] = ascii_toupper(value[j]);
  145. } else {
  146. // Nothing, already in lower.
  147. }
  148. }
  149. result += value;
  150. }
  151. if ((result.length() != 0) &&
  152. !first_capitalized &&
  153. !first_segment_forces_upper) {
  154. result[0] = ascii_tolower(result[0]);
  155. }
  156. return result;
  157. }
  158. const char* const kReservedWordList[] = {
  159. // Note NSObject Methods:
  160. // These are brought in from objectivec_nsobject_methods.h that is generated
  161. // using method_dump.sh. See kNSObjectMethods below.
  162. // Objective C "keywords" that aren't in C
  163. // From
  164. // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
  165. // with some others added on.
  166. "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway",
  167. "self", "instancetype", "nullable", "nonnull", "nil", "Nil",
  168. "YES", "NO", "weak",
  169. // C/C++ keywords (Incl C++ 0x11)
  170. // From http://en.cppreference.com/w/cpp/keywords
  171. "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor",
  172. "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class",
  173. "compl", "const", "constexpr", "const_cast", "continue", "decltype",
  174. "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit",
  175. "export", "extern ", "false", "float", "for", "friend", "goto", "if",
  176. "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not",
  177. "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected",
  178. "public", "register", "reinterpret_cast", "return", "short", "signed",
  179. "sizeof", "static", "static_assert", "static_cast", "struct", "switch",
  180. "template", "this", "thread_local", "throw", "true", "try", "typedef",
  181. "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
  182. "volatile", "wchar_t", "while", "xor", "xor_eq",
  183. // C99 keywords
  184. // From
  185. // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
  186. "restrict",
  187. // GCC/Clang extension
  188. "typeof",
  189. // Not a keyword, but will break you
  190. "NULL",
  191. // Objective-C Runtime typedefs
  192. // From <obc/runtime.h>
  193. "Category", "Ivar", "Method", "Protocol",
  194. // GPBMessage Methods
  195. // Only need to add instance methods that may conflict with
  196. // method declared in protos. The main cases are methods
  197. // that take no arguments, or setFoo:/hasFoo: type methods.
  198. "clear", "data", "delimitedData", "descriptor", "extensionRegistry",
  199. "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize",
  200. "sortedExtensionsInUse", "unknownFields",
  201. // MacTypes.h names
  202. "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount",
  203. "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount",
  204. "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType",
  205. "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style",
  206. "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord",
  207. };
  208. // returns true is input starts with __ or _[A-Z] which are reserved identifiers
  209. // in C/ C++. All calls should go through UnderscoresToCamelCase before getting here
  210. // but this verifies and allows for future expansion if we decide to redefine what a
  211. // reserved C identifier is (for example the GNU list
  212. // https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html )
  213. bool IsReservedCIdentifier(const string& input) {
  214. if (input.length() > 2) {
  215. if (input.at(0) == '_') {
  216. if (isupper(input.at(1)) || input.at(1) == '_') {
  217. return true;
  218. }
  219. }
  220. }
  221. return false;
  222. }
  223. string SanitizeNameForObjC(const string& prefix,
  224. const string& input,
  225. const string& extension,
  226. string* out_suffix_added) {
  227. static const std::unordered_set<string> kReservedWords =
  228. MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
  229. static const std::unordered_set<string> kNSObjectMethods =
  230. MakeWordsMap(kNSObjectMethodsList, GOOGLE_ARRAYSIZE(kNSObjectMethodsList));
  231. string sanitized;
  232. // We add the prefix in the cases where the string is missing a prefix.
  233. // We define "missing a prefix" as where 'input':
  234. // a) Doesn't start with the prefix or
  235. // b) Isn't equivalent to the prefix or
  236. // c) Has the prefix, but the letter after the prefix is lowercase
  237. if (HasPrefixString(input, prefix)) {
  238. if (input.length() == prefix.length() || !ascii_isupper(input[prefix.length()])) {
  239. sanitized = prefix + input;
  240. } else {
  241. sanitized = input;
  242. }
  243. } else {
  244. sanitized = prefix + input;
  245. }
  246. if (IsReservedCIdentifier(sanitized) ||
  247. (kReservedWords.count(sanitized) > 0) ||
  248. (kNSObjectMethods.count(sanitized) > 0)) {
  249. if (out_suffix_added) *out_suffix_added = extension;
  250. return sanitized + extension;
  251. }
  252. if (out_suffix_added) out_suffix_added->clear();
  253. return sanitized;
  254. }
  255. string NameFromFieldDescriptor(const FieldDescriptor* field) {
  256. if (field->type() == FieldDescriptor::TYPE_GROUP) {
  257. return field->message_type()->name();
  258. } else {
  259. return field->name();
  260. }
  261. }
  262. void PathSplit(const string& path, string* directory, string* basename) {
  263. string::size_type last_slash = path.rfind('/');
  264. if (last_slash == string::npos) {
  265. if (directory) {
  266. *directory = "";
  267. }
  268. if (basename) {
  269. *basename = path;
  270. }
  271. } else {
  272. if (directory) {
  273. *directory = path.substr(0, last_slash);
  274. }
  275. if (basename) {
  276. *basename = path.substr(last_slash + 1);
  277. }
  278. }
  279. }
  280. bool IsSpecialName(const string& name, const string* special_names,
  281. size_t count) {
  282. for (size_t i = 0; i < count; ++i) {
  283. size_t length = special_names[i].length();
  284. if (name.compare(0, length, special_names[i]) == 0) {
  285. if (name.length() > length) {
  286. // If name is longer than the retained_name[i] that it matches
  287. // the next character must be not lower case (newton vs newTon vs
  288. // new_ton).
  289. return !ascii_islower(name[length]);
  290. } else {
  291. return true;
  292. }
  293. }
  294. }
  295. return false;
  296. }
  297. string GetZeroEnumNameForFlagType(const FlagType flag_type) {
  298. switch(flag_type) {
  299. case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
  300. return "GPBDescriptorInitializationFlag_None";
  301. case FLAGTYPE_EXTENSION:
  302. return "GPBExtensionNone";
  303. case FLAGTYPE_FIELD:
  304. return "GPBFieldNone";
  305. default:
  306. GOOGLE_LOG(FATAL) << "Can't get here.";
  307. return "0";
  308. }
  309. }
  310. string GetEnumNameForFlagType(const FlagType flag_type) {
  311. switch(flag_type) {
  312. case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
  313. return "GPBDescriptorInitializationFlags";
  314. case FLAGTYPE_EXTENSION:
  315. return "GPBExtensionOptions";
  316. case FLAGTYPE_FIELD:
  317. return "GPBFieldFlags";
  318. default:
  319. GOOGLE_LOG(FATAL) << "Can't get here.";
  320. return string();
  321. }
  322. }
  323. } // namespace
  324. // Escape C++ trigraphs by escaping question marks to \?
  325. string EscapeTrigraphs(const string& to_escape) {
  326. return StringReplace(to_escape, "?", "\\?", true);
  327. }
  328. string StripProto(const string& filename) {
  329. if (HasSuffixString(filename, ".protodevel")) {
  330. return StripSuffixString(filename, ".protodevel");
  331. } else {
  332. return StripSuffixString(filename, ".proto");
  333. }
  334. }
  335. void TrimWhitespace(StringPiece* input) {
  336. while (!input->empty() && ascii_isspace(*input->data())) {
  337. input->remove_prefix(1);
  338. }
  339. while (!input->empty() && ascii_isspace((*input)[input->length() - 1])) {
  340. input->remove_suffix(1);
  341. }
  342. }
  343. bool IsRetainedName(const string& name) {
  344. // List of prefixes from
  345. // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
  346. static const string retained_names[] = {"new", "alloc", "copy",
  347. "mutableCopy"};
  348. return IsSpecialName(name, retained_names,
  349. sizeof(retained_names) / sizeof(retained_names[0]));
  350. }
  351. bool IsInitName(const string& name) {
  352. static const string init_names[] = {"init"};
  353. return IsSpecialName(name, init_names,
  354. sizeof(init_names) / sizeof(init_names[0]));
  355. }
  356. string BaseFileName(const FileDescriptor* file) {
  357. string basename;
  358. PathSplit(file->name(), NULL, &basename);
  359. return basename;
  360. }
  361. string FileClassPrefix(const FileDescriptor* file) {
  362. // Default is empty string, no need to check has_objc_class_prefix.
  363. string result = file->options().objc_class_prefix();
  364. return result;
  365. }
  366. string FilePath(const FileDescriptor* file) {
  367. string output;
  368. string basename;
  369. string directory;
  370. PathSplit(file->name(), &directory, &basename);
  371. if (directory.length() > 0) {
  372. output = directory + "/";
  373. }
  374. basename = StripProto(basename);
  375. // CamelCase to be more ObjC friendly.
  376. basename = UnderscoresToCamelCase(basename, true);
  377. output += basename;
  378. return output;
  379. }
  380. string FilePathBasename(const FileDescriptor* file) {
  381. string output;
  382. string basename;
  383. string directory;
  384. PathSplit(file->name(), &directory, &basename);
  385. basename = StripProto(basename);
  386. // CamelCase to be more ObjC friendly.
  387. output = UnderscoresToCamelCase(basename, true);
  388. return output;
  389. }
  390. string FileClassName(const FileDescriptor* file) {
  391. const string prefix = FileClassPrefix(file);
  392. const string name = UnderscoresToCamelCase(StripProto(BaseFileName(file)), true) + "Root";
  393. // There aren't really any reserved words that end in "Root", but playing
  394. // it safe and checking.
  395. return SanitizeNameForObjC(prefix, name, "_RootClass", NULL);
  396. }
  397. string ClassNameWorker(const Descriptor* descriptor) {
  398. string name;
  399. if (descriptor->containing_type() != NULL) {
  400. name = ClassNameWorker(descriptor->containing_type());
  401. name += "_";
  402. }
  403. return name + descriptor->name();
  404. }
  405. string ClassNameWorker(const EnumDescriptor* descriptor) {
  406. string name;
  407. if (descriptor->containing_type() != NULL) {
  408. name = ClassNameWorker(descriptor->containing_type());
  409. name += "_";
  410. }
  411. return name + descriptor->name();
  412. }
  413. string ClassName(const Descriptor* descriptor) {
  414. return ClassName(descriptor, NULL);
  415. }
  416. string ClassName(const Descriptor* descriptor, string* out_suffix_added) {
  417. // 1. Message names are used as is (style calls for CamelCase, trust it).
  418. // 2. Check for reserved word at the very end and then suffix things.
  419. const string prefix = FileClassPrefix(descriptor->file());
  420. const string name = ClassNameWorker(descriptor);
  421. return SanitizeNameForObjC(prefix, name, "_Class", out_suffix_added);
  422. }
  423. string EnumName(const EnumDescriptor* descriptor) {
  424. // 1. Enum names are used as is (style calls for CamelCase, trust it).
  425. // 2. Check for reserved word at the every end and then suffix things.
  426. // message Fixed {
  427. // message Size {...}
  428. // enum Mumble {...}
  429. // ...
  430. // }
  431. // yields Fixed_Class, Fixed_Size.
  432. const string prefix = FileClassPrefix(descriptor->file());
  433. const string name = ClassNameWorker(descriptor);
  434. return SanitizeNameForObjC(prefix, name, "_Enum", NULL);
  435. }
  436. string EnumValueName(const EnumValueDescriptor* descriptor) {
  437. // Because of the Switch enum compatibility, the name on the enum has to have
  438. // the suffix handing, so it slightly diverges from how nested classes work.
  439. // enum Fixed {
  440. // FOO = 1
  441. // }
  442. // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo).
  443. const string class_name = EnumName(descriptor->type());
  444. const string value_str = UnderscoresToCamelCase(descriptor->name(), true);
  445. const string name = class_name + "_" + value_str;
  446. // There aren't really any reserved words with an underscore and a leading
  447. // capital letter, but playing it safe and checking.
  448. return SanitizeNameForObjC("", name, "_Value", NULL);
  449. }
  450. string EnumValueShortName(const EnumValueDescriptor* descriptor) {
  451. // Enum value names (EnumValueName above) are the enum name turned into
  452. // a class name and then the value name is CamelCased and concatenated; the
  453. // whole thing then gets sanitized for reserved words.
  454. // The "short name" is intended to be the final leaf, the value name; but
  455. // you can't simply send that off to sanitize as that could result in it
  456. // getting modified when the full name didn't. For example enum
  457. // "StorageModes" has a value "retain". So the full name is
  458. // "StorageModes_Retain", but if we sanitize "retain" it would become
  459. // "RetainValue".
  460. // So the right way to get the short name is to take the full enum name
  461. // and then strip off the enum name (leaving the value name and anything
  462. // done by sanitize).
  463. const string class_name = EnumName(descriptor->type());
  464. const string long_name_prefix = class_name + "_";
  465. const string long_name = EnumValueName(descriptor);
  466. return StripPrefixString(long_name, long_name_prefix);
  467. }
  468. string UnCamelCaseEnumShortName(const string& name) {
  469. string result;
  470. for (int i = 0; i < name.size(); i++) {
  471. char c = name[i];
  472. if (i > 0 && ascii_isupper(c)) {
  473. result += '_';
  474. }
  475. result += ascii_toupper(c);
  476. }
  477. return result;
  478. }
  479. string ExtensionMethodName(const FieldDescriptor* descriptor) {
  480. const string name = NameFromFieldDescriptor(descriptor);
  481. const string result = UnderscoresToCamelCase(name, false);
  482. return SanitizeNameForObjC("", result, "_Extension", NULL);
  483. }
  484. string FieldName(const FieldDescriptor* field) {
  485. const string name = NameFromFieldDescriptor(field);
  486. string result = UnderscoresToCamelCase(name, false);
  487. if (field->is_repeated() && !field->is_map()) {
  488. // Add "Array" before do check for reserved worlds.
  489. result += "Array";
  490. } else {
  491. // If it wasn't repeated, but ends in "Array", force on the _p suffix.
  492. if (HasSuffixString(result, "Array")) {
  493. result += "_p";
  494. }
  495. }
  496. return SanitizeNameForObjC("", result, "_p", NULL);
  497. }
  498. string FieldNameCapitalized(const FieldDescriptor* field) {
  499. // Want the same suffix handling, so upcase the first letter of the other
  500. // name.
  501. string result = FieldName(field);
  502. if (result.length() > 0) {
  503. result[0] = ascii_toupper(result[0]);
  504. }
  505. return result;
  506. }
  507. string OneofEnumName(const OneofDescriptor* descriptor) {
  508. const Descriptor* fieldDescriptor = descriptor->containing_type();
  509. string name = ClassName(fieldDescriptor);
  510. name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase";
  511. // No sanitize needed because the OS never has names that end in _OneOfCase.
  512. return name;
  513. }
  514. string OneofName(const OneofDescriptor* descriptor) {
  515. string name = UnderscoresToCamelCase(descriptor->name(), false);
  516. // No sanitize needed because it gets OneOfCase added and that shouldn't
  517. // ever conflict.
  518. return name;
  519. }
  520. string OneofNameCapitalized(const OneofDescriptor* descriptor) {
  521. // Use the common handling and then up-case the first letter.
  522. string result = OneofName(descriptor);
  523. if (result.length() > 0) {
  524. result[0] = ascii_toupper(result[0]);
  525. }
  526. return result;
  527. }
  528. string ObjCClass(const string& class_name) {
  529. return string("GPBObjCClass(") + class_name + ")";
  530. }
  531. string ObjCClassDeclaration(const string& class_name) {
  532. return string("GPBObjCClassDeclaration(") + class_name + ");";
  533. }
  534. string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) {
  535. string worker(name);
  536. if (HasSuffixString(worker, "_p")) {
  537. worker = StripSuffixString(worker, "_p");
  538. }
  539. if (field->is_repeated() && HasSuffixString(worker, "Array")) {
  540. worker = StripSuffixString(worker, "Array");
  541. }
  542. if (field->type() == FieldDescriptor::TYPE_GROUP) {
  543. if (worker.length() > 0) {
  544. if (ascii_islower(worker[0])) {
  545. worker[0] = ascii_toupper(worker[0]);
  546. }
  547. }
  548. return worker;
  549. } else {
  550. string result;
  551. for (int i = 0; i < worker.size(); i++) {
  552. char c = worker[i];
  553. if (ascii_isupper(c)) {
  554. if (i > 0) {
  555. result += '_';
  556. }
  557. result += ascii_tolower(c);
  558. } else {
  559. result += c;
  560. }
  561. }
  562. return result;
  563. }
  564. }
  565. string GetCapitalizedType(const FieldDescriptor* field) {
  566. switch (field->type()) {
  567. case FieldDescriptor::TYPE_INT32:
  568. return "Int32";
  569. case FieldDescriptor::TYPE_UINT32:
  570. return "UInt32";
  571. case FieldDescriptor::TYPE_SINT32:
  572. return "SInt32";
  573. case FieldDescriptor::TYPE_FIXED32:
  574. return "Fixed32";
  575. case FieldDescriptor::TYPE_SFIXED32:
  576. return "SFixed32";
  577. case FieldDescriptor::TYPE_INT64:
  578. return "Int64";
  579. case FieldDescriptor::TYPE_UINT64:
  580. return "UInt64";
  581. case FieldDescriptor::TYPE_SINT64:
  582. return "SInt64";
  583. case FieldDescriptor::TYPE_FIXED64:
  584. return "Fixed64";
  585. case FieldDescriptor::TYPE_SFIXED64:
  586. return "SFixed64";
  587. case FieldDescriptor::TYPE_FLOAT:
  588. return "Float";
  589. case FieldDescriptor::TYPE_DOUBLE:
  590. return "Double";
  591. case FieldDescriptor::TYPE_BOOL:
  592. return "Bool";
  593. case FieldDescriptor::TYPE_STRING:
  594. return "String";
  595. case FieldDescriptor::TYPE_BYTES:
  596. return "Bytes";
  597. case FieldDescriptor::TYPE_ENUM:
  598. return "Enum";
  599. case FieldDescriptor::TYPE_GROUP:
  600. return "Group";
  601. case FieldDescriptor::TYPE_MESSAGE:
  602. return "Message";
  603. }
  604. // Some compilers report reaching end of function even though all cases of
  605. // the enum are handed in the switch.
  606. GOOGLE_LOG(FATAL) << "Can't get here.";
  607. return string();
  608. }
  609. ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) {
  610. switch (field_type) {
  611. case FieldDescriptor::TYPE_INT32:
  612. case FieldDescriptor::TYPE_SINT32:
  613. case FieldDescriptor::TYPE_SFIXED32:
  614. return OBJECTIVECTYPE_INT32;
  615. case FieldDescriptor::TYPE_UINT32:
  616. case FieldDescriptor::TYPE_FIXED32:
  617. return OBJECTIVECTYPE_UINT32;
  618. case FieldDescriptor::TYPE_INT64:
  619. case FieldDescriptor::TYPE_SINT64:
  620. case FieldDescriptor::TYPE_SFIXED64:
  621. return OBJECTIVECTYPE_INT64;
  622. case FieldDescriptor::TYPE_UINT64:
  623. case FieldDescriptor::TYPE_FIXED64:
  624. return OBJECTIVECTYPE_UINT64;
  625. case FieldDescriptor::TYPE_FLOAT:
  626. return OBJECTIVECTYPE_FLOAT;
  627. case FieldDescriptor::TYPE_DOUBLE:
  628. return OBJECTIVECTYPE_DOUBLE;
  629. case FieldDescriptor::TYPE_BOOL:
  630. return OBJECTIVECTYPE_BOOLEAN;
  631. case FieldDescriptor::TYPE_STRING:
  632. return OBJECTIVECTYPE_STRING;
  633. case FieldDescriptor::TYPE_BYTES:
  634. return OBJECTIVECTYPE_DATA;
  635. case FieldDescriptor::TYPE_ENUM:
  636. return OBJECTIVECTYPE_ENUM;
  637. case FieldDescriptor::TYPE_GROUP:
  638. case FieldDescriptor::TYPE_MESSAGE:
  639. return OBJECTIVECTYPE_MESSAGE;
  640. }
  641. // Some compilers report reaching end of function even though all cases of
  642. // the enum are handed in the switch.
  643. GOOGLE_LOG(FATAL) << "Can't get here.";
  644. return OBJECTIVECTYPE_INT32;
  645. }
  646. bool IsPrimitiveType(const FieldDescriptor* field) {
  647. ObjectiveCType type = GetObjectiveCType(field);
  648. switch (type) {
  649. case OBJECTIVECTYPE_INT32:
  650. case OBJECTIVECTYPE_UINT32:
  651. case OBJECTIVECTYPE_INT64:
  652. case OBJECTIVECTYPE_UINT64:
  653. case OBJECTIVECTYPE_FLOAT:
  654. case OBJECTIVECTYPE_DOUBLE:
  655. case OBJECTIVECTYPE_BOOLEAN:
  656. case OBJECTIVECTYPE_ENUM:
  657. return true;
  658. break;
  659. default:
  660. return false;
  661. }
  662. }
  663. bool IsReferenceType(const FieldDescriptor* field) {
  664. return !IsPrimitiveType(field);
  665. }
  666. static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) {
  667. if (val == "nan") {
  668. return "NAN";
  669. } else if (val == "inf") {
  670. return "INFINITY";
  671. } else if (val == "-inf") {
  672. return "-INFINITY";
  673. } else {
  674. // float strings with ., e or E need to have f appended
  675. if (add_float_suffix &&
  676. (val.find(".") != string::npos || val.find("e") != string::npos ||
  677. val.find("E") != string::npos)) {
  678. val += "f";
  679. }
  680. return val;
  681. }
  682. }
  683. string GPBGenericValueFieldName(const FieldDescriptor* field) {
  684. // Returns the field within the GPBGenericValue union to use for the given
  685. // field.
  686. if (field->is_repeated()) {
  687. return "valueMessage";
  688. }
  689. switch (field->cpp_type()) {
  690. case FieldDescriptor::CPPTYPE_INT32:
  691. return "valueInt32";
  692. case FieldDescriptor::CPPTYPE_UINT32:
  693. return "valueUInt32";
  694. case FieldDescriptor::CPPTYPE_INT64:
  695. return "valueInt64";
  696. case FieldDescriptor::CPPTYPE_UINT64:
  697. return "valueUInt64";
  698. case FieldDescriptor::CPPTYPE_FLOAT:
  699. return "valueFloat";
  700. case FieldDescriptor::CPPTYPE_DOUBLE:
  701. return "valueDouble";
  702. case FieldDescriptor::CPPTYPE_BOOL:
  703. return "valueBool";
  704. case FieldDescriptor::CPPTYPE_STRING:
  705. if (field->type() == FieldDescriptor::TYPE_BYTES) {
  706. return "valueData";
  707. } else {
  708. return "valueString";
  709. }
  710. case FieldDescriptor::CPPTYPE_ENUM:
  711. return "valueEnum";
  712. case FieldDescriptor::CPPTYPE_MESSAGE:
  713. return "valueMessage";
  714. }
  715. // Some compilers report reaching end of function even though all cases of
  716. // the enum are handed in the switch.
  717. GOOGLE_LOG(FATAL) << "Can't get here.";
  718. return string();
  719. }
  720. string DefaultValue(const FieldDescriptor* field) {
  721. // Repeated fields don't have defaults.
  722. if (field->is_repeated()) {
  723. return "nil";
  724. }
  725. // Switch on cpp_type since we need to know which default_value_* method
  726. // of FieldDescriptor to call.
  727. switch (field->cpp_type()) {
  728. case FieldDescriptor::CPPTYPE_INT32:
  729. // gcc and llvm reject the decimal form of kint32min and kint64min.
  730. if (field->default_value_int32() == INT_MIN) {
  731. return "-0x80000000";
  732. }
  733. return StrCat(field->default_value_int32());
  734. case FieldDescriptor::CPPTYPE_UINT32:
  735. return StrCat(field->default_value_uint32()) + "U";
  736. case FieldDescriptor::CPPTYPE_INT64:
  737. // gcc and llvm reject the decimal form of kint32min and kint64min.
  738. if (field->default_value_int64() == LLONG_MIN) {
  739. return "-0x8000000000000000LL";
  740. }
  741. return StrCat(field->default_value_int64()) + "LL";
  742. case FieldDescriptor::CPPTYPE_UINT64:
  743. return StrCat(field->default_value_uint64()) + "ULL";
  744. case FieldDescriptor::CPPTYPE_DOUBLE:
  745. return HandleExtremeFloatingPoint(
  746. SimpleDtoa(field->default_value_double()), false);
  747. case FieldDescriptor::CPPTYPE_FLOAT:
  748. return HandleExtremeFloatingPoint(
  749. SimpleFtoa(field->default_value_float()), true);
  750. case FieldDescriptor::CPPTYPE_BOOL:
  751. return field->default_value_bool() ? "YES" : "NO";
  752. case FieldDescriptor::CPPTYPE_STRING: {
  753. const bool has_default_value = field->has_default_value();
  754. const string& default_string = field->default_value_string();
  755. if (!has_default_value || default_string.length() == 0) {
  756. // If the field is defined as being the empty string,
  757. // then we will just assign to nil, as the empty string is the
  758. // default for both strings and data.
  759. return "nil";
  760. }
  761. if (field->type() == FieldDescriptor::TYPE_BYTES) {
  762. // We want constant fields in our data structures so we can
  763. // declare them as static. To achieve this we cheat and stuff
  764. // a escaped c string (prefixed with a length) into the data
  765. // field, and cast it to an (NSData*) so it will compile.
  766. // The runtime library knows how to handle it.
  767. // Must convert to a standard byte order for packing length into
  768. // a cstring.
  769. uint32 length = ghtonl(default_string.length());
  770. string bytes((const char*)&length, sizeof(length));
  771. bytes.append(default_string);
  772. return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\"";
  773. } else {
  774. return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\"";
  775. }
  776. }
  777. case FieldDescriptor::CPPTYPE_ENUM:
  778. return EnumValueName(field->default_value_enum());
  779. case FieldDescriptor::CPPTYPE_MESSAGE:
  780. return "nil";
  781. }
  782. // Some compilers report reaching end of function even though all cases of
  783. // the enum are handed in the switch.
  784. GOOGLE_LOG(FATAL) << "Can't get here.";
  785. return string();
  786. }
  787. bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
  788. // Repeated fields don't have defaults.
  789. if (field->is_repeated()) {
  790. return false;
  791. }
  792. // As much as checking field->has_default_value() seems useful, it isn't
  793. // because of enums. proto2 syntax allows the first item in an enum (the
  794. // default) to be non zero. So checking field->has_default_value() would
  795. // result in missing this non zero default. See MessageWithOneBasedEnum in
  796. // objectivec/Tests/unittest_objc.proto for a test Message to confirm this.
  797. // Some proto file set the default to the zero value, so make sure the value
  798. // isn't the zero case.
  799. switch (field->cpp_type()) {
  800. case FieldDescriptor::CPPTYPE_INT32:
  801. return field->default_value_int32() != 0;
  802. case FieldDescriptor::CPPTYPE_UINT32:
  803. return field->default_value_uint32() != 0U;
  804. case FieldDescriptor::CPPTYPE_INT64:
  805. return field->default_value_int64() != 0LL;
  806. case FieldDescriptor::CPPTYPE_UINT64:
  807. return field->default_value_uint64() != 0ULL;
  808. case FieldDescriptor::CPPTYPE_DOUBLE:
  809. return field->default_value_double() != 0.0;
  810. case FieldDescriptor::CPPTYPE_FLOAT:
  811. return field->default_value_float() != 0.0f;
  812. case FieldDescriptor::CPPTYPE_BOOL:
  813. return field->default_value_bool();
  814. case FieldDescriptor::CPPTYPE_STRING: {
  815. const string& default_string = field->default_value_string();
  816. return default_string.length() != 0;
  817. }
  818. case FieldDescriptor::CPPTYPE_ENUM:
  819. return field->default_value_enum()->number() != 0;
  820. case FieldDescriptor::CPPTYPE_MESSAGE:
  821. return false;
  822. }
  823. // Some compilers report reaching end of function even though all cases of
  824. // the enum are handed in the switch.
  825. GOOGLE_LOG(FATAL) << "Can't get here.";
  826. return false;
  827. }
  828. string BuildFlagsString(const FlagType flag_type,
  829. const std::vector<string>& strings) {
  830. if (strings.empty()) {
  831. return GetZeroEnumNameForFlagType(flag_type);
  832. } else if (strings.size() == 1) {
  833. return strings[0];
  834. }
  835. string string("(" + GetEnumNameForFlagType(flag_type) + ")(");
  836. for (size_t i = 0; i != strings.size(); ++i) {
  837. if (i > 0) {
  838. string.append(" | ");
  839. }
  840. string.append(strings[i]);
  841. }
  842. string.append(")");
  843. return string;
  844. }
  845. string BuildCommentsString(const SourceLocation& location,
  846. bool prefer_single_line) {
  847. const string& comments = location.leading_comments.empty()
  848. ? location.trailing_comments
  849. : location.leading_comments;
  850. std::vector<string> lines;
  851. lines = Split(comments, "\n", false);
  852. while (!lines.empty() && lines.back().empty()) {
  853. lines.pop_back();
  854. }
  855. // If there are no comments, just return an empty string.
  856. if (lines.empty()) {
  857. return "";
  858. }
  859. string prefix;
  860. string suffix;
  861. string final_comments;
  862. string epilogue;
  863. bool add_leading_space = false;
  864. if (prefer_single_line && lines.size() == 1) {
  865. prefix = "/** ";
  866. suffix = " */\n";
  867. } else {
  868. prefix = "* ";
  869. suffix = "\n";
  870. final_comments += "/**\n";
  871. epilogue = " **/\n";
  872. add_leading_space = true;
  873. }
  874. for (int i = 0; i < lines.size(); i++) {
  875. string line = StripPrefixString(lines[i], " ");
  876. // HeaderDoc and appledoc use '\' and '@' for markers; escape them.
  877. line = StringReplace(line, "\\", "\\\\", true);
  878. line = StringReplace(line, "@", "\\@", true);
  879. // Decouple / from * to not have inline comments inside comments.
  880. line = StringReplace(line, "/*", "/\\*", true);
  881. line = StringReplace(line, "*/", "*\\/", true);
  882. line = prefix + line;
  883. StripWhitespace(&line);
  884. // If not a one line, need to add the first space before *, as
  885. // StripWhitespace would have removed it.
  886. line = (add_leading_space ? " " : "") + line;
  887. final_comments += line + suffix;
  888. }
  889. final_comments += epilogue;
  890. return final_comments;
  891. }
  892. // Making these a generator option for folks that don't use CocoaPods, but do
  893. // want to put the library in a framework is an interesting question. The
  894. // problem is it means changing sources shipped with the library to actually
  895. // use a different value; so it isn't as simple as a option.
  896. const char* const ProtobufLibraryFrameworkName = "Protobuf";
  897. string ProtobufFrameworkImportSymbol(const string& framework_name) {
  898. // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS
  899. string result = string("GPB_USE_");
  900. result += ToUpper(framework_name);
  901. result += "_FRAMEWORK_IMPORTS";
  902. return result;
  903. }
  904. bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) {
  905. // We don't check the name prefix or proto package because some files
  906. // (descriptor.proto), aren't shipped generated by the library, so this
  907. // seems to be the safest way to only catch the ones shipped.
  908. const string name = file->name();
  909. if (name == "google/protobuf/any.proto" ||
  910. name == "google/protobuf/api.proto" ||
  911. name == "google/protobuf/duration.proto" ||
  912. name == "google/protobuf/empty.proto" ||
  913. name == "google/protobuf/field_mask.proto" ||
  914. name == "google/protobuf/source_context.proto" ||
  915. name == "google/protobuf/struct.proto" ||
  916. name == "google/protobuf/timestamp.proto" ||
  917. name == "google/protobuf/type.proto" ||
  918. name == "google/protobuf/wrappers.proto") {
  919. return true;
  920. }
  921. return false;
  922. }
  923. bool ReadLine(StringPiece* input, StringPiece* line) {
  924. for (int len = 0; len < input->size(); ++len) {
  925. if (ascii_isnewline((*input)[len])) {
  926. *line = StringPiece(input->data(), len);
  927. ++len; // advance over the newline
  928. *input = StringPiece(input->data() + len, input->size() - len);
  929. return true;
  930. }
  931. }
  932. return false; // Ran out of input with no newline.
  933. }
  934. void RemoveComment(StringPiece* input) {
  935. int offset = input->find('#');
  936. if (offset != StringPiece::npos) {
  937. input->remove_suffix(input->length() - offset);
  938. }
  939. }
  940. namespace {
  941. class ExpectedPrefixesCollector : public LineConsumer {
  942. public:
  943. ExpectedPrefixesCollector(std::map<string, string>* inout_package_to_prefix_map)
  944. : prefix_map_(inout_package_to_prefix_map) {}
  945. virtual bool ConsumeLine(const StringPiece& line, string* out_error);
  946. private:
  947. std::map<string, string>* prefix_map_;
  948. };
  949. bool ExpectedPrefixesCollector::ConsumeLine(
  950. const StringPiece& line, string* out_error) {
  951. int offset = line.find('=');
  952. if (offset == StringPiece::npos) {
  953. *out_error = string("Expected prefixes file line without equal sign: '") +
  954. string(line) + "'.";
  955. return false;
  956. }
  957. StringPiece package = line.substr(0, offset);
  958. StringPiece prefix = line.substr(offset + 1);
  959. TrimWhitespace(&package);
  960. TrimWhitespace(&prefix);
  961. // Don't really worry about error checking the package/prefix for
  962. // being valid. Assume the file is validated when it is created/edited.
  963. (*prefix_map_)[string(package)] = string(prefix);
  964. return true;
  965. }
  966. bool LoadExpectedPackagePrefixes(const Options &generation_options,
  967. std::map<string, string>* prefix_map,
  968. string* out_error) {
  969. if (generation_options.expected_prefixes_path.empty()) {
  970. return true;
  971. }
  972. ExpectedPrefixesCollector collector(prefix_map);
  973. return ParseSimpleFile(
  974. generation_options.expected_prefixes_path, &collector, out_error);
  975. }
  976. bool ValidateObjCClassPrefix(
  977. const FileDescriptor* file,
  978. const string& expected_prefixes_path,
  979. const std::map<string, string>& expected_package_prefixes,
  980. string* out_error) {
  981. const string prefix = file->options().objc_class_prefix();
  982. const string package = file->package();
  983. // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
  984. // error cases, so it seems to be ok to use as a back door for warnings.
  985. // Check: Error - See if there was an expected prefix for the package and
  986. // report if it doesn't match (wrong or missing).
  987. std::map<string, string>::const_iterator package_match =
  988. expected_package_prefixes.find(package);
  989. if (package_match != expected_package_prefixes.end()) {
  990. // There was an entry, and...
  991. if (package_match->second == prefix) {
  992. // ...it matches. All good, out of here!
  993. return true;
  994. } else {
  995. // ...it didn't match!
  996. *out_error = "error: Expected 'option objc_class_prefix = \"" +
  997. package_match->second + "\";' for package '" + package +
  998. "' in '" + file->name() + "'";
  999. if (prefix.length()) {
  1000. *out_error += "; but found '" + prefix + "' instead";
  1001. }
  1002. *out_error += ".";
  1003. return false;
  1004. }
  1005. }
  1006. // If there was no prefix option, we're done at this point.
  1007. if (prefix.empty()) {
  1008. // No prefix, nothing left to check.
  1009. return true;
  1010. }
  1011. // Check: Warning - Make sure the prefix is is a reasonable value according
  1012. // to Apple's rules (the checks above implicitly whitelist anything that
  1013. // doesn't meet these rules).
  1014. if (!ascii_isupper(prefix[0])) {
  1015. std::cerr << std::endl
  1016. << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
  1017. << prefix << "\";' in '" << file->name() << "';"
  1018. << " it should start with a capital letter." << std::endl;
  1019. std::cerr.flush();
  1020. }
  1021. if (prefix.length() < 3) {
  1022. // Apple reserves 2 character prefixes for themselves. They do use some
  1023. // 3 character prefixes, but they haven't updated the rules/docs.
  1024. std::cerr << std::endl
  1025. << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
  1026. << prefix << "\";' in '" << file->name() << "';"
  1027. << " Apple recommends they should be at least 3 characters long."
  1028. << std::endl;
  1029. std::cerr.flush();
  1030. }
  1031. // Look for any other package that uses the same prefix.
  1032. string other_package_for_prefix;
  1033. for (std::map<string, string>::const_iterator i = expected_package_prefixes.begin();
  1034. i != expected_package_prefixes.end(); ++i) {
  1035. if (i->second == prefix) {
  1036. other_package_for_prefix = i->first;
  1037. break;
  1038. }
  1039. }
  1040. // Check: Warning - If the file does not have a package, check whether
  1041. // the prefix declared is being used by another package or not.
  1042. if (package.empty()) {
  1043. // The file does not have a package and ...
  1044. if (other_package_for_prefix.empty()) {
  1045. // ... no other package has declared that prefix.
  1046. std::cerr << std::endl
  1047. << "protoc:0: warning: File '" << file->name() << "' has no "
  1048. << "package. Consider adding a new package to the proto and adding '"
  1049. << "new.package = " << prefix << "' to the expected prefixes file ("
  1050. << expected_prefixes_path << ")." << std::endl;
  1051. std::cerr.flush();
  1052. } else {
  1053. // ... another package has declared the same prefix.
  1054. std::cerr << std::endl
  1055. << "protoc:0: warning: File '" << file->name() << "' has no package "
  1056. << "and package '" << other_package_for_prefix << "' already uses '"
  1057. << prefix << "' as its prefix. Consider either adding a new package "
  1058. << "to the proto, or reusing one of the packages already using this "
  1059. << "prefix in the expected prefixes file ("
  1060. << expected_prefixes_path << ")." << std::endl;
  1061. std::cerr.flush();
  1062. }
  1063. return true;
  1064. }
  1065. // Check: Error - Make sure the prefix wasn't expected for a different
  1066. // package (overlap is allowed, but it has to be listed as an expected
  1067. // overlap).
  1068. if (!other_package_for_prefix.empty()) {
  1069. *out_error =
  1070. "error: Found 'option objc_class_prefix = \"" + prefix +
  1071. "\";' in '" + file->name() +
  1072. "'; that prefix is already used for 'package " +
  1073. other_package_for_prefix + ";'. It can only be reused by listing " +
  1074. "it in the expected file (" +
  1075. expected_prefixes_path + ").";
  1076. return false; // Only report first usage of the prefix.
  1077. }
  1078. // Check: Warning - If the given package/prefix pair wasn't expected, issue a
  1079. // warning issue a warning suggesting it gets added to the file.
  1080. if (!expected_package_prefixes.empty()) {
  1081. std::cerr << std::endl
  1082. << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
  1083. << prefix << "\";' in '" << file->name() << "';"
  1084. << " consider adding it to the expected prefixes file ("
  1085. << expected_prefixes_path << ")." << std::endl;
  1086. std::cerr.flush();
  1087. }
  1088. return true;
  1089. }
  1090. } // namespace
  1091. bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
  1092. const Options& generation_options,
  1093. string* out_error) {
  1094. // Load the expected package prefixes, if available, to validate against.
  1095. std::map<string, string> expected_package_prefixes;
  1096. if (!LoadExpectedPackagePrefixes(generation_options,
  1097. &expected_package_prefixes,
  1098. out_error)) {
  1099. return false;
  1100. }
  1101. for (int i = 0; i < files.size(); i++) {
  1102. bool should_skip =
  1103. (std::find(generation_options.expected_prefixes_suppressions.begin(),
  1104. generation_options.expected_prefixes_suppressions.end(),
  1105. files[i]->name())
  1106. != generation_options.expected_prefixes_suppressions.end());
  1107. if (should_skip) {
  1108. continue;
  1109. }
  1110. bool is_valid =
  1111. ValidateObjCClassPrefix(files[i],
  1112. generation_options.expected_prefixes_path,
  1113. expected_package_prefixes,
  1114. out_error);
  1115. if (!is_valid) {
  1116. return false;
  1117. }
  1118. }
  1119. return true;
  1120. }
  1121. TextFormatDecodeData::TextFormatDecodeData() { }
  1122. TextFormatDecodeData::~TextFormatDecodeData() { }
  1123. void TextFormatDecodeData::AddString(int32 key,
  1124. const string& input_for_decode,
  1125. const string& desired_output) {
  1126. for (std::vector<DataEntry>::const_iterator i = entries_.begin();
  1127. i != entries_.end(); ++i) {
  1128. if (i->first == key) {
  1129. std::cerr << "error: duplicate key (" << key
  1130. << ") making TextFormat data, input: \"" << input_for_decode
  1131. << "\", desired: \"" << desired_output << "\"." << std::endl;
  1132. std::cerr.flush();
  1133. abort();
  1134. }
  1135. }
  1136. const string& data = TextFormatDecodeData::DecodeDataForString(
  1137. input_for_decode, desired_output);
  1138. entries_.push_back(DataEntry(key, data));
  1139. }
  1140. string TextFormatDecodeData::Data() const {
  1141. std::ostringstream data_stringstream;
  1142. if (num_entries() > 0) {
  1143. io::OstreamOutputStream data_outputstream(&data_stringstream);
  1144. io::CodedOutputStream output_stream(&data_outputstream);
  1145. output_stream.WriteVarint32(num_entries());
  1146. for (std::vector<DataEntry>::const_iterator i = entries_.begin();
  1147. i != entries_.end(); ++i) {
  1148. output_stream.WriteVarint32(i->first);
  1149. output_stream.WriteString(i->second);
  1150. }
  1151. }
  1152. data_stringstream.flush();
  1153. return data_stringstream.str();
  1154. }
  1155. namespace {
  1156. // Helper to build up the decode data for a string.
  1157. class DecodeDataBuilder {
  1158. public:
  1159. DecodeDataBuilder() { Reset(); }
  1160. bool AddCharacter(const char desired, const char input);
  1161. void AddUnderscore() {
  1162. Push();
  1163. need_underscore_ = true;
  1164. }
  1165. string Finish() {
  1166. Push();
  1167. return decode_data_;
  1168. }
  1169. private:
  1170. static constexpr uint8 kAddUnderscore = 0x80;
  1171. static constexpr uint8 kOpAsIs = 0x00;
  1172. static constexpr uint8 kOpFirstUpper = 0x40;
  1173. static constexpr uint8 kOpFirstLower = 0x20;
  1174. static constexpr uint8 kOpAllUpper = 0x60;
  1175. static constexpr int kMaxSegmentLen = 0x1f;
  1176. void AddChar(const char desired) {
  1177. ++segment_len_;
  1178. is_all_upper_ &= ascii_isupper(desired);
  1179. }
  1180. void Push() {
  1181. uint8 op = (op_ | segment_len_);
  1182. if (need_underscore_) op |= kAddUnderscore;
  1183. if (op != 0) {
  1184. decode_data_ += (char)op;
  1185. }
  1186. Reset();
  1187. }
  1188. bool AddFirst(const char desired, const char input) {
  1189. if (desired == input) {
  1190. op_ = kOpAsIs;
  1191. } else if (desired == ascii_toupper(input)) {
  1192. op_ = kOpFirstUpper;
  1193. } else if (desired == ascii_tolower(input)) {
  1194. op_ = kOpFirstLower;
  1195. } else {
  1196. // Can't be transformed to match.
  1197. return false;
  1198. }
  1199. AddChar(desired);
  1200. return true;
  1201. }
  1202. void Reset() {
  1203. need_underscore_ = false;
  1204. op_ = 0;
  1205. segment_len_ = 0;
  1206. is_all_upper_ = true;
  1207. }
  1208. bool need_underscore_;
  1209. bool is_all_upper_;
  1210. uint8 op_;
  1211. int segment_len_;
  1212. string decode_data_;
  1213. };
  1214. bool DecodeDataBuilder::AddCharacter(const char desired, const char input) {
  1215. // If we've hit the max size, push to start a new segment.
  1216. if (segment_len_ == kMaxSegmentLen) {
  1217. Push();
  1218. }
  1219. if (segment_len_ == 0) {
  1220. return AddFirst(desired, input);
  1221. }
  1222. // Desired and input match...
  1223. if (desired == input) {
  1224. // If we aren't transforming it, or we're upper casing it and it is
  1225. // supposed to be uppercase; just add it to the segment.
  1226. if ((op_ != kOpAllUpper) || ascii_isupper(desired)) {
  1227. AddChar(desired);
  1228. return true;
  1229. }
  1230. // Add the current segment, and start the next one.
  1231. Push();
  1232. return AddFirst(desired, input);
  1233. }
  1234. // If we need to uppercase, and everything so far has been uppercase,
  1235. // promote op to AllUpper.
  1236. if ((desired == ascii_toupper(input)) && is_all_upper_) {
  1237. op_ = kOpAllUpper;
  1238. AddChar(desired);
  1239. return true;
  1240. }
  1241. // Give up, push and start a new segment.
  1242. Push();
  1243. return AddFirst(desired, input);
  1244. }
  1245. // If decode data can't be generated, a directive for the raw string
  1246. // is used instead.
  1247. string DirectDecodeString(const string& str) {
  1248. string result;
  1249. result += (char)'\0'; // Marker for full string.
  1250. result += str;
  1251. result += (char)'\0'; // End of string.
  1252. return result;
  1253. }
  1254. } // namespace
  1255. // static
  1256. string TextFormatDecodeData::DecodeDataForString(const string& input_for_decode,
  1257. const string& desired_output) {
  1258. if (input_for_decode.empty() || desired_output.empty()) {
  1259. std::cerr << "error: got empty string for making TextFormat data, input: \""
  1260. << input_for_decode << "\", desired: \"" << desired_output << "\"."
  1261. << std::endl;
  1262. std::cerr.flush();
  1263. abort();
  1264. }
  1265. if ((input_for_decode.find('\0') != string::npos) ||
  1266. (desired_output.find('\0') != string::npos)) {
  1267. std::cerr << "error: got a null char in a string for making TextFormat data,"
  1268. << " input: \"" << CEscape(input_for_decode) << "\", desired: \""
  1269. << CEscape(desired_output) << "\"." << std::endl;
  1270. std::cerr.flush();
  1271. abort();
  1272. }
  1273. DecodeDataBuilder builder;
  1274. // Walk the output building it from the input.
  1275. int x = 0;
  1276. for (int y = 0; y < desired_output.size(); y++) {
  1277. const char d = desired_output[y];
  1278. if (d == '_') {
  1279. builder.AddUnderscore();
  1280. continue;
  1281. }
  1282. if (x >= input_for_decode.size()) {
  1283. // Out of input, no way to encode it, just return a full decode.
  1284. return DirectDecodeString(desired_output);
  1285. }
  1286. if (builder.AddCharacter(d, input_for_decode[x])) {
  1287. ++x; // Consumed one input
  1288. } else {
  1289. // Couldn't transform for the next character, just return a full decode.
  1290. return DirectDecodeString(desired_output);
  1291. }
  1292. }
  1293. if (x != input_for_decode.size()) {
  1294. // Extra input (suffix from name sanitizing?), just return a full decode.
  1295. return DirectDecodeString(desired_output);
  1296. }
  1297. // Add the end marker.
  1298. return builder.Finish() + (char)'\0';
  1299. }
  1300. namespace {
  1301. class Parser {
  1302. public:
  1303. Parser(LineConsumer* line_consumer)
  1304. : line_consumer_(line_consumer), line_(0) {}
  1305. // Parses a check of input, returning success/failure.
  1306. bool ParseChunk(StringPiece chunk);
  1307. // Should be called to finish parsing (after all input has been provided via
  1308. // ParseChunk()). Returns success/failure.
  1309. bool Finish();
  1310. int last_line() const { return line_; }
  1311. string error_str() const { return error_str_; }
  1312. private:
  1313. bool ParseLoop();
  1314. LineConsumer* line_consumer_;
  1315. int line_;
  1316. string error_str_;
  1317. StringPiece p_;
  1318. string leftover_;
  1319. };
  1320. bool Parser::ParseChunk(StringPiece chunk) {
  1321. if (!leftover_.empty()) {
  1322. leftover_ += string(chunk);
  1323. p_ = StringPiece(leftover_);
  1324. } else {
  1325. p_ = chunk;
  1326. }
  1327. bool result = ParseLoop();
  1328. if (p_.empty()) {
  1329. leftover_.clear();
  1330. } else {
  1331. leftover_ = string(p_);
  1332. }
  1333. return result;
  1334. }
  1335. bool Parser::Finish() {
  1336. if (leftover_.empty()) {
  1337. return true;
  1338. }
  1339. // Force a newline onto the end to finish parsing.
  1340. leftover_ += "\n";
  1341. p_ = StringPiece(leftover_);
  1342. if (!ParseLoop()) {
  1343. return false;
  1344. }
  1345. return p_.empty(); // Everything used?
  1346. }
  1347. bool Parser::ParseLoop() {
  1348. StringPiece line;
  1349. while (ReadLine(&p_, &line)) {
  1350. ++line_;
  1351. RemoveComment(&line);
  1352. TrimWhitespace(&line);
  1353. if (line.empty()) {
  1354. continue; // Blank line.
  1355. }
  1356. if (!line_consumer_->ConsumeLine(line, &error_str_)) {
  1357. return false;
  1358. }
  1359. }
  1360. return true;
  1361. }
  1362. } // namespace
  1363. LineConsumer::LineConsumer() {}
  1364. LineConsumer::~LineConsumer() {}
  1365. bool ParseSimpleFile(
  1366. const string& path, LineConsumer* line_consumer, string* out_error) {
  1367. int fd;
  1368. do {
  1369. fd = posix::open(path.c_str(), O_RDONLY);
  1370. } while (fd < 0 && errno == EINTR);
  1371. if (fd < 0) {
  1372. *out_error =
  1373. string("error: Unable to open \"") + path + "\", " + strerror(errno);
  1374. return false;
  1375. }
  1376. io::FileInputStream file_stream(fd);
  1377. file_stream.SetCloseOnDelete(true);
  1378. Parser parser(line_consumer);
  1379. const void* buf;
  1380. int buf_len;
  1381. while (file_stream.Next(&buf, &buf_len)) {
  1382. if (buf_len == 0) {
  1383. continue;
  1384. }
  1385. if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len))) {
  1386. *out_error =
  1387. string("error: ") + path +
  1388. " Line " + StrCat(parser.last_line()) + ", " + parser.error_str();
  1389. return false;
  1390. }
  1391. }
  1392. return parser.Finish();
  1393. }
  1394. ImportWriter::ImportWriter(
  1395. const string& generate_for_named_framework,
  1396. const string& named_framework_to_proto_path_mappings_path,
  1397. const string& runtime_import_prefix,
  1398. bool include_wkt_imports)
  1399. : generate_for_named_framework_(generate_for_named_framework),
  1400. named_framework_to_proto_path_mappings_path_(
  1401. named_framework_to_proto_path_mappings_path),
  1402. runtime_import_prefix_(runtime_import_prefix),
  1403. include_wkt_imports_(include_wkt_imports),
  1404. need_to_parse_mapping_file_(true) {
  1405. }
  1406. ImportWriter::~ImportWriter() {}
  1407. void ImportWriter::AddFile(const FileDescriptor* file,
  1408. const string& header_extension) {
  1409. if (IsProtobufLibraryBundledProtoFile(file)) {
  1410. // The imports of the WKTs are only needed within the library itself,
  1411. // in other cases, they get skipped because the generated code already
  1412. // import GPBProtocolBuffers.h and hence proves them.
  1413. if (include_wkt_imports_) {
  1414. const string header_name =
  1415. "GPB" + FilePathBasename(file) + header_extension;
  1416. protobuf_imports_.push_back(header_name);
  1417. }
  1418. return;
  1419. }
  1420. // Lazy parse any mappings.
  1421. if (need_to_parse_mapping_file_) {
  1422. ParseFrameworkMappings();
  1423. }
  1424. std::map<string, string>::iterator proto_lookup =
  1425. proto_file_to_framework_name_.find(file->name());
  1426. if (proto_lookup != proto_file_to_framework_name_.end()) {
  1427. other_framework_imports_.push_back(
  1428. proto_lookup->second + "/" +
  1429. FilePathBasename(file) + header_extension);
  1430. return;
  1431. }
  1432. if (!generate_for_named_framework_.empty()) {
  1433. other_framework_imports_.push_back(
  1434. generate_for_named_framework_ + "/" +
  1435. FilePathBasename(file) + header_extension);
  1436. return;
  1437. }
  1438. other_imports_.push_back(FilePath(file) + header_extension);
  1439. }
  1440. void ImportWriter::Print(io::Printer* printer) const {
  1441. bool add_blank_line = false;
  1442. if (!protobuf_imports_.empty()) {
  1443. PrintRuntimeImports(printer, protobuf_imports_, runtime_import_prefix_);
  1444. add_blank_line = true;
  1445. }
  1446. if (!other_framework_imports_.empty()) {
  1447. if (add_blank_line) {
  1448. printer->Print("\n");
  1449. }
  1450. for (std::vector<string>::const_iterator iter = other_framework_imports_.begin();
  1451. iter != other_framework_imports_.end(); ++iter) {
  1452. printer->Print(
  1453. "#import <$header$>\n",
  1454. "header", *iter);
  1455. }
  1456. add_blank_line = true;
  1457. }
  1458. if (!other_imports_.empty()) {
  1459. if (add_blank_line) {
  1460. printer->Print("\n");
  1461. }
  1462. for (std::vector<string>::const_iterator iter = other_imports_.begin();
  1463. iter != other_imports_.end(); ++iter) {
  1464. printer->Print(
  1465. "#import \"$header$\"\n",
  1466. "header", *iter);
  1467. }
  1468. }
  1469. }
  1470. void ImportWriter::PrintRuntimeImports(
  1471. io::Printer* printer,
  1472. const std::vector<string>& header_to_import,
  1473. const string& runtime_import_prefix,
  1474. bool default_cpp_symbol) {
  1475. // Given an override, use that.
  1476. if (!runtime_import_prefix.empty()) {
  1477. for (const auto& header : header_to_import) {
  1478. printer->Print(
  1479. " #import \"$import_prefix$/$header$\"\n",
  1480. "import_prefix", runtime_import_prefix,
  1481. "header", header);
  1482. }
  1483. return;
  1484. }
  1485. const string framework_name(ProtobufLibraryFrameworkName);
  1486. const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name));
  1487. if (default_cpp_symbol) {
  1488. printer->Print(
  1489. "// This CPP symbol can be defined to use imports that match up to the framework\n"
  1490. "// imports needed when using CocoaPods.\n"
  1491. "#if !defined($cpp_symbol$)\n"
  1492. " #define $cpp_symbol$ 0\n"
  1493. "#endif\n"
  1494. "\n",
  1495. "cpp_symbol", cpp_symbol);
  1496. }
  1497. printer->Print(
  1498. "#if $cpp_symbol$\n",
  1499. "cpp_symbol", cpp_symbol);
  1500. for (const auto& header : header_to_import) {
  1501. printer->Print(
  1502. " #import <$framework_name$/$header$>\n",
  1503. "framework_name", framework_name,
  1504. "header", header);
  1505. }
  1506. printer->Print(
  1507. "#else\n");
  1508. for (const auto& header : header_to_import) {
  1509. printer->Print(
  1510. " #import \"$header$\"\n",
  1511. "header", header);
  1512. }
  1513. printer->Print(
  1514. "#endif\n");
  1515. }
  1516. void ImportWriter::ParseFrameworkMappings() {
  1517. need_to_parse_mapping_file_ = false;
  1518. if (named_framework_to_proto_path_mappings_path_.empty()) {
  1519. return; // Nothing to do.
  1520. }
  1521. ProtoFrameworkCollector collector(&proto_file_to_framework_name_);
  1522. string parse_error;
  1523. if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_,
  1524. &collector, &parse_error)) {
  1525. std::cerr << "error parsing " << named_framework_to_proto_path_mappings_path_
  1526. << " : " << parse_error << std::endl;
  1527. std::cerr.flush();
  1528. }
  1529. }
  1530. bool ImportWriter::ProtoFrameworkCollector::ConsumeLine(
  1531. const StringPiece& line, string* out_error) {
  1532. int offset = line.find(':');
  1533. if (offset == StringPiece::npos) {
  1534. *out_error =
  1535. string("Framework/proto file mapping line without colon sign: '") +
  1536. string(line) + "'.";
  1537. return false;
  1538. }
  1539. StringPiece framework_name = line.substr(0, offset);
  1540. StringPiece proto_file_list = line.substr(offset + 1);
  1541. TrimWhitespace(&framework_name);
  1542. int start = 0;
  1543. while (start < proto_file_list.length()) {
  1544. offset = proto_file_list.find(',', start);
  1545. if (offset == StringPiece::npos) {
  1546. offset = proto_file_list.length();
  1547. }
  1548. StringPiece proto_file = proto_file_list.substr(start, offset - start);
  1549. TrimWhitespace(&proto_file);
  1550. if (!proto_file.empty()) {
  1551. std::map<string, string>::iterator existing_entry =
  1552. map_->find(string(proto_file));
  1553. if (existing_entry != map_->end()) {
  1554. std::cerr << "warning: duplicate proto file reference, replacing "
  1555. "framework entry for '"
  1556. << string(proto_file) << "' with '" << string(framework_name)
  1557. << "' (was '" << existing_entry->second << "')." << std::endl;
  1558. std::cerr.flush();
  1559. }
  1560. if (proto_file.find(' ') != StringPiece::npos) {
  1561. std::cerr << "note: framework mapping file had a proto file with a "
  1562. "space in, hopefully that isn't a missing comma: '"
  1563. << string(proto_file) << "'" << std::endl;
  1564. std::cerr.flush();
  1565. }
  1566. (*map_)[string(proto_file)] = string(framework_name);
  1567. }
  1568. start = offset + 1;
  1569. }
  1570. return true;
  1571. }
  1572. } // namespace objectivec
  1573. } // namespace compiler
  1574. } // namespace protobuf
  1575. } // namespace google