From f9209bff087f82bc1973e7772be35f914a822701 Mon Sep 17 00:00:00 2001 From: JinnBlue Date: Wed, 21 Dec 2016 18:17:31 +0800 Subject: [PATCH 1/4] 1.Add example2 for BenchmarkTest; 2.Fix AddFromBuf bug for Generate .pas; --- .gitignore | 1 + Generator/Test/ProtoBufGeneratorTests.dpr | 1 + Generator/Test/TestGeneratedProtoBufPas.pas | 2 +- Generator/uProtoBufGenerator.pas | 6 +- Generator/ufmMain.dfm | 9 +- Generator/ufmMain.pas | 148 ++++- example2/PTestAssign.dpr | 15 + example2/PTestAssign.dproj | 596 ++++++++++++++++++++ example2/PTestAssign.res | Bin 0 -> 59416 bytes example2/TestAssign.dfm | 26 + example2/TestAssign.pas | 130 +++++ example2/test1.proto | 43 ++ example2/test2.proto | 10 + 13 files changed, 970 insertions(+), 17 deletions(-) create mode 100644 example2/PTestAssign.dpr create mode 100644 example2/PTestAssign.dproj create mode 100644 example2/PTestAssign.res create mode 100644 example2/TestAssign.dfm create mode 100644 example2/TestAssign.pas create mode 100644 example2/test1.proto create mode 100644 example2/test2.proto diff --git a/.gitignore b/.gitignore index 19864c6..19dc229 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,4 @@ __recovery/ # Castalia statistics file (since XE7 Castalia is distributed with Delphi) *.stat +/Generator/Test/Win32 diff --git a/Generator/Test/ProtoBufGeneratorTests.dpr b/Generator/Test/ProtoBufGeneratorTests.dpr index 800e39f..ad6868e 100644 --- a/Generator/Test/ProtoBufGeneratorTests.dpr +++ b/Generator/Test/ProtoBufGeneratorTests.dpr @@ -17,6 +17,7 @@ program ProtoBufGeneratorTests; uses DUnitTestRunner, TestuProtoBufParserClasses in 'TestuProtoBufParserClasses.pas', + TestuProtoBufGenerator in 'TestuProtoBufGenerator.pas', uProtoBufParserClasses in '..\uProtoBufParserClasses.pas', uProtoBufParserAbstractClasses in '..\uProtoBufParserAbstractClasses.pas', uProtoBufGenerator in '..\uProtoBufGenerator.pas', diff --git a/Generator/Test/TestGeneratedProtoBufPas.pas b/Generator/Test/TestGeneratedProtoBufPas.pas index fdc158f..07fefd0 100644 --- a/Generator/Test/TestGeneratedProtoBufPas.pas +++ b/Generator/Test/TestGeneratedProtoBufPas.pas @@ -85,7 +85,7 @@ procedure TestTTestMsg1.TestSaveLoadFromBuf; FTestMsg1.DefField9 := 5.5; FTestMsg1.FieldArr1List.Add(-5); FTestMsg1.FieldArr2List.Add(234); - FTestMsg1.FieldArr3List.Add('asdf'); + FTestMsg1.FieldArr3List.Add('asdf?); tmp := TTestMsg1.Create; try diff --git a/Generator/uProtoBufGenerator.pas b/Generator/uProtoBufGenerator.pas index ada7b0f..c67115f 100644 --- a/Generator/uProtoBufGenerator.pas +++ b/Generator/uProtoBufGenerator.pas @@ -344,7 +344,7 @@ procedure TProtoBufGenerator.GenerateImplementationSection(Proto: TProtoFile; SL end; SL.Add(' if Result then'); SL.Add(' exit;'); - SL.Add(' case fieldNumber of'); + SL.Add(' case FieldNumber of'); for i := 0 to ProtoMsg.Count - 1 do begin Prop := ProtoMsg[i]; @@ -412,7 +412,7 @@ procedure TProtoBufGenerator.GenerateImplementationSection(Proto: TProtoFile; SL SL.Add(Format(' F%s.Add(T%s(ProtoBuf.readEnum));', [DelphiProp.PropertyName, Prop.PropType])); end else - SL.Add(Format(' F%s.AddFromBuf(ProtoBuf, fieldNumber);', [DelphiProp.PropertyName])); + SL.Add(Format(' F%s.AddFromBuf(ProtoBuf, makeTag(FieldNumber, WireType));', [DelphiProp.PropertyName])); end; SL.Add(' Result := True;'); SL.Add(' end;'); @@ -594,7 +594,7 @@ SL.Add(Format(' T%s = class(T%s)', [ProtoMsg.Name, s])); SL.Add(' destructor Destroy; override;'); SL.Add(''); end; - SL.Add(''); + for i := 0 to ProtoMsg.Count - 1 do begin Prop := ProtoMsg[i]; diff --git a/Generator/ufmMain.dfm b/Generator/ufmMain.dfm index 8ba9738..742cb58 100644 --- a/Generator/ufmMain.dfm +++ b/Generator/ufmMain.dfm @@ -11,19 +11,21 @@ object fmMain: TfmMain Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False + OnCreate = FormCreate + OnDestroy = FormDestroy DesignSize = ( 458 154) PixelsPerInch = 96 TextHeight = 13 - object edProtoFileName: TEdit + object edtProtoFiles: TEdit Left = 8 Top = 16 Width = 409 Height = 21 Anchors = [akLeft, akTop, akRight] TabOrder = 0 - TextHint = 'Choose proto file' + TextHint = 'Choose .proto file' end object btnOpenProtoFile: TButton Left = 423 @@ -45,13 +47,14 @@ object fmMain: TfmMain TabOrder = 2 OnClick = btnGenerateClick end - object edOutputFolder: TEdit + object edtOutputFolder: TEdit Left = 8 Top = 53 Width = 409 Height = 21 Anchors = [akLeft, akTop, akRight] TabOrder = 3 + Text = '.\PbOut' TextHint = 'Choose output folder' end object btnChooseOutputFolder: TButton diff --git a/Generator/ufmMain.pas b/Generator/ufmMain.pas index 3a84edf..a2467be 100644 --- a/Generator/ufmMain.pas +++ b/Generator/ufmMain.pas @@ -6,31 +6,48 @@ interface Winapi.Windows, Winapi.Messages, System.SysUtils, - System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, - Vcl.StdCtrls, - Vcl.ExtCtrls; + Vcl.StdCtrls; type TfmMain = class(TForm) - edProtoFileName: TEdit; + edtProtoFiles: TEdit; btnOpenProtoFile: TButton; odProtoFile: TFileOpenDialog; btnGenerate: TButton; - edOutputFolder: TEdit; + edtOutputFolder: TEdit; btnChooseOutputFolder: TButton; procedure btnOpenProtoFileClick(Sender: TObject); procedure btnChooseOutputFolderClick(Sender: TObject); procedure btnGenerateClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); private - { Private declarations } + FFiles: TArray; + FFileCount: Integer; + + procedure ClearFiles; + procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES; + end; + + { Files Drop Class } + TFileCatcher = class(TObject) + private + FDropHandle: THANDLE; + function GetFile(Idx: Integer): string; + function GetFileCount: Integer; + function GetPoint: TPoint; procedure Generate(SourceFiles: TStrings; const OutputDir: string); public - { Public declarations } + constructor Create(DropHandle: THANDLE); + destructor Destroy; override; + property FileCount: Integer read GetFileCount; + property Files[Idx: Integer]: string read GetFile; + property DropPoint: TPoint read GetPoint; end; var @@ -40,38 +57,63 @@ implementation uses Vcl.FileCtrl, + Winapi.ShellAPI, uProtoBufGenerator; +const + PROTO = '.proto'; + {$R *.dfm} procedure TfmMain.btnChooseOutputFolderClick(Sender: TObject); var Dir: string; begin - Dir := edOutputFolder.Text; - if SelectDirectory('Select output directory', '', Dir, [sdNewFolder, sdShowShares, sdNewUI, sdValidateDir], nil) then - edOutputFolder.Text := Dir; + Dir := edtOutputFolder.Text; + if SelectDirectory('choose output dir', '', Dir, [sdNewFolder, sdShowShares, sdNewUI, sdValidateDir], nil) + then + edtOutputFolder.Text := Dir; end; procedure TfmMain.btnGenerateClick(Sender: TObject); var FileNames: TStrings; + I: Integer; begin FileNames := TStringList.Create; + if edtOutputFolder.Text <> '' then + ForceDirectories(edtOutputFolder.Text); + + Gen := TProtoBufGenerator.Create; try FileNames.Delimiter:=odProtoFile.Files.Delimiter; FileNames.DelimitedText:=edProtoFileName.Text; Generate(FileNames, edOutputFolder.Text); ShowMessage('Complete! Take a look into output directory'); + for I := 0 to Pred(FFileCount) do + begin + Gen.Generate(FFiles[I], edtOutputFolder.Text, TEncoding.UTF8); + end; finally FileNames.Free; end; end; procedure TfmMain.btnOpenProtoFileClick(Sender: TObject); +var + I: Integer; begin if odProtoFile.Execute then edProtoFileName.Text := odProtoFile.Files.DelimitedText; + begin + FFileCount := odProtoFile.Files.Count; + SetLength(FFiles, FFileCount); + for I := 0 to Pred(FFileCount) do + begin + FFiles[I] := odProtoFile.Files[I]; + edtProtoFiles.Text := edtProtoFiles.Text + ExtractFileName(FFiles[I]) + ';'; + end; + end; end; procedure TfmMain.Generate(SourceFiles: TStrings; const OutputDir: string); @@ -88,5 +130,91 @@ procedure TfmMain.Generate(SourceFiles: TStrings; const OutputDir: string); Gen.Free; end; end; +procedure TfmMain.ClearFiles; +begin + SetLength(FFiles, 0); + FFileCount := 0; + edtProtoFiles.Text := ''; + edtProtoFiles.Font.Color := clWindowText; +end; + +{ Drop Files Action } +procedure TfmMain.FormCreate(Sender: TObject); +begin + odProtoFile.DefaultFolder := '.\'; + odProtoFile.DefaultExtension := PROTO; + odProtoFile.Options := odProtoFile.Options + [fdoAllowMultiSelect]; + + DragAcceptFiles(Self.Handle, True); +end; + +procedure TfmMain.FormDestroy(Sender: TObject); +begin + DragAcceptFiles(Self.Handle, False); +end; + +procedure TfmMain.WMDropFiles(var Msg: TWMDropFiles); +var + I, Len: Integer; + Catcher: TFileCatcher; +begin + inherited; + ClearFiles; + + Catcher := TFileCatcher.Create(Msg.Drop); + try + FFileCount := Catcher.FileCount; + SetLength(FFiles, FFileCount); + for I := 0 to Pred(FFileCount) do + begin + FFiles[I] := Catcher.Files[I]; + if SameText(ExtractFileExt(FFiles[I]), PROTO) then + begin + edtProtoFiles.Text := edtProtoFiles.Text + ExtractFileName(FFiles[I]) + ';'; + end + else + begin + edtProtoFiles.Font.Color := clRed; + edtProtoFiles.Text := Format('Files Type need %s !!!', [PROTO]); + end; + end; + finally + Catcher.Free; + end; + Msg.Result := 0; +end; + +{ TFileCatcher } + +constructor TFileCatcher.Create(DropHandle: HDROP); +begin + inherited Create; + FDropHandle := DropHandle; +end; + +destructor TFileCatcher.Destroy; +begin + DragFinish(FDropHandle); + inherited; +end; + +function TFileCatcher.GetFile(Idx: Integer): string; +var + FileNameLen: Integer; +begin + FileNameLen := DragQueryFile(FDropHandle, Idx, nil, 0); + SetLength(Result, FileNameLen); + DragQueryFile(FDropHandle, Idx, PChar(Result), FileNameLen + 1); +end; + +function TFileCatcher.GetFileCount: Integer; +begin + Result := DragQueryFile(FDropHandle, $FFFFFFFF, nil, 0); +end; + +function TFileCatcher.GetPoint: TPoint; +begin + DragQueryPoint(FDropHandle, Result); +end; end. diff --git a/example2/PTestAssign.dpr b/example2/PTestAssign.dpr new file mode 100644 index 0000000..fbe5792 --- /dev/null +++ b/example2/PTestAssign.dpr @@ -0,0 +1,15 @@ +program PTestAssign; + +uses + Vcl.Forms, + TestAssign in 'TestAssign.pas' {Form1}, + test in 'test.pas'; + +{$R *.res} + +begin + Application.Initialize; + Application.MainFormOnTaskbar := True; + Application.CreateForm(TForm1, Form1); + Application.Run; +end. diff --git a/example2/PTestAssign.dproj b/example2/PTestAssign.dproj new file mode 100644 index 0000000..e780abe --- /dev/null +++ b/example2/PTestAssign.dproj @@ -0,0 +1,596 @@ + + + {0CF88340-A1A1-4843-9147-EA9CE20FCDA7} + 18.2 + VCL + PTestAssign.dpr + True + Debug + Win64 + 3 + Application + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + 2052 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + ..\;$(DCC_UnitSearchPath) + System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) + $(BDS)\bin\delphi_PROJECTICON.ico + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + PTestAssign + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + + + true + 1033 + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;svnui;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;svn;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) + $(BDS)\bin\default_app.manifest + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + Debug + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) + Debug + true + $(BDS)\bin\default_app.manifest + 1033 + DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + true + 1033 + true + true + false + + + true + true + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + true + 1033 + true + true + + + true + true + + + + MainSource + + +
Form1
+ dfm +
+ + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + Application + + + + PTestAssign.dpr + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + PTestAssign.exe + true + + + + + 0 + .dll;.bpl + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + + + Contents\Resources + 1 + + + + + classes + 1 + + + + + Contents\MacOS + 0 + + + 1 + + + Contents\MacOS + 1 + + + + + 1 + + + 1 + + + 1 + + + + + res\drawable-xxhdpi + 1 + + + + + library\lib\mips + 1 + + + + + 1 + + + 1 + + + 0 + + + 1 + + + Contents\MacOS + 1 + + + library\lib\armeabi-v7a + 1 + + + 1 + + + + + 0 + + + Contents\MacOS + 1 + .framework + + + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + library\lib\armeabi + 1 + + + + + 0 + + + 1 + + + Contents\MacOS + 1 + + + + + 1 + + + 1 + + + 1 + + + + + res\drawable-normal + 1 + + + + + res\drawable-xhdpi + 1 + + + + + res\drawable-large + 1 + + + + + 1 + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + + + res\drawable-hdpi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + Contents + 1 + + + + + ..\ + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + 1 + + + 1 + + + 1 + + + + + res\values + 1 + + + + + res\drawable-small + 1 + + + + + res\drawable + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + + + res\drawable + 1 + + + + + 0 + + + 0 + + + Contents\Resources\StartUp\ + 0 + + + 0 + + + 0 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 0 + .bpl + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + + + res\drawable-mdpi + 1 + + + + + res\drawable-xlarge + 1 + + + + + res\drawable-ldpi + 1 + + + + + 1 + + + 1 + + + + + + + + + + + + + True + True + + + 12 + + + + +
diff --git a/example2/PTestAssign.res b/example2/PTestAssign.res new file mode 100644 index 0000000000000000000000000000000000000000..3c308e67f14106bf90e6dd79eefd7c596e5bea43 GIT binary patch literal 59416 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 literal 0 HcmV?d00001 diff --git a/example2/TestAssign.dfm b/example2/TestAssign.dfm new file mode 100644 index 0000000..c2cc466 --- /dev/null +++ b/example2/TestAssign.dfm @@ -0,0 +1,26 @@ +object Form1: TForm1 + Left = 0 + Top = 0 + Caption = 'Form1' + ClientHeight = 243 + ClientWidth = 472 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + OnCreate = FormCreate + PixelsPerInch = 96 + TextHeight = 13 + object Button1: TButton + Left = 200 + Top = 184 + Width = 161 + Height = 25 + Caption = 'Save/Load Stream Time' + TabOrder = 0 + OnClick = Button1Click + end +end diff --git a/example2/TestAssign.pas b/example2/TestAssign.pas new file mode 100644 index 0000000..29bb7b2 --- /dev/null +++ b/example2/TestAssign.pas @@ -0,0 +1,130 @@ +unit TestAssign; + +interface + +uses + Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, + Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, test; + +type + TForm1 = class(TForm) + Button1: TButton; + procedure FormCreate(Sender: TObject); + procedure Button1Click(Sender: TObject); + private + { Private declarations } + FStruct1: TTestStruct; + FStruct2: TTestStruct; + + FPerson1: TPerson; + FPerson2: TPerson; + procedure InitData; + public + { Public declarations } + end; + +var + Form1: TForm1; + +implementation + +uses + pbOutput, pbInput, System.Diagnostics, System.TypInfo; + +{$R *.dfm} + +procedure TForm1.Button1Click(Sender: TObject); +var + lvWatch: TStopwatch; + lvStream: TMemoryStream; + I: Integer; +begin + FStruct2.Assign(FStruct1); + Assert(FStruct1.ToString = FStruct2.ToString, 'Assign Fail!'); + + lvStream := TMemoryStream.Create; + lvWatch := TStopWatch.StartNew; + for I := 0 to 100000 do + begin + lvStream.Clear; + FStruct1.SaveToStream(lvStream); + end; + lvWatch.Stop; + ShowMessage(Format('Save: %d', [lvWatch.ElapsedMilliseconds])); + + lvWatch.Reset; + lvWatch.Start; + for I := 0 to 100000 do + begin + FStruct1.LoadFromStream(lvStream); + end; + lvWatch.Stop; + ShowMessage(Format('Load: %d', [lvWatch.ElapsedMilliseconds])); + +//test Persion + lvWatch.Reset; + lvWatch.Start; + for I := 0 to 100000 do + begin + lvStream.Clear; + FPerson1.SaveToStream(lvStream); + end; + lvWatch.Stop; + ShowMessage(Format('Save: %d', [lvWatch.ElapsedMilliseconds])); + + lvStream.Free; +end; + +procedure TForm1.FormCreate(Sender: TObject); +begin + InitData; +end; + +procedure TForm1.InitData; +var + ver1, ver2: TVersionInfo; + ph1, ph2: TPhoneNumber; +begin + FStruct1 := TTestStruct.Create; + FStruct2 := TTestStruct.Create; + + FStruct1.aint := 2; + FStruct1.aword := 3; + FStruct1.bword := 5; + + ver1 := TVersionInfo.Create; + ver1.majorVersion := 1; + ver1.minorVersion := 2; + ver1.realease := 3; + ver1.build := 4; + FStruct1.lstVerList.Add(ver1); + + ver2 := TVersionInfo.Create; + ver2.majorVersion := 5; + ver2.minorVersion := 6; + ver2.realease := 7; + ver2.build := 8; + FStruct1.lstVerList.Add(ver2); + + FStruct1.arrIntList.Add(10); + FStruct1.arrIntList.Add(15); + FStruct1.arrStrList.Add('123'); + FStruct1.arrStrList.Add('456'); + + //TPersion + FPerson1 := TPerson.Create; + FPerson1.Name := 'Marat Shaymardanov'; + FPerson1.Id := 1; + FPerson1.Email := 'marat-sh@sibmail.com'; + ph1 := TPhoneNumber.Create; + ph1.ptype := TPhoneType.HOME; + ph1.number := '+7 392 224 3699'; + FPerson1.phoneList.Add(ph1); + + ph2 := TPhoneNumber.Create; + ph2.ptype := TPhoneType.MOBILE; + ph2.number := '+7 913 826 2144'; + FPerson1.phoneList.Add(ph2); +end; + +end. diff --git a/example2/test1.proto b/example2/test1.proto new file mode 100644 index 0000000..0fedd5f --- /dev/null +++ b/example2/test1.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; + +package test1; + +message TestStruct { + int32 aint = 1; + uint32 aword = 2; + uint32 bword = 3; + uint32 abyte = 4; + double dt = 5; + bool b = 6; + string str = 7; + repeated int32 arrInt = 8; + repeated string arrStr = 9; + repeated VersionInfo lstVer = 10; + VersionInfo ver = 11; +} + +message VersionInfo { + uint32 majorVersion = 1; + uint32 minorVersion = 2; + uint32 realease = 3; + uint32 build = 4; + } + +message Person { + required string name = 1; + required int32 id = 2; + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType ptype = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} \ No newline at end of file diff --git a/example2/test2.proto b/example2/test2.proto new file mode 100644 index 0000000..d31f996 --- /dev/null +++ b/example2/test2.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package test2; + +message VersionInfo2 { + uint32 majorVersion = 1; + uint32 minorVersion = 2; + uint32 realease = 3; + uint32 build = 4; + } \ No newline at end of file From 94cf15a3ceba9ab6232703fd0f1e5a39159b8e00 Mon Sep 17 00:00:00 2001 From: JinnBlue Date: Wed, 21 Dec 2016 18:28:03 +0800 Subject: [PATCH 2/4] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2f1a4c1..66be792 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # ProtoBufGenerator - +## Update -- 2016.12.21(jinnblue) + 1.Fix Generates .pas files bug; + 2.Add Drop Files feature; + 3.Add Benchmark Test; + + +## Work in progress! (but you can use it right now) Delphi ProtoBuf files generator ### Update 14.01.2017 @@ -42,4 +48,4 @@ Do not use `LoadFromBuf`/`SaveToBuf` methods in generated classes! Use `LoadFrom ## ToDo: - add `extensions` (simple ignore directive, or - wrap to comment) -- add tests with "original" ProtoBuf generated binary messages. \ No newline at end of file +- add tests with "original" ProtoBuf generated binary messages. From 5bb4bc3c2cd0218ffc1555ef3bebb2a6ff638597 Mon Sep 17 00:00:00 2001 From: JinnBlue Date: Fri, 8 Sep 2017 17:34:00 +0800 Subject: [PATCH 3/4] [!] rebase from kami-soft/master; [+] 1.Add Drap files to generator.exe feature; 2.Add extensions check. --- Generator/ProtoBufGenerator.dproj | 125 +++- Generator/ProtoBufGenerator.res | Bin 58644 -> 59452 bytes Generator/ProtoBufGeneratorConsole.dproj | 163 +++-- Generator/Test/ProtoBufGeneratorTests.dpr | 1 - Generator/Test/ProtoBufGeneratorTests.dproj | 53 +- Generator/Test/TestProtoBuf.pas | 8 +- Generator/ufmMain.pas | 74 +-- README.md | 28 +- example1_without_Generator/Example1.pas | 122 ++-- example1_without_Generator/Project1.dpr | 2 - example1_without_Generator/Project1.dproj | 433 ++++++++++++- .../Test/Project1Tests.dproj | 478 +++++++++++++- example2/PTestAssign.dpr | 15 - example2/PTestAssign.dproj | 596 ------------------ example2/PTestAssign.res | Bin 59416 -> 0 bytes example2/TestAssign.dfm | 26 - example2/TestAssign.pas | 130 ---- example2/test1.proto | 43 -- example2/test2.proto | 10 - example2_with_Generator/ProjectExample2.dproj | 99 ++- example2_with_Generator/test1.pas | 14 +- example2_with_Generator/ufmMain.dfm | 23 +- 22 files changed, 1275 insertions(+), 1168 deletions(-) delete mode 100644 example2/PTestAssign.dpr delete mode 100644 example2/PTestAssign.dproj delete mode 100644 example2/PTestAssign.res delete mode 100644 example2/TestAssign.dfm delete mode 100644 example2/TestAssign.pas delete mode 100644 example2/test1.proto delete mode 100644 example2/test2.proto diff --git a/Generator/ProtoBufGenerator.dproj b/Generator/ProtoBufGenerator.dproj index 3d8fbcc..7315e78 100644 --- a/Generator/ProtoBufGenerator.dproj +++ b/Generator/ProtoBufGenerator.dproj @@ -1,7 +1,7 @@  {D34DF9E7-E280-40E5-8974-55D191521066} - 18.1 + 18.2 VCL ProtoBufGenerator.dpr True @@ -34,6 +34,12 @@ true true + + true + Cfg_1 + true + true + true Base @@ -45,6 +51,12 @@ true true + + true + Cfg_2 + true + true + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=kami-soft;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=https://github.com/kami-soft/ProtoBufGenerator true @@ -61,13 +73,23 @@ false + Debug + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;svnui;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;svn;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FixInsight_10;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;madExcept_;VirtualTreesR;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;madBasic_;TeeDB;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;madDisAsm_;DBXSybaseASADriver;CustomIPTransport;vcldsnap;CodeSiteExpressPkg;bindcomp;appanalytics;fgx;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) 1033 - true $(BDS)\bin\default_app.manifest Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + $(BDS)\bin\default_app.manifest + Debug + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;VirtualTreesR;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) @@ -79,12 +101,18 @@ true + Debug true 1033 true true false + + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + true + false RELEASE;$(DCC_Define) @@ -95,6 +123,10 @@ true true + + true + true + MainSource @@ -136,19 +168,34 @@ Microsoft Office XP Sample Automation Server Wrapper Components - + ProtoBufGenerator.exe true - + + + 0 + .dll;.bpl + 1 + .dylib + + + Contents\MacOS + 1 + .dylib 1 + .dylib + + + 1 + .dylib @@ -200,19 +247,22 @@ + + 1 + + + 1 + 0 - + 1 Contents\MacOS 1 - - 1 - library\lib\armeabi-v7a 1 @@ -231,6 +281,14 @@ .framework + + + 1 + + + 1 + + 1 @@ -263,12 +321,7 @@ 1 - - - library\lib\x86 - 1 - - + 1 @@ -349,13 +402,23 @@ 1 + + + Assets + 1 + + + Assets + 1 + + - ../ + ..\ 1 - ../ + ..\ 1 @@ -379,7 +442,17 @@ - ../ + ..\ + 1 + + + + + Assets + 1 + + + Assets 1 @@ -502,33 +575,19 @@ 1 - - - 0 - .dll;.bpl - + 1 - .dylib - - - Contents\MacOS - 1 - .dylib 1 - .dylib - - - 1 - .dylib + diff --git a/Generator/ProtoBufGenerator.res b/Generator/ProtoBufGenerator.res index 304fe44587305e0f41c0a3efc263722bca611c2f..e27e9daa3625f8697c14342634e3406902f2f8e0 100644 GIT binary patch delta 947 zcmbu7O^XvT7{{M!VPO8=*+qh(%x%=@;cNZNe9RLIX2M4DX zCzoeCq%*(u)Z3lEzwG7n{c~6E!fEi}He`^4fsvavq%d`H1&v!vn7C?KeDbc$zmaRt zpy%WdoS=l~Zk15L*p;;-b-4oi&Y}S2cBU>PLA$tB_gjmLqZRIVy@oBPXyD$;#k3Z! zW^u#gdq2JN-#hO%_BNLL-7{%fRIuG+GI_a;vWad5rbbSS>aD6Orwy{@6g_cU<#vr8XLTbH#+%O2 zAO2Aoeg7dE>+8MOCLol~xQH+nJj9%(0!v{HCM4Fz7^ayeZ+e6O=11$j+ItrYU_3YRX8%Y{qWfgNzZepyGJ5pdC oTP=vBLME#>_kF)@!NFfWI2;`6RrfVcQrD(X`Hl-<@%6{eUjfq)pa1{> delta 217 zcmdmUfqBX)<_QYi9~c=J6c`v7{{I)4?Eg@d=>y|Lrzl3hiF1`1wI&`EpRB@YU~0j@ z#lXnm!;s35&XCBE!{E%2&rrZn$xy_Q2^7g-C;{rv2Fm0D`MM0nK-n~glF45g%>&CA z^np4->T`iGl_3wPwiu`yq^AUEMlpjGP=!9wluRH$gQ1imi9wGc8LVC((@X~aiT_nM jYcWaPXIjs^+3n#$W*+^-;^NfYq?}4SUarZ%pF08o-#s>_ diff --git a/Generator/ProtoBufGeneratorConsole.dproj b/Generator/ProtoBufGeneratorConsole.dproj index 7e87c6e..7d1b35a 100644 --- a/Generator/ProtoBufGeneratorConsole.dproj +++ b/Generator/ProtoBufGeneratorConsole.dproj @@ -1,7 +1,7 @@  {81A7AF46-9C76-49D6-9775-F01D681DC620} - 18.1 + 18.2 None ProtoBufGeneratorConsole.dpr True @@ -13,31 +13,6 @@ true - - true - Base - true - - - true - Base - true - - - true - Base - true - - - true - Base - true - - - true - Base - true - true Base @@ -75,38 +50,12 @@ false false - - $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png - android-support-v4.dex.jar;apk-expansion.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar - $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png - $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png - $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png - $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png - DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;bindcompfmx;FmxTeeUI;FireDACIBDriver;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;ibxbindings;FireDACDSDriver;soapmidas;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;DataSnapProviderClient;dsnapxml;dbrtl;IndyProtocols;$(DCC_UsePackage) - $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png - $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png - $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png - $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png - - - DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;bindcompfmx;FmxTeeUI;FireDACIBDriver;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;ibxbindings;FireDACDSDriver;soapmidas;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;DataSnapProviderClient;dsnapxml;dbrtl;IndyProtocols;fmxase;$(DCC_UsePackage) - - - DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;bindcompfmx;FmxTeeUI;FireDACIBDriver;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;ibxbindings;FireDACDSDriver;soapmidas;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;DataSnapProviderClient;dsnapxml;dbrtl;IndyProtocols;fmxase;$(DCC_UsePackage) - - - DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;bindcompfmx;FmxTeeUI;FireDACIBDriver;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;ibxbindings;FireDACDSDriver;soapmidas;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;DataSnapProviderClient;dsnapxml;dbrtl;IndyProtocols;fmxase;$(DCC_UsePackage) - - - true - DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;FireDACMSSQLDriver;bindcompfmx;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;bindcomp;DBXInformixDriver;IndyIPClient;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) - 1033 true Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;svnui;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;svn;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FixInsight_10;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;madExcept_;VirtualTreesR;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;madBasic_;TeeDB;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;madDisAsm_;DBXSybaseASADriver;CustomIPTransport;vcldsnap;CodeSiteExpressPkg;bindcomp;appanalytics;fgx;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) - CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName) true @@ -121,6 +70,11 @@ true + ..\Ready + (None) + ..\DCU + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) + 1033 /f "D:\DelphiComponents\ProtoBuf\Ready" /o "c:\Temp" false @@ -159,8 +113,12 @@ ProtoBufGeneratorConsole.dpr + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + - + true @@ -176,18 +134,38 @@ true + + + true + + ProtoBufGeneratorConsole.exe true - + + + 0 + .dll;.bpl + 1 + .dylib + + + Contents\MacOS + 1 + .dylib 1 + .dylib + + + 1 + .dylib @@ -239,19 +217,22 @@ + + 1 + + + 1 + 0 - + 1 Contents\MacOS 1 - - 1 - library\lib\armeabi-v7a 1 @@ -270,6 +251,14 @@ .framework + + + 1 + + + 1 + + 1 @@ -302,12 +291,7 @@ 1 - - - library\lib\x86 - 1 - - + 1 @@ -388,13 +372,23 @@ 1 + + + Assets + 1 + + + Assets + 1 + + - ../ + ..\ 1 - ../ + ..\ 1 @@ -418,7 +412,17 @@ - ../ + ..\ + 1 + + + + + Assets + 1 + + + Assets 1 @@ -541,43 +545,24 @@ 1 - - - 0 - .dll;.bpl - + 1 - .dylib - - - Contents\MacOS - 1 - .dylib 1 - .dylib - - - 1 - .dylib + - False - False - False - False - False True False diff --git a/Generator/Test/ProtoBufGeneratorTests.dpr b/Generator/Test/ProtoBufGeneratorTests.dpr index ad6868e..4784e3a 100644 --- a/Generator/Test/ProtoBufGeneratorTests.dpr +++ b/Generator/Test/ProtoBufGeneratorTests.dpr @@ -26,7 +26,6 @@ uses pbOutput in '..\..\pbOutput.pas', pbPublic in '..\..\pbPublic.pas', StrBuffer in '..\..\StrBuffer.pas', - TestuProtoBufGenerator in 'TestuProtoBufGenerator.pas', TestProtoBuf in 'TestProtoBuf.pas'; {R *.RES} diff --git a/Generator/Test/ProtoBufGeneratorTests.dproj b/Generator/Test/ProtoBufGeneratorTests.dproj index 7ffd3d9..dba590e 100644 --- a/Generator/Test/ProtoBufGeneratorTests.dproj +++ b/Generator/Test/ProtoBufGeneratorTests.dproj @@ -13,11 +13,6 @@ true - - true - Base - true - true Base @@ -59,9 +54,6 @@ false false - - DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;FireDACMSSQLDriver;bindcompfmx;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;bindcomp;DBXInformixDriver;IndyIPClient;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) - 1033 Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) @@ -96,6 +88,7 @@ MainSource + @@ -104,7 +97,6 @@ - Cfg_2 @@ -147,23 +139,38 @@ true + + + true + + ProtoBufGeneratorTests.exe true - - - true + + + 0 + .dll;.bpl - - 1 + .dylib + + + Contents\MacOS + 1 + .dylib 1 + .dylib + + + 1 + .dylib @@ -543,27 +550,12 @@ 1 - - - 0 - .dll;.bpl - + 1 - .dylib - - - Contents\MacOS - 1 - .dylib 1 - .dylib - - - 1 - .dylib @@ -576,7 +568,6 @@ - False True False diff --git a/Generator/Test/TestProtoBuf.pas b/Generator/Test/TestProtoBuf.pas index 9900a0e..6ef7fa1 100644 --- a/Generator/Test/TestProtoBuf.pas +++ b/Generator/Test/TestProtoBuf.pas @@ -71,8 +71,8 @@ procedure TestProtoBufMethods.TestDecodeZigZag; CheckEquals(Int64($FFFFFFFFC0000000), decodeZigZag64($000000007FFFFFFF)); CheckEquals(Int64($000000007FFFFFFF), decodeZigZag64($00000000FFFFFFFE)); CheckEquals(Int64($FFFFFFFF80000000), decodeZigZag64($00000000FFFFFFFF)); - CheckEquals(Int64($7FFFFFFFFFFFFFFF), decodeZigZag64($FFFFFFFFFFFFFFFE)); - CheckEquals(Int64($8000000000000000), decodeZigZag64($FFFFFFFFFFFFFFFF)); + CheckEquals(Int64($7FFFFFFFFFFFFFFF), decodeZigZag64(Int64($FFFFFFFFFFFFFFFE))); + CheckEquals(Int64($8000000000000000), decodeZigZag64(Int64($FFFFFFFFFFFFFFFF))); end; procedure TestProtoBufMethods.TestEncodeDecodeZigZag; @@ -196,7 +196,7 @@ TLittleEndianCase = record procedure TestProtoBufMethods.TestReadString; const - TEST_string = ' '; + TEST_string:string = '? '; TEST_integer = 12345678; TEST_single = 12345.123; TEST_double = 1234567890.123; @@ -316,7 +316,7 @@ TVarintCase = record for i := 0 to 7 do begin t := VarintCases[i]; - // + // ? ? SetLength(buf, t.Size); for j := 1 to t.Size do buf[j] := AnsiChar(t.bytes[j]); diff --git a/Generator/ufmMain.pas b/Generator/ufmMain.pas index a2467be..b55bdb5 100644 --- a/Generator/ufmMain.pas +++ b/Generator/ufmMain.pas @@ -3,15 +3,7 @@ interface uses - Winapi.Windows, - Winapi.Messages, - System.SysUtils, - System.Classes, - Vcl.Graphics, - Vcl.Controls, - Vcl.Forms, - Vcl.Dialogs, - Vcl.StdCtrls; + Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TfmMain = class(TForm) @@ -27,7 +19,7 @@ TfmMain = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private - FFiles: TArray; + FFiles : TArray; FFileCount: Integer; procedure ClearFiles; @@ -41,7 +33,6 @@ TFileCatcher = class(TObject) function GetFile(Idx: Integer): string; function GetFileCount: Integer; function GetPoint: TPoint; - procedure Generate(SourceFiles: TStrings; const OutputDir: string); public constructor Create(DropHandle: THANDLE); destructor Destroy; override; @@ -56,9 +47,7 @@ TFileCatcher = class(TObject) implementation uses - Vcl.FileCtrl, - Winapi.ShellAPI, - uProtoBufGenerator; + Vcl.FileCtrl, Winapi.ShellAPI, uProtoBufGenerator; const PROTO = '.proto'; @@ -70,32 +59,29 @@ procedure TfmMain.btnChooseOutputFolderClick(Sender: TObject); Dir: string; begin Dir := edtOutputFolder.Text; - if SelectDirectory('choose output dir', '', Dir, [sdNewFolder, sdShowShares, sdNewUI, sdValidateDir], nil) - then + if SelectDirectory('choose output dir', '', Dir, [sdNewFolder, sdShowShares, sdNewUI, sdValidateDir], nil) then edtOutputFolder.Text := Dir; end; procedure TfmMain.btnGenerateClick(Sender: TObject); var - FileNames: TStrings; - I: Integer; + OutPutDir: string; + I : Integer; + Gen: TProtoBufGenerator; begin - FileNames := TStringList.Create; - if edtOutputFolder.Text <> '' then - ForceDirectories(edtOutputFolder.Text); + if edtProtoFiles.Font.Color = clRed then + Exit; + + OutPutDir := edtOutputFolder.Text; + if OutPutDir <> '' then + ForceDirectories(OutPutDir); Gen := TProtoBufGenerator.Create; try - FileNames.Delimiter:=odProtoFile.Files.Delimiter; - FileNames.DelimitedText:=edProtoFileName.Text; - Generate(FileNames, edOutputFolder.Text); - ShowMessage('Complete! Take a look into output directory'); for I := 0 to Pred(FFileCount) do - begin Gen.Generate(FFiles[I], edtOutputFolder.Text, TEncoding.UTF8); - end; finally - FileNames.Free; + Gen.Free; end; end; @@ -104,32 +90,26 @@ procedure TfmMain.btnOpenProtoFileClick(Sender: TObject); I: Integer; begin if odProtoFile.Execute then - edProtoFileName.Text := odProtoFile.Files.DelimitedText; begin - FFileCount := odProtoFile.Files.Count; + ClearFiles; + FFileCount := odProtoFile.Files.Count; SetLength(FFiles, FFileCount); for I := 0 to Pred(FFileCount) do begin FFiles[I] := odProtoFile.Files[I]; - edtProtoFiles.Text := edtProtoFiles.Text + ExtractFileName(FFiles[I]) + ';'; + if SameText(ExtractFileExt(FFiles[I]), PROTO) then + begin + edtProtoFiles.Text := edtProtoFiles.Text + ExtractFileName(FFiles[I]) + ','; + end + else + begin + edtProtoFiles.Font.Color := clRed; + edtProtoFiles.Text := Format('Files Type need %s !!!', [PROTO]); + end; end; end; end; -procedure TfmMain.Generate(SourceFiles: TStrings; const OutputDir: string); -var - Gen: TProtoBufGenerator; - i: Integer; -begin - System.SysUtils.ForceDirectories(OutputDir); - Gen := TProtoBufGenerator.Create; - try - for i := 0 to SourceFiles.Count - 1 do - Gen.Generate(SourceFiles[i], edOutputFolder.Text, TEncoding.UTF8); - finally - Gen.Free; - end; -end; procedure TfmMain.ClearFiles; begin SetLength(FFiles, 0); @@ -155,7 +135,7 @@ procedure TfmMain.FormDestroy(Sender: TObject); procedure TfmMain.WMDropFiles(var Msg: TWMDropFiles); var - I, Len: Integer; + I, Len : Integer; Catcher: TFileCatcher; begin inherited; @@ -170,7 +150,7 @@ procedure TfmMain.WMDropFiles(var Msg: TWMDropFiles); FFiles[I] := Catcher.Files[I]; if SameText(ExtractFileExt(FFiles[I]), PROTO) then begin - edtProtoFiles.Text := edtProtoFiles.Text + ExtractFileName(FFiles[I]) + ';'; + edtProtoFiles.Text := edtProtoFiles.Text + ExtractFileName(FFiles[I]) + ','; end else begin diff --git a/README.md b/README.md index 66be792..9797c59 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,15 @@ # ProtoBufGenerator -## Update -- 2016.12.21(jinnblue) - 1.Fix Generates .pas files bug; - 2.Add Drop Files feature; - 3.Add Benchmark Test; - - -## Work in progress! (but you can use it right now) Delphi ProtoBuf files generator +### Update 08.09.2017(jinnblue) rebase from kami-soft/master ++ Add Drap files to generator.exe feature ++ Add extensions check + ### Update 14.01.2017 -Add console generator version ++ Add console generator version ### Update 08.01.2017 -Add example ++ Add example Work with binary ProtoBuf messages based on https://sourceforge.net/projects/protobuf-delphi/files/ by marat1961 (sources have some modifications) @@ -37,15 +34,14 @@ Limitations: - `groups` (deprecated feature) not supported ## How to use -+ add root folder of this project to library path (Tools - Options - Delphi options - Library) -+ open ProtoBufGeneratorGroup.groupproj from root folder of this project -+ compile and run ProtoBufGenerator.exe -+ open .proto file(s) by press "Open" button -+ select directory for new generated .pas file(s) and press "Generate" button -+ add generated file to your project. +1. add root folder of this project to library path (Tools - Options - Delphi options - Library) +2. open ProtoBufGeneratorGroup.groupproj from root folder of this project +3. compile and run ProtoBufGenerator.exe +4. open .proto file(s) by press "Open" button +5. select directory for new generated .pas file(s) and press "Generate" button +6. add generated file to your project. Do not use `LoadFromBuf`/`SaveToBuf` methods in generated classes! Use `LoadFromStream` and `SaveToStream` methods, which inherited from base class. See `Example2`, how to use generated classes. ## ToDo: -- add `extensions` (simple ignore directive, or - wrap to comment) - add tests with "original" ProtoBuf generated binary messages. diff --git a/example1_without_Generator/Example1.pas b/example1_without_Generator/Example1.pas index 1746d67..6b5a4de 100644 --- a/example1_without_Generator/Example1.pas +++ b/example1_without_Generator/Example1.pas @@ -12,7 +12,8 @@ interface -uses Classes, SysUtils, Contnrs, pbPublic, pbInput, pbOutput; +uses + Classes, SysUtils, Contnrs, pbPublic, pbInput, pbOutput; (* @@ -40,45 +41,47 @@ interface type - TPhoneType = (ptMOBILE, ptHOME, ptWORK); - - TPhoneNumber = class - private - FTyp: TPhoneType; - FNumber: AnsiString; - const - ft_Number = 1; - ft_Typ = 2; - public - constructor Create; - property Number: AnsiString read FNumber write FNumber; - property Typ: TPhoneType read FTyp write FTyp; - end; + TPhoneType = (ptMOBILE, ptHOME, ptWORK); - TPerson = class - private - FName: AnsiString; - FEmail: AnsiString; - FId: integer; - FPhones: TObjectList; - function GetPhones(Index: integer): TPhoneNumber; - function GetPhonesCount: integer; - const - ft_Name = 1; - ft_Id = 2; - ft_Email = 3; - ft_Phone = 4; - public - constructor Create; - destructor Destroy; override; - procedure AddPhone(const Number: AnsiString; Typ: TPhoneType = ptHOME); - procedure DeletePhone(Index: integer); - property Name: AnsiString read FName write FName; - property Id: integer read FId write FId; - property Email: AnsiString read FEmail write FEmail; - property PhonesCount: integer read GetPhonesCount; - property Phones[Index: integer]: TPhoneNumber read GetPhones; - end; + TPhoneNumber = class + private + FTyp : TPhoneType; + FNumber: AnsiString; + + const + ft_Number = 1; + ft_Typ = 2; + public + constructor Create; + property Number: AnsiString read FNumber write FNumber; + property Typ: TPhoneType read FTyp write FTyp; + end; + + TPerson = class + private + FName : AnsiString; + FEmail : AnsiString; + FId : integer; + FPhones: TObjectList; + function GetPhones(Index: integer): TPhoneNumber; + function GetPhonesCount: integer; + + const + ft_Name = 1; + ft_Id = 2; + ft_Email = 3; + ft_Phone = 4; + public + constructor Create; + destructor Destroy; override; + procedure AddPhone(const Number: AnsiString; Typ: TPhoneType = ptHOME); + procedure DeletePhone(Index: integer); + property name: AnsiString read FName write FName; + property Id: integer read FId write FId; + property Email: AnsiString read FEmail write FEmail; + property PhonesCount: integer read GetPhonesCount; + property Phones[index: integer]: TPhoneNumber read GetPhones; + end; TPersonBuilder = class private @@ -98,7 +101,7 @@ TPersonReader = class constructor Create; destructor Destroy; override; function GetBuf: TProtoBufInput; - procedure Load(person: TPerson); + procedure Load(Person: TPerson); end; implementation @@ -130,9 +133,9 @@ function TPerson.GetPhonesCount: integer; Result := FPhones.Count; end; -function TPerson.GetPhones(Index: Integer): TPhoneNumber; +function TPerson.GetPhones(Index: integer): TPhoneNumber; begin - Result := FPhones.Items[Index] as TPhoneNumber; + Result := FPhones.Items[index] as TPhoneNumber; end; procedure TPerson.AddPhone(const Number: AnsiString; Typ: TPhoneType = ptHOME); @@ -147,7 +150,7 @@ procedure TPerson.AddPhone(const Number: AnsiString; Typ: TPhoneType = ptHOME); procedure TPerson.DeletePhone(Index: integer); begin - FPhones.Delete(Index); + FPhones.Delete(index); end; { TPersonBuilder } @@ -171,9 +174,9 @@ function TPersonBuilder.GetBuf: TProtoBufOutput; procedure TPersonBuilder.Write(Person: TPerson); var - Phone: TPhoneNumber; + Phone : TPhoneNumber; PhonesBuffer: TProtoBufOutput; - i: Integer; + i : integer; begin FBuffer.writeString(TPerson.ft_Name, Person.Name); FBuffer.writeInt32(TPerson.ft_Id, Person.FId); @@ -222,30 +225,31 @@ function TPersonReader.GetBuf: TProtoBufInput; Result := FBuffer; end; -procedure TPersonReader.Load(person: TPerson); +procedure TPersonReader.Load(Person: TPerson); var tag, fieldNumber, wireType: integer; - Phone: TPhoneNumber; + Phone : TPhoneNumber; begin tag := FBuffer.readTag; - while tag <> 0 do begin + while tag <> 0 do + begin wireType := getTagWireType(tag); fieldNumber := getTagFieldNumber(tag); case fieldNumber of TPerson.ft_Name: begin Assert(wireType = WIRETYPE_LENGTH_DELIMITED); - person.Name := FBuffer.readString; + Person.Name := FBuffer.readString; end; TPerson.ft_Id: begin Assert(wireType = WIRETYPE_VARINT); - person.Id := FBuffer.readInt32; + Person.Id := FBuffer.readInt32; end; TPerson.ft_Email: begin Assert(wireType = WIRETYPE_LENGTH_DELIMITED); - person.Email := FBuffer.readString; + Person.Email := FBuffer.readString; end; TPerson.ft_Phone: begin @@ -254,8 +258,8 @@ procedure TPersonReader.Load(person: TPerson); Person.FPhones.Add(Phone); LoadPhone(Phone); end; - else - FBuffer.skipField(tag); + else + FBuffer.skipField(tag); end; tag := FBuffer.readTag; end; @@ -264,14 +268,15 @@ procedure TPersonReader.Load(person: TPerson); procedure TPersonReader.LoadPhone(Phone: TPhoneNumber); var tag, fieldNumber, wireType: integer; - size: Integer; - endPosition: Integer; + size : integer; + endPosition : integer; begin size := FBuffer.readInt32; endPosition := FBuffer.getPos + size; repeat tag := FBuffer.readTag; - if tag = 0 then exit; + if tag = 0 then + exit; wireType := getTagWireType(tag); fieldNumber := getTagFieldNumber(tag); case fieldNumber of @@ -285,11 +290,10 @@ procedure TPersonReader.LoadPhone(Phone: TPhoneNumber); Assert(wireType = WIRETYPE_VARINT); Phone.Typ := TPhoneType(FBuffer.readInt32); end; - else - FBuffer.skipField(tag); + else + FBuffer.skipField(tag); end; until FBuffer.getPos >= endPosition; end; end. - diff --git a/example1_without_Generator/Project1.dpr b/example1_without_Generator/Project1.dpr index 3dde0db..a4db0d7 100644 --- a/example1_without_Generator/Project1.dpr +++ b/example1_without_Generator/Project1.dpr @@ -5,7 +5,6 @@ program Project1; uses SysUtils, TypInfo, Example1 in 'Example1.pas', - UnitTest in '..\UnitTest.pas', pbInput in '..\pbInput.pas', pbOutput in '..\pbOutput.pas', pbPublic in '..\pbPublic.pas', @@ -78,7 +77,6 @@ end; begin Writeln('Run Protocol Buffer Tests'); - TestAll; TestPerson; end. diff --git a/example1_without_Generator/Project1.dproj b/example1_without_Generator/Project1.dproj index a34de9f..a0d4945 100644 --- a/example1_without_Generator/Project1.dproj +++ b/example1_without_Generator/Project1.dproj @@ -1,7 +1,7 @@  {F5064338-5047-4F36-AF30-AB3E1CD5D3B9} - 14.3 + 18.2 VCL Project1.dpr True @@ -40,6 +40,7 @@ true + Project1 System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) $(BDS)\bin\delphi_PROJECTICON.ico .\$(Platform)\$(Config) @@ -51,14 +52,19 @@ false + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + true fs17;frx17;bindcompfmx;DBXSqliteDriver;vcldbx;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;TeeDB;bindcomp;inetdb;vclib;inetdbbde;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DBXOdbcDriver;DataSnapServer;Tee;DataSnapProviderClient;xmlrtl;svnui;ibxpress;DbxCommonDriver;DBXSybaseASEDriver;vclimg;IndyProtocols;dbxcds;DBXMySQLDriver;MetropolisUILiveTile;vclactnband;bindengine;vcldb;soaprtl;bindcompdbx;vcldsnap;bindcompvcl;FMXTee;TeeUI;vclie;vcltouch;DBXDb2Driver;websnap;DBXOracleDriver;CustomIPTransport;vclribbon;VclSmp;dsnap;IndyIPServer;DBXInformixDriver;Intraweb;fmxase;vcl;IndyCore;DataSnapConnectors;IndyIPCommon;CloudService;DBXMSSQLDriver;dsnapcon;DBXFirebirdDriver;FmxTeeUI;inet;fsDB17;fmxobj;frxDB17;CodeSiteExpressPkg;vclx;frxe17;inetdbxpress;webdsnap;svn;DBXSybaseASADriver;fmxdae;bdertl;dbexpress;adortl;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) $(BDS)\bin\default_app.manifest Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 1033 - CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName) true + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png bindcompfmx;DBXSqliteDriver;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;TeeDB;bindcomp;inetdb;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DBXOdbcDriver;DataSnapServer;Tee;DataSnapProviderClient;xmlrtl;ibxpress;DbxCommonDriver;DBXSybaseASEDriver;vclimg;IndyProtocols;dbxcds;DBXMySQLDriver;vclactnband;bindengine;vcldb;soaprtl;bindcompdbx;vcldsnap;bindcompvcl;TeeUI;vclie;vcltouch;DBXDb2Driver;websnap;DBXOracleDriver;CustomIPTransport;VclSmp;dsnap;IndyIPServer;DBXInformixDriver;fmxase;vcl;IndyCore;DataSnapConnectors;IndyIPCommon;DBXMSSQLDriver;dsnapcon;DBXFirebirdDriver;inet;fmxobj;vclx;inetdbxpress;webdsnap;DBXSybaseASADriver;fmxdae;dbexpress;adortl;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) @@ -70,20 +76,20 @@ true + Debug false false RELEASE;$(DCC_Define) 0 - false + 0 MainSource - @@ -144,7 +150,423 @@ Project1.dpr - + + + + 0 + .dll;.bpl + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + + + Contents\Resources + 1 + + + + + classes + 1 + + + + + Contents\MacOS + 0 + + + 1 + + + Contents\MacOS + 1 + + + + + 1 + + + 1 + + + 1 + + + + + res\drawable-xxhdpi + 1 + + + + + library\lib\mips + 1 + + + + + 1 + + + 1 + + + 0 + + + 1 + + + Contents\MacOS + 1 + + + library\lib\armeabi-v7a + 1 + + + 1 + + + + + 0 + + + Contents\MacOS + 1 + .framework + + + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + library\lib\armeabi + 1 + + + + + 0 + + + 1 + + + Contents\MacOS + 1 + + + + + 1 + + + 1 + + + 1 + + + + + res\drawable-normal + 1 + + + + + res\drawable-xhdpi + 1 + + + + + res\drawable-large + 1 + + + + + 1 + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + + + res\drawable-hdpi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + Contents + 1 + + + + + ..\ + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + 1 + + + 1 + + + 1 + + + + + res\values + 1 + + + + + res\drawable-small + 1 + + + + + res\drawable + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + + + res\drawable + 1 + + + + + 0 + + + 0 + + + Contents\Resources\StartUp\ + 0 + + + 0 + + + 0 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 0 + .bpl + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + + + res\drawable-mdpi + 1 + + + + + res\drawable-xlarge + 1 + + + + + res\drawable-ldpi + 1 + + + + + 1 + + + 1 + + + + + + + + + + + True False @@ -157,4 +579,5 @@ + diff --git a/example1_without_Generator/Test/Project1Tests.dproj b/example1_without_Generator/Test/Project1Tests.dproj index 4d473e1..934ff7e 100644 --- a/example1_without_Generator/Test/Project1Tests.dproj +++ b/example1_without_Generator/Test/Project1Tests.dproj @@ -1,7 +1,7 @@  {CB7BD6AB-72F4-47AA-99DB-B48A0B7D746C} - 14.3 + 18.2 None True Debug @@ -13,8 +13,23 @@ true - - true + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true Base true @@ -45,6 +60,9 @@ true + $(BDS)\bin\delphi_PROJECTICNS.icns + Project1Tests + $(BDS)\bin\delphi_PROJECTICON.ico _CONSOLE_TESTRUNNER;$(DCC_Define) $(BDS)\Source\DUnit\src;$(DCC_UnitSearchPath) System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) @@ -56,14 +74,74 @@ false false - - bindcompfmx;DBXSqliteDriver;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;bindcomp;inetdb;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;xmlrtl;DbxCommonDriver;IndyProtocols;dbxcds;DBXMySQLDriver;bindengine;soaprtl;bindcompdbx;DBXOracleDriver;CustomIPTransport;dsnap;IndyIPServer;DBXInformixDriver;fmxase;IndyCore;IndyIPCommon;DBXFirebirdDriver;inet;fmxobj;inetdbxpress;DBXSybaseASADriver;fmxdae;dbexpress;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) + + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png + true + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png + true + true + true + true + true + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png + true + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png + true + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png + $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png + true + $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png + true + + + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png + $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png + $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png + $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png + $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png + + + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png + $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png + $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png + $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png + $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png + + + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png + $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png + $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png + $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png + $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png + $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png + $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 1033 fs17;frx17;bindcompfmx;DBXSqliteDriver;vcldbx;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;TeeDB;bindcomp;inetdb;vclib;inetdbbde;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DBXOdbcDriver;DataSnapServer;Tee;DataSnapProviderClient;xmlrtl;svnui;ibxpress;DbxCommonDriver;DBXSybaseASEDriver;vclimg;IndyProtocols;dbxcds;DBXMySQLDriver;MetropolisUILiveTile;vclactnband;bindengine;vcldb;soaprtl;bindcompdbx;vcldsnap;bindcompvcl;FMXTee;TeeUI;vclie;vcltouch;DBXDb2Driver;websnap;DBXOracleDriver;CustomIPTransport;vclribbon;VclSmp;dsnap;IndyIPServer;DBXInformixDriver;Intraweb;fmxase;vcl;IndyCore;DataSnapConnectors;IndyIPCommon;CloudService;DBXMSSQLDriver;dsnapcon;DBXFirebirdDriver;FmxTeeUI;inet;fsDB17;fmxobj;frxDB17;CodeSiteExpressPkg;vclx;frxe17;inetdbxpress;webdsnap;svn;DBXSybaseASADriver;fmxdae;bdertl;dbexpress;adortl;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) - CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName) bindcompfmx;DBXSqliteDriver;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;bindcomp;inetdb;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DBXOdbcDriver;DataSnapServer;DataSnapProviderClient;xmlrtl;DbxCommonDriver;DBXSybaseASEDriver;vclimg;IndyProtocols;dbxcds;DBXMySQLDriver;vclactnband;bindengine;vcldb;soaprtl;bindcompdbx;vcldsnap;bindcompvcl;vclie;vcltouch;DBXDb2Driver;websnap;DBXOracleDriver;CustomIPTransport;VclSmp;dsnap;IndyIPServer;DBXInformixDriver;fmxase;vcl;IndyCore;IndyIPCommon;DBXMSSQLDriver;dsnapcon;DBXFirebirdDriver;inet;fmxobj;vclx;inetdbxpress;webdsnap;DBXSybaseASADriver;fmxdae;dbexpress;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) @@ -83,7 +161,7 @@ false RELEASE;$(DCC_Define) 0 - false + 0 @@ -151,8 +229,390 @@ Project1Tests.dpr - + + + + true + + + + + true + + + + + true + + + + + true + + + + + 0 + .dll;.bpl + + + 1 + .dylib + + + + + Contents\Resources + 1 + + + + + classes + 1 + + + + + Contents\MacOS + 0 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + res\drawable-xxhdpi + 1 + + + + + library\lib\mips + 1 + + + + + 1 + + + 1 + + + 0 + + + 1 + + + 1 + + + library\lib\armeabi-v7a + 1 + + + 1 + + + + + 0 + + + 1 + .framework + + + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + 1 + + + 1 + + + 1 + + + + + + library\lib\armeabi + 1 + + + + + 0 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + res\drawable-normal + 1 + + + + + res\drawable-xhdpi + 1 + + + + + res\drawable-large + 1 + + + + + 1 + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + res\drawable-hdpi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + + + Assets + 1 + + + Assets + 1 + + + + + 1 + + + 1 + + + 1 + + + + + res\values + 1 + + + + + res\drawable-small + 1 + + + + + res\drawable + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + + + res\drawable + 1 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 0 + .bpl + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + + + res\drawable-mdpi + 1 + + + + + res\drawable-xlarge + 1 + + + + + res\drawable-ldpi + 1 + + + + + + + + + + + + + False + False + False + False False True False @@ -161,10 +621,12 @@ DUnit / Delphi Win32 GUI D:\work\protobuf delphi\protobuf-delphi\example1\Project1.dproj + 12 + diff --git a/example2/PTestAssign.dpr b/example2/PTestAssign.dpr deleted file mode 100644 index fbe5792..0000000 --- a/example2/PTestAssign.dpr +++ /dev/null @@ -1,15 +0,0 @@ -program PTestAssign; - -uses - Vcl.Forms, - TestAssign in 'TestAssign.pas' {Form1}, - test in 'test.pas'; - -{$R *.res} - -begin - Application.Initialize; - Application.MainFormOnTaskbar := True; - Application.CreateForm(TForm1, Form1); - Application.Run; -end. diff --git a/example2/PTestAssign.dproj b/example2/PTestAssign.dproj deleted file mode 100644 index e780abe..0000000 --- a/example2/PTestAssign.dproj +++ /dev/null @@ -1,596 +0,0 @@ - - - {0CF88340-A1A1-4843-9147-EA9CE20FCDA7} - 18.2 - VCL - PTestAssign.dpr - True - Debug - Win64 - 3 - Application - - - true - - - true - Base - true - - - true - Base - true - - - true - Base - true - - - true - Cfg_1 - true - true - - - true - Cfg_1 - true - true - - - true - Base - true - - - true - Cfg_2 - true - true - - - true - Cfg_2 - true - true - - - 2052 - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= - ..\;$(DCC_UnitSearchPath) - System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) - $(BDS)\bin\delphi_PROJECTICON.ico - $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png - PTestAssign - $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png - .\$(Platform)\$(Config) - .\$(Platform)\$(Config) - false - false - false - false - false - - - true - 1033 - Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) - DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;svnui;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;svn;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) - $(BDS)\bin\default_app.manifest - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= - Debug - - - Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) - Debug - true - $(BDS)\bin\default_app.manifest - 1033 - DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) - - - DEBUG;$(DCC_Define) - true - false - true - true - true - - - true - 1033 - true - true - false - - - true - true - - - false - RELEASE;$(DCC_Define) - 0 - 0 - - - true - 1033 - true - true - - - true - true - - - - MainSource - - -
Form1
- dfm -
- - - Cfg_2 - Base - - - Base - - - Cfg_1 - Base - -
- - Delphi.Personality.12 - Application - - - - PTestAssign.dpr - - - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components - - - - - - PTestAssign.exe - true - - - - - 0 - .dll;.bpl - - - 1 - .dylib - - - Contents\MacOS - 1 - .dylib - - - 1 - .dylib - - - 1 - .dylib - - - - - Contents\Resources - 1 - - - - - classes - 1 - - - - - Contents\MacOS - 0 - - - 1 - - - Contents\MacOS - 1 - - - - - 1 - - - 1 - - - 1 - - - - - res\drawable-xxhdpi - 1 - - - - - library\lib\mips - 1 - - - - - 1 - - - 1 - - - 0 - - - 1 - - - Contents\MacOS - 1 - - - library\lib\armeabi-v7a - 1 - - - 1 - - - - - 0 - - - Contents\MacOS - 1 - .framework - - - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - library\lib\armeabi - 1 - - - - - 0 - - - 1 - - - Contents\MacOS - 1 - - - - - 1 - - - 1 - - - 1 - - - - - res\drawable-normal - 1 - - - - - res\drawable-xhdpi - 1 - - - - - res\drawable-large - 1 - - - - - 1 - - - 1 - - - 1 - - - - - Assets - 1 - - - Assets - 1 - - - - - ..\ - 1 - - - ..\ - 1 - - - - - res\drawable-hdpi - 1 - - - - - library\lib\armeabi-v7a - 1 - - - - - Contents - 1 - - - - - ..\ - 1 - - - - - Assets - 1 - - - Assets - 1 - - - - - 1 - - - 1 - - - 1 - - - - - res\values - 1 - - - - - res\drawable-small - 1 - - - - - res\drawable - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - - - res\drawable - 1 - - - - - 0 - - - 0 - - - Contents\Resources\StartUp\ - 0 - - - 0 - - - 0 - - - 0 - - - - - library\lib\armeabi-v7a - 1 - - - - - 0 - .bpl - - - 1 - .dylib - - - Contents\MacOS - 1 - .dylib - - - 1 - .dylib - - - 1 - .dylib - - - - - res\drawable-mdpi - 1 - - - - - res\drawable-xlarge - 1 - - - - - res\drawable-ldpi - 1 - - - - - 1 - - - 1 - - - - - - - - - - - - - True - True - - - 12 - - - - -
diff --git a/example2/PTestAssign.res b/example2/PTestAssign.res deleted file mode 100644 index 3c308e67f14106bf90e6dd79eefd7c596e5bea43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59416 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 diff --git a/example2/TestAssign.dfm b/example2/TestAssign.dfm deleted file mode 100644 index c2cc466..0000000 --- a/example2/TestAssign.dfm +++ /dev/null @@ -1,26 +0,0 @@ -object Form1: TForm1 - Left = 0 - Top = 0 - Caption = 'Form1' - ClientHeight = 243 - ClientWidth = 472 - Color = clBtnFace - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -11 - Font.Name = 'Tahoma' - Font.Style = [] - OldCreateOrder = False - OnCreate = FormCreate - PixelsPerInch = 96 - TextHeight = 13 - object Button1: TButton - Left = 200 - Top = 184 - Width = 161 - Height = 25 - Caption = 'Save/Load Stream Time' - TabOrder = 0 - OnClick = Button1Click - end -end diff --git a/example2/TestAssign.pas b/example2/TestAssign.pas deleted file mode 100644 index 29bb7b2..0000000 --- a/example2/TestAssign.pas +++ /dev/null @@ -1,130 +0,0 @@ -unit TestAssign; - -interface - -uses - Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, - Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, test; - -type - TForm1 = class(TForm) - Button1: TButton; - procedure FormCreate(Sender: TObject); - procedure Button1Click(Sender: TObject); - private - { Private declarations } - FStruct1: TTestStruct; - FStruct2: TTestStruct; - - FPerson1: TPerson; - FPerson2: TPerson; - procedure InitData; - public - { Public declarations } - end; - -var - Form1: TForm1; - -implementation - -uses - pbOutput, pbInput, System.Diagnostics, System.TypInfo; - -{$R *.dfm} - -procedure TForm1.Button1Click(Sender: TObject); -var - lvWatch: TStopwatch; - lvStream: TMemoryStream; - I: Integer; -begin - FStruct2.Assign(FStruct1); - Assert(FStruct1.ToString = FStruct2.ToString, 'Assign Fail!'); - - lvStream := TMemoryStream.Create; - lvWatch := TStopWatch.StartNew; - for I := 0 to 100000 do - begin - lvStream.Clear; - FStruct1.SaveToStream(lvStream); - end; - lvWatch.Stop; - ShowMessage(Format('Save: %d', [lvWatch.ElapsedMilliseconds])); - - lvWatch.Reset; - lvWatch.Start; - for I := 0 to 100000 do - begin - FStruct1.LoadFromStream(lvStream); - end; - lvWatch.Stop; - ShowMessage(Format('Load: %d', [lvWatch.ElapsedMilliseconds])); - -//test Persion - lvWatch.Reset; - lvWatch.Start; - for I := 0 to 100000 do - begin - lvStream.Clear; - FPerson1.SaveToStream(lvStream); - end; - lvWatch.Stop; - ShowMessage(Format('Save: %d', [lvWatch.ElapsedMilliseconds])); - - lvStream.Free; -end; - -procedure TForm1.FormCreate(Sender: TObject); -begin - InitData; -end; - -procedure TForm1.InitData; -var - ver1, ver2: TVersionInfo; - ph1, ph2: TPhoneNumber; -begin - FStruct1 := TTestStruct.Create; - FStruct2 := TTestStruct.Create; - - FStruct1.aint := 2; - FStruct1.aword := 3; - FStruct1.bword := 5; - - ver1 := TVersionInfo.Create; - ver1.majorVersion := 1; - ver1.minorVersion := 2; - ver1.realease := 3; - ver1.build := 4; - FStruct1.lstVerList.Add(ver1); - - ver2 := TVersionInfo.Create; - ver2.majorVersion := 5; - ver2.minorVersion := 6; - ver2.realease := 7; - ver2.build := 8; - FStruct1.lstVerList.Add(ver2); - - FStruct1.arrIntList.Add(10); - FStruct1.arrIntList.Add(15); - FStruct1.arrStrList.Add('123'); - FStruct1.arrStrList.Add('456'); - - //TPersion - FPerson1 := TPerson.Create; - FPerson1.Name := 'Marat Shaymardanov'; - FPerson1.Id := 1; - FPerson1.Email := 'marat-sh@sibmail.com'; - ph1 := TPhoneNumber.Create; - ph1.ptype := TPhoneType.HOME; - ph1.number := '+7 392 224 3699'; - FPerson1.phoneList.Add(ph1); - - ph2 := TPhoneNumber.Create; - ph2.ptype := TPhoneType.MOBILE; - ph2.number := '+7 913 826 2144'; - FPerson1.phoneList.Add(ph2); -end; - -end. diff --git a/example2/test1.proto b/example2/test1.proto deleted file mode 100644 index 0fedd5f..0000000 --- a/example2/test1.proto +++ /dev/null @@ -1,43 +0,0 @@ -syntax = "proto3"; - -package test1; - -message TestStruct { - int32 aint = 1; - uint32 aword = 2; - uint32 bword = 3; - uint32 abyte = 4; - double dt = 5; - bool b = 6; - string str = 7; - repeated int32 arrInt = 8; - repeated string arrStr = 9; - repeated VersionInfo lstVer = 10; - VersionInfo ver = 11; -} - -message VersionInfo { - uint32 majorVersion = 1; - uint32 minorVersion = 2; - uint32 realease = 3; - uint32 build = 4; - } - -message Person { - required string name = 1; - required int32 id = 2; - optional string email = 3; - - enum PhoneType { - MOBILE = 0; - HOME = 1; - WORK = 2; - } - - message PhoneNumber { - required string number = 1; - optional PhoneType ptype = 2 [default = HOME]; - } - - repeated PhoneNumber phone = 4; -} \ No newline at end of file diff --git a/example2/test2.proto b/example2/test2.proto deleted file mode 100644 index d31f996..0000000 --- a/example2/test2.proto +++ /dev/null @@ -1,10 +0,0 @@ -syntax = "proto3"; - -package test2; - -message VersionInfo2 { - uint32 majorVersion = 1; - uint32 minorVersion = 2; - uint32 realease = 3; - uint32 build = 4; - } \ No newline at end of file diff --git a/example2_with_Generator/ProjectExample2.dproj b/example2_with_Generator/ProjectExample2.dproj index aba4bda..4d78227 100644 --- a/example2_with_Generator/ProjectExample2.dproj +++ b/example2_with_Generator/ProjectExample2.dproj @@ -1,7 +1,7 @@  {C4E7CF2C-F7EA-44F7-A60A-3B87C1E6EA33} - 18.1 + 18.2 VCL ProjectExample2.dpr True @@ -61,14 +61,18 @@ false + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png $(BDS)\bin\default_app.manifest 1033 true DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;svnui;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;svn;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FixInsight_10;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;madExcept_;VirtualTreesR;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;madBasic_;TeeDB;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;madDisAsm_;DBXSybaseASADriver;CustomIPTransport;vcldsnap;CodeSiteExpressPkg;bindcomp;appanalytics;fgx;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) - CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName) Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;VirtualTreesR;FireDACMSAccDriver;FireDACInfxDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;ibxbindings;fmxobj;FireDACDSDriver;soapmidas;rtl;vclwinx;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;dsnapxml;dbrtl;FireDACMongoDBDriver;IndyProtocols;inetdbxpress;fmxase;$(DCC_UsePackage) @@ -80,6 +84,8 @@ true + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName) + Debug true true true @@ -129,34 +135,19 @@ Microsoft Office XP Sample Automation Server Wrapper Components - + ProjectExample2.exe true - - - 0 - .dll;.bpl - + 1 - .dylib - - - Contents\MacOS - 1 - .dylib 1 - .dylib - - - 1 - .dylib @@ -208,19 +199,22 @@ + + 1 + + + 1 + 0 - + 1 Contents\MacOS 1 - - 1 - library\lib\armeabi-v7a 1 @@ -239,6 +233,14 @@ .framework + + + 1 + + + 1 + + 1 @@ -271,12 +273,7 @@ 1 - - - library\lib\x86 - 1 - - + 1 @@ -357,13 +354,23 @@ 1 + + + Assets + 1 + + + Assets + 1 + + - ../ + ..\ 1 - ../ + ..\ 1 @@ -387,7 +394,17 @@ - ../ + ..\ + 1 + + + + + Assets + 1 + + + Assets 1 @@ -510,18 +527,34 @@ 1 - + + + 0 + .dll;.bpl + 1 + .dylib + + + Contents\MacOS + 1 + .dylib 1 + .dylib + + + 1 + .dylib + diff --git a/example2_with_Generator/test1.pas b/example2_with_Generator/test1.pas index 1568e77..66b3910 100644 --- a/example2_with_Generator/test1.pas +++ b/example2_with_Generator/test1.pas @@ -40,7 +40,6 @@ TTestMsg0 = class(TAbstractProtoBufClass) constructor Create; override; destructor Destroy; override; - property Field1:integer read FField1 write FField1; property Field2:Int64 read FField2 write FField2; end; @@ -52,7 +51,6 @@ TTestNested1 = class(TAbstractProtoBufClass) function LoadSingleFieldFromBuf(ProtoBuf: TProtoBufInput; FieldNumber: integer; WireType: integer): Boolean; override; procedure SaveFieldsToBuf(ProtoBuf: TProtoBufOutput); override; public - property Field1:integer read FField1 write FField1; end; @@ -86,7 +84,6 @@ TTestMsg1 = class(TAbstractProtoBufClass) constructor Create; override; destructor Destroy; override; - property DefField1:integer read FDefField1 write FDefField1 default 2; property DefField2:Int64 read FDefField2 write FDefField2 default -1; property DefField3:string read FDefField3 write FDefField3; // default 'yes'; @@ -124,7 +121,6 @@ TTestMsg1Extension1 = class(TTestMsg1) function LoadSingleFieldFromBuf(ProtoBuf: TProtoBufInput; FieldNumber: integer; WireType: integer): Boolean; override; procedure SaveFieldsToBuf(ProtoBuf: TProtoBufOutput); override; public - property field_name_test_1:integer read Ffield_name_test_1 write Ffield_name_test_1; property field_Name_test_2:integer read Ffield_Name_test_2 write Ffield_Name_test_2; end; @@ -152,7 +148,7 @@ function TTestMsg0.LoadSingleFieldFromBuf(ProtoBuf: TProtoBufInput; FieldNumber: Result := inherited LoadSingleFieldFromBuf(ProtoBuf, FieldNumber, WireType); if Result then exit; - case fieldNumber of + case FieldNumber of 1: begin FField1 := ProtoBuf.readInt32; @@ -181,7 +177,7 @@ function TTestNested1.LoadSingleFieldFromBuf(ProtoBuf: TProtoBufInput; FieldNumb Result := inherited LoadSingleFieldFromBuf(ProtoBuf, FieldNumber, WireType); if Result then exit; - case fieldNumber of + case FieldNumber of 1: begin FField1 := ProtoBuf.readInt32; @@ -238,7 +234,7 @@ function TTestMsg1.LoadSingleFieldFromBuf(ProtoBuf: TProtoBufInput; FieldNumber: Result := inherited LoadSingleFieldFromBuf(ProtoBuf, FieldNumber, WireType); if Result then exit; - case fieldNumber of + case FieldNumber of 1: begin FDefField1 := ProtoBuf.readInt32; @@ -352,7 +348,7 @@ function TTestMsg1.LoadSingleFieldFromBuf(ProtoBuf: TProtoBufInput; FieldNumber: end; 44: begin - FFieldMArr2List.AddFromBuf(ProtoBuf, fieldNumber); + FFieldMArr2List.AddFromBuf(ProtoBuf, makeTag(FieldNumber, WireType)); Result := True; end; 50: @@ -425,7 +421,7 @@ function TTestMsg1Extension1.LoadSingleFieldFromBuf(ProtoBuf: TProtoBufInput; Fi Result := inherited LoadSingleFieldFromBuf(ProtoBuf, FieldNumber, WireType); if Result then exit; - case fieldNumber of + case FieldNumber of 187: begin Ffield_name_test_1 := ProtoBuf.readInt32; diff --git a/example2_with_Generator/ufmMain.dfm b/example2_with_Generator/ufmMain.dfm index 40da586..21c3b25 100644 --- a/example2_with_Generator/ufmMain.dfm +++ b/example2_with_Generator/ufmMain.dfm @@ -1,7 +1,7 @@ object Form15: TForm15 Left = 0 Top = 0 - Caption = 'Form15' + Caption = 'Example2' ClientHeight = 250 ClientWidth = 430 Color = clBtnFace @@ -18,18 +18,19 @@ object Form15: TForm15 Left = 16 Top = 8 Width = 395 - Height = 130 + Height = 143 Caption = - 'First, compile and run ProtoBufGenerator.exe'#13#10'Choose TestImport1' + - '.proto file and output folder - "example2_with_Generator"'#13#10'Press' + - ' Generate button.'#13#10'Choose Test1.proto file'#13#10'Press Generate butto' + - 'n'#13#10'Now you get 2 new files in this project directory - TestImpor' + - 't1.pas and Test1.pas.'#13#10#13#10'Or - you can use for test pre-loaded fi' + - 'les.'#13#10#13#10'See in OnClick event handlers how to use generated files' + '1. Compile and run ProtoBufGenerator.exe'#13#10#13#10'2. Choose/Drag TestI' + + 'mport1.proto & Test1.proto file to ProtoBufGenerator.exe'#13#10' Se' + + 't output folder - "example2_with_Generator"'#13#10#13#10'3. Press Generate' + + ' button.'#13#10#13#10'Now you get 2 new files in this project directory - ' + + 'TestImport1.pas and Test1.pas.'#13#10'Or - you can use for test pre-lo' + + 'aded files.'#13#10#13#10'See in OnClick event handlers how to use generate' + + 'd files' end object btnSaveToPtotoBuf: TButton Left = 72 - Top = 160 + Top = 169 Width = 121 Height = 25 Caption = 'SaveToPtotoBuf' @@ -37,8 +38,8 @@ object Form15: TForm15 OnClick = btnSaveToPtotoBufClick end object btnLoadFromProtoBuf: TButton - Left = 216 - Top = 160 + Left = 224 + Top = 169 Width = 121 Height = 25 Caption = 'LoadFromProtoBuf' From 9846dbd0c9bb78e399cba346331ada89da32b050 Mon Sep 17 00:00:00 2001 From: jinnBlue Date: Sun, 10 Sep 2017 11:31:07 +0800 Subject: [PATCH 4/4] [!] just chose or drag files, can't edit --- Generator/Test/TestGeneratedProtoBufPas.pas | 6 +++--- Generator/Test/TestProtoBuf.pas | 6 +++--- Generator/uProtoBufGenerator.pas | 2 +- Generator/ufmMain.dfm | 10 +++++++++- Generator/ufmMain.pas | 20 ++++++-------------- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Generator/Test/TestGeneratedProtoBufPas.pas b/Generator/Test/TestGeneratedProtoBufPas.pas index 07fefd0..4405ed2 100644 --- a/Generator/Test/TestGeneratedProtoBufPas.pas +++ b/Generator/Test/TestGeneratedProtoBufPas.pas @@ -1,4 +1,4 @@ -unit TestGeneratedProtoBufPas; +unit TestGeneratedProtoBufPas; { Delphi DUnit Test Case @@ -76,7 +76,7 @@ procedure TestTTestMsg1.TestSaveLoadFromBuf; begin FTestMsg1.DefField1 := 1; FTestMsg1.DefField2 := 3; - FTestMsg1.DefField3 := 'as'; + FTestMsg1.DefField3 := 'asôâàóöé'; FTestMsg1.DefField4 := -2.5; FTestMsg1.DefField5 := True; FTestMsg1.DefField6 := TEnumG0.g2; @@ -85,7 +85,7 @@ procedure TestTTestMsg1.TestSaveLoadFromBuf; FTestMsg1.DefField9 := 5.5; FTestMsg1.FieldArr1List.Add(-5); FTestMsg1.FieldArr2List.Add(234); - FTestMsg1.FieldArr3List.Add('asdf?); + FTestMsg1.FieldArr3List.Add('asdfçöóêãøò'); tmp := TTestMsg1.Create; try diff --git a/Generator/Test/TestProtoBuf.pas b/Generator/Test/TestProtoBuf.pas index 6ef7fa1..ef19f92 100644 --- a/Generator/Test/TestProtoBuf.pas +++ b/Generator/Test/TestProtoBuf.pas @@ -1,4 +1,4 @@ -unit TestProtoBuf; +unit TestProtoBuf; { Delphi DUnit Test Case @@ -196,7 +196,7 @@ TLittleEndianCase = record procedure TestProtoBufMethods.TestReadString; const - TEST_string:string = '? '; + TEST_string:string = 'Òåñòîâàÿ ñòðîêà'; TEST_integer = 12345678; TEST_single = 12345.123; TEST_double = 1234567890.123; @@ -316,7 +316,7 @@ TVarintCase = record for i := 0 to 7 do begin t := VarintCases[i]; - // ? ? + // 耦玟囹?蝈耱钼 狍翦? SetLength(buf, t.Size); for j := 1 to t.Size do buf[j] := AnsiChar(t.bytes[j]); diff --git a/Generator/uProtoBufGenerator.pas b/Generator/uProtoBufGenerator.pas index c67115f..4a43f62 100644 --- a/Generator/uProtoBufGenerator.pas +++ b/Generator/uProtoBufGenerator.pas @@ -412,7 +412,7 @@ procedure TProtoBufGenerator.GenerateImplementationSection(Proto: TProtoFile; SL SL.Add(Format(' F%s.Add(T%s(ProtoBuf.readEnum));', [DelphiProp.PropertyName, Prop.PropType])); end else - SL.Add(Format(' F%s.AddFromBuf(ProtoBuf, makeTag(FieldNumber, WireType));', [DelphiProp.PropertyName])); + SL.Add(Format(' F%s.AddFromBuf(ProtoBuf, FieldNumber);', [DelphiProp.PropertyName])); end; SL.Add(' Result := True;'); SL.Add(' end;'); diff --git a/Generator/ufmMain.dfm b/Generator/ufmMain.dfm index 742cb58..91649de 100644 --- a/Generator/ufmMain.dfm +++ b/Generator/ufmMain.dfm @@ -23,9 +23,17 @@ object fmMain: TfmMain Top = 16 Width = 409 Height = 21 + TabStop = False Anchors = [akLeft, akTop, akRight] + Font.Charset = DEFAULT_CHARSET + Font.Color = clGray + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + ParentFont = False + ReadOnly = True TabOrder = 0 - TextHint = 'Choose .proto file' + Text = 'Use "..." Choose .proto files Or Drag files into window~' end object btnOpenProtoFile: TButton Left = 423 diff --git a/Generator/ufmMain.pas b/Generator/ufmMain.pas index b55bdb5..79396d3 100644 --- a/Generator/ufmMain.pas +++ b/Generator/ufmMain.pas @@ -69,9 +69,6 @@ procedure TfmMain.btnGenerateClick(Sender: TObject); I : Integer; Gen: TProtoBufGenerator; begin - if edtProtoFiles.Font.Color = clRed then - Exit; - OutPutDir := edtOutputFolder.Text; if OutPutDir <> '' then ForceDirectories(OutPutDir); @@ -97,15 +94,7 @@ procedure TfmMain.btnOpenProtoFileClick(Sender: TObject); for I := 0 to Pred(FFileCount) do begin FFiles[I] := odProtoFile.Files[I]; - if SameText(ExtractFileExt(FFiles[I]), PROTO) then - begin - edtProtoFiles.Text := edtProtoFiles.Text + ExtractFileName(FFiles[I]) + ','; - end - else - begin - edtProtoFiles.Font.Color := clRed; - edtProtoFiles.Text := Format('Files Type need %s !!!', [PROTO]); - end; + edtProtoFiles.Text := edtProtoFiles.Text + ExtractFileName(FFiles[I]) + ','; end; end; end; @@ -115,7 +104,8 @@ procedure TfmMain.ClearFiles; SetLength(FFiles, 0); FFileCount := 0; edtProtoFiles.Text := ''; - edtProtoFiles.Font.Color := clWindowText; + edtProtoFiles.Font.Color := clGray; + btnGenerate.Enabled := True; end; { Drop Files Action } @@ -123,7 +113,6 @@ procedure TfmMain.FormCreate(Sender: TObject); begin odProtoFile.DefaultFolder := '.\'; odProtoFile.DefaultExtension := PROTO; - odProtoFile.Options := odProtoFile.Options + [fdoAllowMultiSelect]; DragAcceptFiles(Self.Handle, True); end; @@ -156,8 +145,11 @@ procedure TfmMain.WMDropFiles(var Msg: TWMDropFiles); begin edtProtoFiles.Font.Color := clRed; edtProtoFiles.Text := Format('Files Type need %s !!!', [PROTO]); + btnGenerate.Enabled := False; + Exit; end; end; + edtProtoFiles.Font.Color := clBlack; finally Catcher.Free; end;