cProtoBufProtoNodes.pas 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282
  1. {******************************************************************************}
  2. { }
  3. { Library: Fundamentals 4.00 }
  4. { File name: cProtoBufProtoNodes.pas }
  5. { File version: 0.02 }
  6. { Description: Protocol Buffer proto file nodes. }
  7. { }
  8. { Copyright: Copyright (c) 2012-2013, David J Butler }
  9. { All rights reserved. }
  10. { This file is licensed under the BSD License. }
  11. { See http://www.opensource.org/licenses/bsd-license.php }
  12. { Redistribution and use in source and binary forms, with }
  13. { or without modification, are permitted provided that }
  14. { the following conditions are met: }
  15. { Redistributions of source code must retain the above }
  16. { copyright notice, this list of conditions and the }
  17. { following disclaimer. }
  18. { THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
  19. { CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
  20. { WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
  21. { WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
  22. { PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
  23. { THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
  24. { INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
  25. { CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
  26. { PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
  27. { USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
  28. { HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
  29. { IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
  30. { NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
  31. { USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
  32. { POSSIBILITY OF SUCH DAMAGE. }
  33. { }
  34. { Home page: http://fundementals.sourceforge.net }
  35. { Forum: http://sourceforge.net/forum/forum.php?forum_id=2117 }
  36. { E-mail: fundamentals.library@gmail.com }
  37. { }
  38. { Revision history: }
  39. { }
  40. { 2012/04/15 0.01 Initial development: Proto nodes. }
  41. { 2012/04/26 0.02 Resolve delimited identifiers. }
  42. { }
  43. {******************************************************************************}
  44. {$INCLUDE cProtoBuf.inc}
  45. unit cProtoBufProtoNodes;
  46. interface
  47. uses
  48. { System }
  49. SysUtils;
  50. type
  51. TpbProtoNodeFactory = class;
  52. TpbProtoNode = class
  53. protected
  54. public
  55. function ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; virtual;
  56. function ResolveType(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; virtual;
  57. function ExpectResolvedValue(const AIdentifier: AnsiString): TpbProtoNode;
  58. function ExpectResolvedType(const AIdentifier: AnsiString): TpbProtoNode;
  59. function GetAsProtoString: AnsiString; virtual;
  60. end;
  61. EpbProtoNode = class(Exception);
  62. TpbProtoEnum = class; // forward
  63. TpbProtoEnumValue = class(TpbProtoNode)
  64. protected
  65. FParentEnum : TpbProtoEnum;
  66. FName : AnsiString;
  67. FValue : LongInt;
  68. public
  69. constructor Create(const AParentEnum: TpbProtoEnum);
  70. property Name: AnsiString read FName write FName;
  71. property Value: LongInt read FValue write FValue;
  72. function GetAsProtoString: AnsiString; override;
  73. end;
  74. TpbProtoMessage = class; // forward
  75. TpbProtoEnum = class(TpbProtoNode)
  76. protected
  77. FName : AnsiString;
  78. FValues : array of TpbProtoEnumValue;
  79. public
  80. constructor Create(const AParentNode: TpbProtoNode);
  81. property Name: AnsiString read FName write FName;
  82. procedure Add(const V: TpbProtoEnumValue);
  83. function GetValueCount: Integer;
  84. function GetValue(const Idx: Integer): TpbProtoEnumValue;
  85. function GetValueByName(const AName: AnsiString): TpbProtoEnumValue;
  86. function ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; override;
  87. function GetAsProtoString: AnsiString; override;
  88. end;
  89. TpbProtoLiteralType = (
  90. pltNone,
  91. pltInteger,
  92. pltFloat,
  93. pltString,
  94. pltBoolean,
  95. pltIdentifier
  96. );
  97. TpbProtoLiteral = class(TpbProtoNode)
  98. protected
  99. FParentNode : TpbProtoNode;
  100. FLiteralType : TpbProtoLiteralType;
  101. FLiteralInt : Int64;
  102. FLiteralFloat : Extended;
  103. FLiteralStr : AnsiString;
  104. FLiteralBool : Boolean;
  105. FLiteralIden : AnsiString;
  106. public
  107. constructor Create(const AParentNode: TpbProtoNode);
  108. property LiteralType: TpbProtoLiteralType read FLiteralType write FLiteralType;
  109. property LiteralInt: Int64 read FLiteralInt write FLiteralInt;
  110. property LiteralFloat: Extended read FLiteralFloat write FLiteralFloat;
  111. property LiteralStr: AnsiString read FLiteralStr write FLiteralStr;
  112. property LiteralBool: Boolean read FLiteralBool write FLiteralBool;
  113. property LiteralIden: AnsiString read FLiteralIden write FLiteralIden;
  114. function ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; override;
  115. function GetAsProtoString: AnsiString; override;
  116. function LiteralIdenValue: TpbProtoNode;
  117. end;
  118. TpbProtoOption = class(TpbProtoNode)
  119. protected
  120. FCustom : Boolean;
  121. FName : AnsiString;
  122. FValue : TpbProtoLiteral;
  123. procedure SetValue(const Value: TpbProtoLiteral);
  124. public
  125. constructor Create(const AFactory: TpbProtoNodeFactory);
  126. destructor Destroy; override;
  127. property Custom: Boolean read FCustom write FCustom;
  128. property Name: AnsiString read FName write FName;
  129. property Value: TpbProtoLiteral read FValue write FValue;
  130. end;
  131. TpbProtoFieldCardinality = (
  132. pfcNone,
  133. pfcRequired,
  134. pfcOptional,
  135. pfcRepeated
  136. );
  137. TpbProtoFieldBaseType = (
  138. pftNone,
  139. pftDouble,
  140. pftFloat,
  141. pftInt32,
  142. pftInt64,
  143. pftUInt32,
  144. pftUInt64,
  145. pftSInt32,
  146. pftSInt64,
  147. pftFixed32,
  148. pftFixed64,
  149. pftSFixed32,
  150. pftSFixed64,
  151. pftBool,
  152. pftString,
  153. pftBytes,
  154. pftIdentifier
  155. );
  156. TpbProtoField = class; // forward
  157. TpbProtoFieldType = class(TpbProtoNode)
  158. protected
  159. FParentField : TpbProtoField;
  160. FBaseType : TpbProtoFieldBaseType;
  161. FIdenStr : AnsiString;
  162. public
  163. constructor Create(const AParentField: TpbProtoField);
  164. property ParentField: TpbProtoField read FParentField;
  165. property BaseType: TpbProtoFieldBaseType read FBaseType write FBaseType;
  166. property IdenStr: AnsiString read FIdenStr write FIdenStr;
  167. function ResolveType(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; override;
  168. function GetAsProtoString: AnsiString; override;
  169. function IsSimpleType: Boolean;
  170. function IsIdenType: Boolean;
  171. function IdenType: TpbProtoNode;
  172. end;
  173. TpbProtoField = class(TpbProtoNode)
  174. protected
  175. FParentMessage : TpbProtoMessage;
  176. FName : AnsiString;
  177. FFieldType : TpbProtoFieldType;
  178. FCardinality : TpbProtoFieldCardinality;
  179. FTagID : LongInt;
  180. FDefaultValue : TpbProtoLiteral;
  181. FOptionPacked : Boolean;
  182. FOptions : array of TpbProtoOption;
  183. procedure SetFieldType(const Value: TpbProtoFieldType);
  184. procedure SetDefaultValue(const Value: TpbProtoLiteral);
  185. public
  186. constructor Create(const AParentMessage: TpbProtoMessage; const AFactory: TpbProtoNodeFactory);
  187. destructor Destroy; override;
  188. property ParentMessage: TpbProtoMessage read FParentMessage;
  189. property Name: AnsiString read FName write FName;
  190. property FieldType: TpbProtoFieldType read FFieldType write SetFieldType;
  191. property Cardinality: TpbProtoFieldCardinality read FCardinality write FCardinality;
  192. property TagID: LongInt read FTagID write FTagID;
  193. property DefaultValue: TpbProtoLiteral read FDefaultValue write SetDefaultValue;
  194. property OptionPacked: Boolean read FOptionPacked write FOptionPacked;
  195. procedure AddOption(const Option: TpbProtoOption);
  196. function GetOptionCount: Integer;
  197. function GetOption(const Idx: Integer): TpbProtoOption;
  198. function ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; override;
  199. function ResolveType(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; override;
  200. function GetAsProtoString: AnsiString; override;
  201. end;
  202. TpbProtoMessage = class(TpbProtoNode)
  203. protected
  204. FParentNode : TpbProtoNode;
  205. FName : AnsiString;
  206. FMessages : array of TpbProtoMessage;
  207. FFields : array of TpbProtoField;
  208. FEnums : array of TpbProtoEnum;
  209. FExtensionsMin : LongInt;
  210. FExtensionsMax : LongInt;
  211. function GetFieldCount: Integer;
  212. function GetField(const Idx: Integer): TpbProtoField;
  213. function GetEnumCount: Integer;
  214. function GetEnum(const Idx: Integer): TpbProtoEnum;
  215. function GetEnumByName(const AName: AnsiString): TpbProtoEnum;
  216. function GetMessageCount: Integer;
  217. function GetMessage(const Idx: Integer): TpbProtoMessage;
  218. function GetMessageByName(const AName: AnsiString): TpbProtoMessage;
  219. public
  220. constructor Create(const AParentNode: TpbProtoNode);
  221. destructor Destroy; override;
  222. property ParentNode: TpbProtoNode read FParentNode;
  223. property Name: AnsiString read FName write FName;
  224. procedure AddField(const F: TpbProtoField);
  225. property FieldCount: Integer read GetFieldCount;
  226. property Field[const Idx: Integer]: TpbProtoField read GetField;
  227. function GetFieldByTagID(const ATagID: Integer): TpbProtoField;
  228. procedure AddEnum(const E: TpbProtoEnum);
  229. property EnumCount: Integer read GetEnumCount;
  230. property Enum[const Idx: Integer]: TpbProtoEnum read GetEnum;
  231. procedure AddMessage(const M: TpbProtoMessage);
  232. property MessageCount: Integer read GetMessageCount;
  233. property Msg[const Idx: Integer]: TpbProtoMessage read GetMessage;
  234. property ExtensionsMin: LongInt read FExtensionsMin write FExtensionsMin;
  235. property ExtensionsMax: LongInt read FExtensionsMax write FExtensionsMax;
  236. function ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; override;
  237. function ResolveType(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; override;
  238. function GetAsProtoString: AnsiString; override;
  239. end;
  240. TpbProtoPackage = class(TpbProtoNode)
  241. protected
  242. FFileName : AnsiString;
  243. FName : AnsiString;
  244. FMessages : array of TpbProtoMessage;
  245. FImports : array of AnsiString;
  246. FImportedPackages : array of TpbProtoPackage;
  247. FOptions : array of TpbProtoOption;
  248. FEnums : array of TpbProtoEnum;
  249. function GetEnumCount: Integer;
  250. function GetEnum(const Idx: Integer): TpbProtoEnum;
  251. function GetEnumByName(const AName: AnsiString): TpbProtoEnum;
  252. public
  253. constructor Create;
  254. destructor Destroy; override;
  255. property FileName: AnsiString read FFileName write FFileName;
  256. property Name: AnsiString read FName write FName;
  257. procedure AddMessage(const M: TpbProtoMessage);
  258. function GetMessageCount: Integer;
  259. function GetMessage(const Idx: Integer): TpbProtoMessage;
  260. function GetMessageByName(const AName: AnsiString): TpbProtoMessage;
  261. procedure AddImport(const Path: AnsiString);
  262. function GetImportCount: Integer;
  263. function GetImport(const Idx: Integer): AnsiString;
  264. procedure AddImportedPackage(const Package: TpbProtoPackage);
  265. function GetImportedPackageCount: Integer;
  266. function GetImportedPackage(const Idx: Integer): TpbProtoPackage;
  267. function GetImportedPackageByName(const AName: AnsiString): TpbProtoPackage;
  268. procedure AddOption(const Option: TpbProtoOption);
  269. function GetOptionCount: Integer;
  270. function GetOption(const Idx: Integer): TpbProtoOption;
  271. procedure AddEnum(const E: TpbProtoEnum);
  272. property EnumCount: Integer read GetEnumCount;
  273. property Enum[const Idx: Integer]: TpbProtoEnum read GetEnum;
  274. function ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; override;
  275. function ResolveType(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode; override;
  276. function GetAsProtoString: AnsiString; override;
  277. end;
  278. TpbProtoNodeFactory = class
  279. public
  280. function CreatePackage: TpbProtoPackage; virtual;
  281. function CreateMessage(const AParentNode: TpbProtoNode): TpbProtoMessage; virtual;
  282. function CreateField(const AParentMessage: TpbProtoMessage): TpbProtoField; virtual;
  283. function CreateFieldType(const AParentField: TpbProtoField): TpbProtoFieldType; virtual;
  284. function CreateLiteral(const AParentNode: TpbProtoNode): TpbProtoLiteral; virtual;
  285. function CreateEnum(const AParentNode: TpbProtoNode): TpbProtoEnum; virtual;
  286. function CreateEnumValue(const AParentEnum: TpbProtoEnum): TpbProtoEnumValue; virtual;
  287. end;
  288. { Default ProtoNode factory }
  289. function GetDefaultProtoNodeFactory: TpbProtoNodeFactory;
  290. implementation
  291. uses
  292. { Fundamentals }
  293. cUtils,
  294. cStrings;
  295. const
  296. pbCRLF = AnsiString(#13#10);
  297. ProtoFieldCardinalityStr : array[TpbProtoFieldCardinality] of AnsiString = (
  298. '',
  299. 'required',
  300. 'optional',
  301. 'repeated'
  302. );
  303. ProtoFieldTypeStr : array[TpbProtoFieldBaseType] of AnsiString = (
  304. '',
  305. 'double',
  306. 'float',
  307. 'int32',
  308. 'int64',
  309. 'uint32',
  310. 'uint64',
  311. 'sint32',
  312. 'sint64',
  313. 'fixed32',
  314. 'fixed64',
  315. 'sfixed32',
  316. 'sfixed64',
  317. 'bool',
  318. 'string',
  319. 'bytes',
  320. ''
  321. );
  322. SErr_IdentifierNotDefined = 'Identifier not defined (%s)';
  323. SErr_IdentifierNotAValue = 'Identifier not a value (%s)';
  324. { Helper functions }
  325. procedure pbSplitIdentifier(const AIdentifier: AnsiString;
  326. var ALeftName, ARightIdentifier: AnsiString);
  327. begin
  328. StrSplitAtCharA(AIdentifier, '.', ALeftName, ARightIdentifier, True);
  329. end;
  330. { TpbProtoNode }
  331. function TpbProtoNode.ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  332. begin
  333. raise EpbProtoNode.CreateFmt('%s.ResolveValue not implemented', [ClassName]);
  334. end;
  335. function TpbProtoNode.ResolveType(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  336. begin
  337. raise EpbProtoNode.CreateFmt('%s.ResolveType not implemented', [ClassName]);
  338. end;
  339. function TpbProtoNode.ExpectResolvedValue(const AIdentifier: AnsiString): TpbProtoNode;
  340. begin
  341. Result := ResolveValue(AIdentifier, False);
  342. if not Assigned(Result) then
  343. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotDefined, [AIdentifier]);
  344. end;
  345. function TpbProtoNode.ExpectResolvedType(const AIdentifier: AnsiString): TpbProtoNode;
  346. begin
  347. Result := ResolveType(AIdentifier, False);
  348. if not Assigned(Result) then
  349. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotDefined, [AIdentifier]);
  350. end;
  351. function TpbProtoNode.GetAsProtoString: AnsiString;
  352. begin
  353. raise EpbProtoNode.CreateFmt('%s.GetAsProtoString not implemented', [ClassName]);
  354. end;
  355. { TpbProtoEnumValue }
  356. constructor TpbProtoEnumValue.Create(const AParentEnum: TpbProtoEnum);
  357. begin
  358. Assert(Assigned(AParentEnum));
  359. inherited Create;
  360. FParentEnum := AParentEnum;
  361. end;
  362. function TpbProtoEnumValue.GetAsProtoString: AnsiString;
  363. begin
  364. Result := FName + ' = ' + IntToStringA(FValue) + ';';
  365. end;
  366. { TpbProtoEnum }
  367. constructor TpbProtoEnum.Create(const AParentNode: TpbProtoNode);
  368. begin
  369. Assert(Assigned(AParentNode));
  370. inherited Create;
  371. end;
  372. procedure TpbProtoEnum.Add(const V: TpbProtoEnumValue);
  373. var L : Integer;
  374. begin
  375. L := Length(FValues);
  376. SetLength(FValues, L + 1);
  377. FValues[L] := V;
  378. end;
  379. function TpbProtoEnum.GetValueCount: Integer;
  380. begin
  381. Result := Length(FValues);
  382. end;
  383. function TpbProtoEnum.GetValue(const Idx: Integer): TpbProtoEnumValue;
  384. begin
  385. Assert((Idx >= 0) and (Idx < Length(FValues)));
  386. Result := FValues[Idx];
  387. end;
  388. function TpbProtoEnum.GetValueByName(const AName: AnsiString): TpbProtoEnumValue;
  389. var
  390. I : Integer;
  391. V : TpbProtoEnumValue;
  392. begin
  393. for I := 0 to Length(FValues) - 1 do
  394. begin
  395. V := FValues[I];
  396. if V.FName = AName then
  397. begin
  398. Result := V;
  399. exit;
  400. end;
  401. end;
  402. Result := nil;
  403. end;
  404. function TpbProtoEnum.ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  405. begin
  406. Result := GetValueByName(AIdentifier);
  407. end;
  408. function TpbProtoEnum.GetAsProtoString: AnsiString;
  409. var I, L : Integer;
  410. begin
  411. Result := 'enum ' + FName + ' {' + pbCRLF;
  412. L := Length(FValues);
  413. for I := 0 to L - 1 do
  414. Result := Result + FValues[I].GetAsProtoString + pbCRLF;
  415. Result := Result + '}';
  416. end;
  417. { TpbProtoLiteral }
  418. constructor TpbProtoLiteral.Create(const AParentNode: TpbProtoNode);
  419. begin
  420. Assert(Assigned(AParentNode));
  421. inherited Create;
  422. FParentNode := AParentNode;
  423. end;
  424. function TpbProtoLiteral.ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  425. begin
  426. if AChildrenOnly then
  427. Result := nil
  428. else
  429. Result := FParentNode.ResolveValue(AIdentifier, False);
  430. end;
  431. function TpbProtoLiteral.GetAsProtoString: AnsiString;
  432. begin
  433. case FLiteralType of
  434. pltNone : Result := '';
  435. pltInteger : Result := IntToStringA(FLiteralInt);
  436. pltFloat : Result := FloatToStringA(FLiteralFloat);
  437. pltString : Result := StrQuoteA(FLiteralStr, '"');
  438. pltBoolean : Result := iifA(FLiteralBool, 'true', 'false');
  439. pltIdentifier : Result := FLiteralIden;
  440. else
  441. raise EpbProtoNode.Create('Invalid literal type');
  442. end;
  443. end;
  444. function TpbProtoLiteral.LiteralIdenValue: TpbProtoNode;
  445. begin
  446. if FLiteralType <> pltIdentifier then
  447. raise EpbProtoNode.Create('Not a identifier type');
  448. Result := ResolveValue(FLiteralIden, False);
  449. end;
  450. { TpbProtoFieldType }
  451. constructor TpbProtoFieldType.Create(const AParentField: TpbProtoField);
  452. begin
  453. Assert(Assigned(AParentField));
  454. inherited Create;
  455. FParentField := AParentField;
  456. end;
  457. function TpbProtoFieldType.ResolveType(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  458. begin
  459. if AChildrenOnly then
  460. Result := nil
  461. else
  462. Result := FParentField.ResolveType(AIdentifier, False);
  463. end;
  464. function TpbProtoFieldType.GetAsProtoString: AnsiString;
  465. begin
  466. if FBaseType = pftIdentifier then
  467. Result := FIdenStr
  468. else
  469. Result := ProtoFieldTypeStr[FBaseType];
  470. end;
  471. function TpbProtoFieldType.IsSimpleType: Boolean;
  472. begin
  473. Result := not (FBaseType in [pftNone, pftIdentifier]);
  474. end;
  475. function TpbProtoFieldType.IsIdenType: Boolean;
  476. begin
  477. Result := FBaseType = pftIdentifier;
  478. end;
  479. function TpbProtoFieldType.IdenType: TpbProtoNode;
  480. begin
  481. if not IsIdenType then
  482. raise EpbProtoNode.Create('Not an identifier type');
  483. Result := ExpectResolvedType(FIdenStr);
  484. end;
  485. { TpbProtoField }
  486. constructor TpbProtoField.Create(const AParentMessage: TpbProtoMessage; const AFactory: TpbProtoNodeFactory);
  487. begin
  488. Assert(Assigned(AParentMessage));
  489. Assert(Assigned(AFactory));
  490. inherited Create;
  491. FParentMessage := AParentMessage;
  492. FDefaultValue := AFactory.CreateLiteral(self);
  493. FFieldType := AFactory.CreateFieldType(self);
  494. end;
  495. destructor TpbProtoField.Destroy;
  496. var I : Integer;
  497. begin
  498. for I := Length(FOptions) - 1 downto 0 do
  499. FreeAndNil(FOptions);
  500. FreeAndNil(FFieldType);
  501. FreeAndNil(FDefaultValue);
  502. inherited Destroy;
  503. end;
  504. procedure TpbProtoField.SetFieldType(const Value: TpbProtoFieldType);
  505. begin
  506. FreeAndNil(FFieldType);
  507. FFieldType := Value;
  508. end;
  509. procedure TpbProtoField.SetDefaultValue(const Value: TpbProtoLiteral);
  510. begin
  511. FreeAndNil(FDefaultValue);
  512. FDefaultValue := Value;
  513. end;
  514. procedure TpbProtoField.AddOption(const Option: TpbProtoOption);
  515. var
  516. L : Integer;
  517. begin
  518. L := Length(FOptions);
  519. SetLength(FOptions, L + 1);
  520. FOptions[L] := Option;
  521. end;
  522. function TpbProtoField.GetOptionCount: Integer;
  523. begin
  524. Result := Length(FOptions);
  525. end;
  526. function TpbProtoField.GetOption(const Idx: Integer): TpbProtoOption;
  527. begin
  528. Assert((Idx >= 0) and (Idx < Length(FOptions)));
  529. Result := FOptions[Idx];
  530. end;
  531. function TpbProtoField.ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  532. begin
  533. if AChildrenOnly then
  534. Result := nil
  535. else
  536. Result := FParentMessage.ResolveValue(AIdentifier, False);
  537. end;
  538. function TpbProtoField.ResolveType(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  539. begin
  540. if AChildrenOnly then
  541. Result := nil
  542. else
  543. Result := FParentMessage.ResolveType(AIdentifier, False);
  544. end;
  545. function TpbProtoField.GetAsProtoString: AnsiString;
  546. begin
  547. Result :=
  548. ProtoFieldCardinalityStr[FCardinality] + ' ' +
  549. FFieldType.GetAsProtoString + ' ' +
  550. FName + ' = ' +
  551. IntToStringA(FTagID) + ';';
  552. end;
  553. { TpbProtoMessage }
  554. constructor TpbProtoMessage.Create(const AParentNode: TpbProtoNode);
  555. begin
  556. Assert(Assigned(AParentNode));
  557. inherited Create;
  558. FParentNode := AParentNode;
  559. end;
  560. destructor TpbProtoMessage.Destroy;
  561. var I : Integer;
  562. begin
  563. for I := Length(FEnums) - 1 downto 0 do
  564. FreeAndNil(FEnums[I]);
  565. for I := Length(FFields) - 1 downto 0 do
  566. FreeAndNil(FFields[I]);
  567. for I := Length(FMessages) - 1 downto 0 do
  568. FreeAndNil(FMessages[I]);
  569. inherited Destroy;
  570. end;
  571. procedure TpbProtoMessage.AddField(const F: TpbProtoField);
  572. var L : Integer;
  573. begin
  574. L := Length(FFields);
  575. SetLength(FFields, L + 1);
  576. FFields[L] := F;
  577. end;
  578. function TpbProtoMessage.GetFieldCount: Integer;
  579. begin
  580. Result := Length(FFields);
  581. end;
  582. function TpbProtoMessage.GetField(const Idx: Integer): TpbProtoField;
  583. begin
  584. Assert((Idx >= 0) and (Idx < Length(FFields)));
  585. Result := FFields[Idx];
  586. end;
  587. function TpbProtoMessage.GetFieldByTagID(const ATagID: Integer): TpbProtoField;
  588. var
  589. I : Integer;
  590. F : TpbProtoField;
  591. begin
  592. for I := 0 to Length(FFields) - 1 do
  593. begin
  594. F := GetField(I);
  595. if F.FTagID = ATagID then
  596. begin
  597. Result := F;
  598. exit;
  599. end;
  600. end;
  601. Result := nil;
  602. end;
  603. procedure TpbProtoMessage.AddEnum(const E: TpbProtoEnum);
  604. var L : Integer;
  605. begin
  606. L := Length(FEnums);
  607. SetLength(FEnums, L + 1);
  608. FEnums[L] := E;
  609. end;
  610. function TpbProtoMessage.GetEnumCount: Integer;
  611. begin
  612. Result := Length(FEnums);
  613. end;
  614. function TpbProtoMessage.GetEnum(const Idx: Integer): TpbProtoEnum;
  615. begin
  616. Assert((Idx >= 0) and (Idx < Length(FEnums)));
  617. Result := FEnums[Idx];
  618. end;
  619. function TpbProtoMessage.GetEnumByName(const AName: AnsiString): TpbProtoEnum;
  620. var
  621. I : Integer;
  622. E : TpbProtoEnum;
  623. begin
  624. for I := 0 to GetEnumCount - 1 do
  625. begin
  626. E := GetEnum(I);
  627. if E.FName = AName then
  628. begin
  629. Result := E;
  630. exit;
  631. end;
  632. end;
  633. Result := nil;
  634. end;
  635. procedure TpbProtoMessage.AddMessage(const M: TpbProtoMessage);
  636. var L : Integer;
  637. begin
  638. L := Length(FMessages);
  639. SetLength(FMessages, L + 1);
  640. FMessages[L] := M;
  641. end;
  642. function TpbProtoMessage.GetMessageCount: Integer;
  643. begin
  644. Result := Length(FMessages);
  645. end;
  646. function TpbProtoMessage.GetMessage(const Idx: Integer): TpbProtoMessage;
  647. begin
  648. Assert((Idx >= 0) and (Idx < Length(FMessages)));
  649. Result := FMessages[Idx];
  650. end;
  651. function TpbProtoMessage.GetMessageByName(const AName: AnsiString): TpbProtoMessage;
  652. var
  653. I : Integer;
  654. M : TpbProtoMessage;
  655. begin
  656. for I := 0 to GetMessageCount - 1 do
  657. begin
  658. M := GetMessage(I);
  659. if M.FName = AName then
  660. begin
  661. Result := M;
  662. exit;
  663. end;
  664. end;
  665. Result := nil;
  666. end;
  667. function TpbProtoMessage.ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  668. var
  669. I : Integer;
  670. E : TpbProtoEnum;
  671. M : TpbProtoMessage;
  672. N, S : AnsiString;
  673. begin
  674. for I := 0 to GetEnumCount - 1 do
  675. begin
  676. E := GetEnum(I);
  677. Result := E.ResolveValue(AIdentifier, True);
  678. if Assigned(Result) then
  679. exit;
  680. end;
  681. pbSplitIdentifier(AIdentifier, N, S);
  682. M := GetMessageByName(N);
  683. if Assigned(M) then
  684. begin
  685. if S = '' then
  686. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotAValue, [AIdentifier]);
  687. Result := M.ResolveValue(S, True);
  688. if Assigned(Result) then
  689. exit
  690. else
  691. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotDefined, [AIdentifier]);
  692. end;
  693. if AChildrenOnly then
  694. Result := nil
  695. else
  696. Result := FParentNode.ResolveValue(AIdentifier, False);
  697. end;
  698. function TpbProtoMessage.ResolveType(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  699. var
  700. M : TpbProtoMessage;
  701. E : TpbProtoEnum;
  702. N, S : AnsiString;
  703. begin
  704. pbSplitIdentifier(AIdentifier, N, S);
  705. M := GetMessageByName(N);
  706. if Assigned(M) then
  707. begin
  708. if S = '' then
  709. Result := M
  710. else
  711. begin
  712. Result := M.ResolveType(S, True);
  713. if not Assigned(Result) then
  714. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotDefined, [AIdentifier]);
  715. end;
  716. exit;
  717. end;
  718. E := GetEnumByName(AIdentifier);
  719. if Assigned(E) then
  720. begin
  721. Result := E;
  722. exit;
  723. end;
  724. if AChildrenOnly then
  725. Result := nil
  726. else
  727. Result := FParentNode.ResolveType(AIdentifier, False);
  728. end;
  729. function TpbProtoMessage.GetAsProtoString: AnsiString;
  730. var
  731. S : AnsiString;
  732. I : Integer;
  733. begin
  734. S := 'message ' + FName + ' {' + pbCRLF;
  735. for I := 0 to GetMessageCount - 1 do
  736. S := S + GetMessage(I).GetAsProtoString;
  737. for I := 0 to GetEnumCount - 1 do
  738. S := S + GetEnum(I).GetAsProtoString;
  739. for I := 0 to GetFieldCount - 1 do
  740. S := S + GetField(I).GetAsProtoString;
  741. S := S + '}' + pbCRLF;
  742. Result := S;
  743. end;
  744. { TpbProtoOption }
  745. constructor TpbProtoOption.Create(const AFactory: TpbProtoNodeFactory);
  746. begin
  747. Assert(Assigned(AFactory));
  748. inherited Create;
  749. FValue := AFactory.CreateLiteral(self);
  750. end;
  751. destructor TpbProtoOption.Destroy;
  752. begin
  753. FreeAndNil(FValue);
  754. inherited Destroy;
  755. end;
  756. procedure TpbProtoOption.SetValue(const Value: TpbProtoLiteral);
  757. begin
  758. FreeAndNil(FValue);
  759. FValue := Value;
  760. end;
  761. { TpbProtoPackage }
  762. constructor TpbProtoPackage.Create;
  763. begin
  764. inherited Create;
  765. end;
  766. destructor TpbProtoPackage.Destroy;
  767. var I : Integer;
  768. begin
  769. for I := Length(FImportedPackages) - 1 downto 0 do
  770. FreeAndNil(FImportedPackages[I]);
  771. for I := Length(FOptions) - 1 downto 0 do
  772. FreeAndNil(FOptions[I]);
  773. for I := Length(FMessages) - 1 downto 0 do
  774. FreeAndNil(FMessages[I]);
  775. inherited Destroy;
  776. end;
  777. procedure TpbProtoPackage.AddMessage(const M: TpbProtoMessage);
  778. var
  779. L : Integer;
  780. begin
  781. L := Length(FMessages);
  782. SetLength(FMessages, L + 1);
  783. FMessages[L] := M;
  784. end;
  785. function TpbProtoPackage.GetMessageCount: Integer;
  786. begin
  787. Result := Length(FMessages);
  788. end;
  789. function TpbProtoPackage.GetMessage(const Idx: Integer): TpbProtoMessage;
  790. begin
  791. Assert((Idx >= 0) and (Idx < Length(FMessages)));
  792. Result := FMessages[Idx];
  793. end;
  794. function TpbProtoPackage.GetMessageByName(const AName: AnsiString): TpbProtoMessage;
  795. var
  796. I : Integer;
  797. M : TpbProtoMessage;
  798. begin
  799. for I := 0 to GetMessageCount - 1 do
  800. begin
  801. M := GetMessage(I);
  802. if M.FName = AName then
  803. begin
  804. Result := M;
  805. exit;
  806. end;
  807. end;
  808. Result := nil;
  809. end;
  810. procedure TpbProtoPackage.AddImport(const Path: AnsiString);
  811. var
  812. L : Integer;
  813. begin
  814. L := Length(FImports);
  815. SetLength(FImports, L + 1);
  816. FImports[L] := Path;
  817. end;
  818. function TpbProtoPackage.GetImportCount: Integer;
  819. begin
  820. Result := Length(FImports);
  821. end;
  822. function TpbProtoPackage.GetImport(const Idx: Integer): AnsiString;
  823. begin
  824. Assert((Idx >= 0) and (Idx < Length(FImports)));
  825. Result := FImports[Idx];
  826. end;
  827. procedure TpbProtoPackage.AddImportedPackage(const Package: TpbProtoPackage);
  828. var
  829. L : Integer;
  830. begin
  831. L := Length(FImportedPackages);
  832. SetLength(FImportedPackages, L + 1);
  833. FImportedPackages[L] := Package;
  834. end;
  835. function TpbProtoPackage.GetImportedPackageCount: Integer;
  836. begin
  837. Result := Length(FImportedPackages);
  838. end;
  839. function TpbProtoPackage.GetImportedPackage(const Idx: Integer): TpbProtoPackage;
  840. begin
  841. Assert((Idx >= 0) and (Idx < Length(FImportedPackages)));
  842. Result := FImportedPackages[Idx];
  843. end;
  844. function TpbProtoPackage.GetImportedPackageByName(const AName: AnsiString): TpbProtoPackage;
  845. var
  846. I : Integer;
  847. P : TpbProtoPackage;
  848. begin
  849. for I := 0 to GetImportedPackageCount - 1 do
  850. begin
  851. P := GetImportedPackage(I);
  852. if P.FName = AName then
  853. begin
  854. Result := P;
  855. exit;
  856. end;
  857. end;
  858. Result := nil;
  859. end;
  860. procedure TpbProtoPackage.AddOption(const Option: TpbProtoOption);
  861. var
  862. L : Integer;
  863. begin
  864. L := Length(FOptions);
  865. SetLength(FOptions, L + 1);
  866. FOptions[L] := Option;
  867. end;
  868. function TpbProtoPackage.GetOptionCount: Integer;
  869. begin
  870. Result := Length(FOptions);
  871. end;
  872. function TpbProtoPackage.GetOption(const Idx: Integer): TpbProtoOption;
  873. begin
  874. Assert((Idx >= 0) and (Idx < Length(FOptions)));
  875. Result := FOptions[Idx];
  876. end;
  877. procedure TpbProtoPackage.AddEnum(const E: TpbProtoEnum);
  878. var L : Integer;
  879. begin
  880. L := Length(FEnums);
  881. SetLength(FEnums, L + 1);
  882. FEnums[L] := E;
  883. end;
  884. function TpbProtoPackage.GetEnumCount: Integer;
  885. begin
  886. Result := Length(FEnums);
  887. end;
  888. function TpbProtoPackage.GetEnum(const Idx: Integer): TpbProtoEnum;
  889. begin
  890. Assert((Idx >= 0) and (Idx < Length(FEnums)));
  891. Result := FEnums[Idx];
  892. end;
  893. function TpbProtoPackage.GetEnumByName(const AName: AnsiString): TpbProtoEnum;
  894. var
  895. I : Integer;
  896. E : TpbProtoEnum;
  897. begin
  898. for I := 0 to GetEnumCount - 1 do
  899. begin
  900. E := GetEnum(I);
  901. if E.FName = AName then
  902. begin
  903. Result := E;
  904. exit;
  905. end;
  906. end;
  907. Result := nil;
  908. end;
  909. function TpbProtoPackage.ResolveValue(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  910. var
  911. I : Integer;
  912. E : TpbProtoEnum;
  913. M : TpbProtoMessage;
  914. P : TpbProtoPackage;
  915. N, S : AnsiString;
  916. begin
  917. for I := 0 to GetEnumCount - 1 do
  918. begin
  919. E := GetEnum(I);
  920. Result := E.ResolveValue(AIdentifier, True);
  921. if Assigned(Result) then
  922. exit;
  923. end;
  924. pbSplitIdentifier(AIdentifier, N, S);
  925. M := GetMessageByName(N);
  926. if Assigned(M) then
  927. begin
  928. if S = '' then
  929. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotAValue, [AIdentifier]);
  930. Result := M.ResolveValue(S, True);
  931. if Assigned(Result) then
  932. exit
  933. else
  934. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotDefined, [AIdentifier]);
  935. end;
  936. for I := 0 to GetMessageCount - 1 do
  937. begin
  938. M := GetMessage(I);
  939. Result := M.ResolveValue(AIdentifier, True);
  940. if Assigned(Result) then
  941. exit;
  942. end;
  943. P := GetImportedPackageByName(N);
  944. if Assigned(P) then
  945. begin
  946. if S = '' then
  947. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotAValue, [AIdentifier]);
  948. Result := P.ResolveValue(S, True);
  949. if Assigned(Result) then
  950. exit
  951. else
  952. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotDefined, [AIdentifier]);
  953. end;
  954. for I := 0 to GetImportedPackageCount - 1 do
  955. begin
  956. P := GetImportedPackage(I);
  957. Result := P.ResolveValue(AIdentifier, True);
  958. if Assigned(Result) then
  959. exit;
  960. end;
  961. Result := nil;
  962. end;
  963. function TpbProtoPackage.ResolveType(const AIdentifier: AnsiString; const AChildrenOnly: Boolean): TpbProtoNode;
  964. var
  965. M : TpbProtoMessage;
  966. E : TpbProtoEnum;
  967. P : TpbProtoPackage;
  968. N, S : AnsiString;
  969. I : Integer;
  970. begin
  971. pbSplitIdentifier(AIdentifier, N, S);
  972. M := GetMessageByName(N);
  973. if Assigned(M) then
  974. begin
  975. if S = '' then
  976. Result := M
  977. else
  978. begin
  979. Result := M.ResolveType(S, True);
  980. if not Assigned(Result) then
  981. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotDefined, [AIdentifier]);
  982. end;
  983. exit;
  984. end;
  985. E := GetEnumByName(AIdentifier);
  986. if Assigned(E) then
  987. begin
  988. Result := E;
  989. exit;
  990. end;
  991. P := GetImportedPackageByName(N);
  992. if Assigned(P) then
  993. begin
  994. if S = '' then
  995. Result := P
  996. else
  997. begin
  998. Result := P.ResolveType(S, True);
  999. if not Assigned(Result) then
  1000. raise EpbProtoNode.CreateFmt(SErr_IdentifierNotDefined, [AIdentifier]);
  1001. end;
  1002. exit;
  1003. end;
  1004. for I := 0 to GetImportedPackageCount - 1 do
  1005. begin
  1006. Result := GetImportedPackage(I).ResolveType(AIdentifier, True);
  1007. if Assigned(Result) then
  1008. exit;
  1009. end;
  1010. Result := nil;
  1011. end;
  1012. function TpbProtoPackage.GetAsProtoString: AnsiString;
  1013. var
  1014. I : Integer;
  1015. S : AnsiString;
  1016. begin
  1017. S := '';
  1018. if FName <> '' then
  1019. S := S + 'package ' + FName + ';' + pbCRLF + pbCRLF;
  1020. for I := 0 to GetMessageCount - 1 do
  1021. S := S + GetMessage(I).GetAsProtoString;
  1022. Result := S;
  1023. end;
  1024. { TpbProtoNodeFactory }
  1025. function TpbProtoNodeFactory.CreatePackage: TpbProtoPackage;
  1026. begin
  1027. Result := TpbProtoPackage.Create;
  1028. end;
  1029. function TpbProtoNodeFactory.CreateMessage(const AParentNode: TpbProtoNode): TpbProtoMessage;
  1030. begin
  1031. Result := TpbProtoMessage.Create(AParentNode);
  1032. end;
  1033. function TpbProtoNodeFactory.CreateField(const AParentMessage: TpbProtoMessage): TpbProtoField;
  1034. begin
  1035. Result := TpbProtoField.Create(AParentMessage, self);
  1036. end;
  1037. function TpbProtoNodeFactory.CreateFieldType(const AParentField: TpbProtoField): TpbProtoFieldType;
  1038. begin
  1039. Result := TpbProtoFieldType.Create(AParentField);
  1040. end;
  1041. function TpbProtoNodeFactory.CreateLiteral(const AParentNode: TpbProtoNode): TpbProtoLiteral;
  1042. begin
  1043. Result := TpbProtoLiteral.Create(AParentNode);
  1044. end;
  1045. function TpbProtoNodeFactory.CreateEnum(const AParentNode: TpbProtoNode): TpbProtoEnum;
  1046. begin
  1047. Result := TpbProtoEnum.Create(AParentNode);
  1048. end;
  1049. function TpbProtoNodeFactory.CreateEnumValue(const AParentEnum: TpbProtoEnum): TpbProtoEnumValue;
  1050. begin
  1051. Result := TpbProtoEnumValue.Create(AParentEnum);
  1052. end;
  1053. { Default ProtoNode factory }
  1054. var
  1055. DefaultProtoNodeFactory: TpbProtoNodeFactory = nil;
  1056. function GetDefaultProtoNodeFactory: TpbProtoNodeFactory;
  1057. begin
  1058. if not Assigned(DefaultProtoNodeFactory) then
  1059. DefaultProtoNodeFactory := TpbProtoNodeFactory.Create;
  1060. Result := DefaultProtoNodeFactory;
  1061. end;
  1062. initialization
  1063. finalization
  1064. FreeAndNil(DefaultProtoNodeFactory);
  1065. end.