objectivec_helpers.cc 54 KB

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