├── .gitattributes
├── .gitignore
├── AMQP
├── AMQP.groupproj
├── Samples
│ ├── Testbench
│ │ ├── Testbench.dpr
│ │ ├── Testbench.dproj
│ │ ├── Testbench.res
│ │ ├── TestbenchWin.dfm
│ │ └── TestbenchWin.pas
│ └── Threads
│ │ ├── ThreadSample.dfm
│ │ ├── ThreadSample.dpr
│ │ ├── ThreadSample.dproj
│ │ ├── ThreadSample.pas
│ │ ├── ThreadSample.res
│ │ ├── ThreadSampleWin.dfm
│ │ └── ThreadSampleWin.pas
└── Source
│ ├── AMQP.Arguments.pas
│ ├── AMQP.Channel.pas
│ ├── AMQP.Classes.pas
│ ├── AMQP.Connection.pas
│ ├── AMQP.Frame.pas
│ ├── AMQP.Header.pas
│ ├── AMQP.Helper.pas
│ ├── AMQP.IMessageProperties.pas
│ ├── AMQP.Interfaces.pas
│ ├── AMQP.Message.pas
│ ├── AMQP.MessageProperties.pas
│ ├── AMQP.Method.pas
│ ├── AMQP.Payload.pas
│ ├── AMQP.Protocol.pas
│ ├── AMQP.StreamHelper.pas
│ └── AMQP.Types.pas
├── EasyDelphiQ
├── EasyDelphiQ.Classes.pas
├── EasyDelphiQ.DTO.pas
├── EasyDelphiQ.Interfaces.pas
├── EasyDelphiQ.pas
└── Testbench
│ ├── MainWin.dfm
│ ├── MainWin.pas
│ ├── Neas.PowermanApi.Notifications.DTOs.V1.pas
│ ├── QTestbench.dpr
│ ├── QTestbench.dproj
│ ├── QTestbench.res
│ └── Some.namespace.pas
├── JSON
├── DJSON.pas
├── DTO.pas
├── JSON Samples
│ └── Nexus.txt
├── JSON2DTO.pas
├── JSONProject.groupproj
├── Project1.dpr
├── Project1.dproj
├── Sample1.dpr
├── Sample1.dproj
├── Sample1.res
├── Sample1Form.dfm
├── Sample1Form.pas
├── Test
│ ├── Sample1Tests.dpr
│ ├── Sample1Tests.dproj
│ ├── TestJSON.pas
│ └── TestObjects.pas
├── TimeseriesDTO.pas
├── WinHttp_TLB.pas
└── Wizard
│ ├── JSON.bmp
│ ├── JSON.ico
│ ├── JSON.rc
│ ├── JSONDTO.txt
│ ├── JSONDTOExpt.pas
│ ├── JSONDTOWiz.dpk
│ ├── JSONDTOWiz.dproj
│ ├── JSONFile.ico
│ ├── WizardWin.dfm
│ └── WizardWin.pas
├── README.md
└── XPath
├── HtmlParser.pas
├── TestBench
├── HtmlTest.dpr
├── HtmlTest.dproj
├── HtmlTest.res
├── MainWin.dfm
├── MainWin.pas
└── Win32
│ └── Debug
│ └── Download.html
├── UnitTest
├── TestHtmlParser.pas
├── TestLexer.pas
├── TestXPath.pas
├── XPathTests.dpr
├── XPathTests.dproj
└── XPathTests.res
├── XPath EBNF.txt
├── XPath.pas
├── XPathGroup.groupproj
└── XPathLexer.pas
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Disable LF normalization for all files
2 | * -text
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.identcache
2 | *.local
3 | *.dcu
4 | *.stat
5 | *.dsk
6 | JSON/__history/
7 | XPath/UnitTest/Win32/Debug/dunit.ini
8 | XPath/__history/
9 | XPath/TestBench/__history/
10 | XPath/UnitTest/__history/
11 | AMQP/__history/
12 | AMQP/source/__history/
13 | AMQP/Samples/Threads/__history/
14 | AMQP/Samples/Testbench/__history/
15 | EasyDelphiQ/__history/
16 | EasyDelphiQ/Testbench/__history
17 | EasyDelphiQ/Testbench/Win32
18 |
--------------------------------------------------------------------------------
/AMQP/AMQP.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {08B89F4A-51A1-413B-8DBF-5A5C03F9E91C}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Default.Personality.12
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/AMQP/Samples/Testbench/Testbench.dpr:
--------------------------------------------------------------------------------
1 | // JCL_DEBUG_EXPERT_GENERATEJDBG OFF
2 | // JCL_DEBUG_EXPERT_INSERTJDBG OFF
3 | program Testbench;
4 |
5 | uses
6 | Vcl.Forms,
7 | TestbenchWin in 'TestbenchWin.pas' {TestbenchForm},
8 | AMQP.Method in '..\..\Source\AMQP.Method.pas',
9 | AMQP.Types in '..\..\Source\AMQP.Types.pas',
10 | AMQP.Message in '..\..\Source\AMQP.Message.pas',
11 | AMQP.Protocol in '..\..\Source\AMQP.Protocol.pas',
12 | AMQP.Connection in '..\..\Source\AMQP.Connection.pas',
13 | AMQP.Frame in '..\..\Source\AMQP.Frame.pas',
14 | AMQP.Helper in '..\..\Source\AMQP.Helper.pas',
15 | AMQP.Payload in '..\..\Source\AMQP.Payload.pas',
16 | AMQP.MessageProperties in '..\..\Source\AMQP.MessageProperties.pas',
17 | AMQP.Header in '..\..\Source\AMQP.Header.pas',
18 | AMQP.StreamHelper in '..\..\Source\AMQP.StreamHelper.pas',
19 | AMQP.Channel in '..\..\Source\AMQP.Channel.pas',
20 | AMQP.Classes in '..\..\Source\AMQP.Classes.pas',
21 | AMQP.Interfaces in '..\..\Source\AMQP.Interfaces.pas',
22 | AMQP.IMessageProperties in '..\..\Source\AMQP.IMessageProperties.pas',
23 | AMQP.Arguments in '..\..\Source\AMQP.Arguments.pas';
24 |
25 | {$R *.res}
26 |
27 | begin
28 | Application.Initialize;
29 | Application.MainFormOnTaskbar := True;
30 | Application.CreateForm(TTestbenchForm, TestbenchForm);
31 | Application.Run;
32 | end.
33 |
--------------------------------------------------------------------------------
/AMQP/Samples/Testbench/Testbench.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/AMQP/Samples/Testbench/Testbench.res
--------------------------------------------------------------------------------
/AMQP/Samples/Testbench/TestbenchWin.dfm:
--------------------------------------------------------------------------------
1 | object TestbenchForm: TTestbenchForm
2 | Left = 0
3 | Top = 0
4 | Caption = 'AMQP Testbench'
5 | ClientHeight = 821
6 | ClientWidth = 1218
7 | Color = clBtnFace
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -11
11 | Font.Name = 'Tahoma'
12 | Font.Style = []
13 | OldCreateOrder = False
14 | OnCreate = FormCreate
15 | OnDestroy = FormDestroy
16 | DesignSize = (
17 | 1218
18 | 821)
19 | PixelsPerInch = 96
20 | TextHeight = 13
21 | object MemoMessages: TMemo
22 | Left = 8
23 | Top = 629
24 | Width = 897
25 | Height = 184
26 | Anchors = [akLeft, akRight, akBottom]
27 | Color = clBlack
28 | Font.Charset = DEFAULT_CHARSET
29 | Font.Color = clWhite
30 | Font.Height = 18
31 | Font.Name = 'Courier New'
32 | Font.Style = []
33 | ParentFont = False
34 | ScrollBars = ssVertical
35 | TabOrder = 1
36 | end
37 | object ButtonConnect: TButton
38 | Left = 8
39 | Top = 8
40 | Width = 75
41 | Height = 25
42 | Caption = 'Connect'
43 | TabOrder = 0
44 | OnClick = ButtonConnectClick
45 | end
46 | object MemoSent: TMemo
47 | Left = 8
48 | Top = 104
49 | Width = 401
50 | Height = 520
51 | Anchors = [akLeft, akTop, akBottom]
52 | Ctl3D = False
53 | Font.Charset = DEFAULT_CHARSET
54 | Font.Color = clWindowText
55 | Font.Height = 16
56 | Font.Name = 'Courier New'
57 | Font.Style = []
58 | ParentCtl3D = False
59 | ParentFont = False
60 | ScrollBars = ssBoth
61 | TabOrder = 2
62 | end
63 | object MemoReceived: TMemo
64 | Left = 617
65 | Top = 104
66 | Width = 401
67 | Height = 520
68 | Anchors = [akLeft, akTop, akRight, akBottom]
69 | Ctl3D = False
70 | Font.Charset = DEFAULT_CHARSET
71 | Font.Color = clWindowText
72 | Font.Height = 16
73 | Font.Name = 'Courier New'
74 | Font.Style = []
75 | ParentCtl3D = False
76 | ParentFont = False
77 | ScrollBars = ssBoth
78 | TabOrder = 3
79 | end
80 | object MemoSentBytes: TMemo
81 | Left = 415
82 | Top = 104
83 | Width = 196
84 | Height = 519
85 | Anchors = [akLeft, akTop, akBottom]
86 | Color = clGreen
87 | Ctl3D = False
88 | Font.Charset = DEFAULT_CHARSET
89 | Font.Color = clWhite
90 | Font.Height = 16
91 | Font.Name = 'Courier New'
92 | Font.Style = []
93 | ParentCtl3D = False
94 | ParentFont = False
95 | ScrollBars = ssBoth
96 | TabOrder = 4
97 | end
98 | object MemoReceivedBytes: TMemo
99 | Left = 1024
100 | Top = 104
101 | Width = 186
102 | Height = 520
103 | Anchors = [akTop, akRight, akBottom]
104 | Color = clGreen
105 | Ctl3D = False
106 | Font.Charset = DEFAULT_CHARSET
107 | Font.Color = clWhite
108 | Font.Height = 16
109 | Font.Name = 'Courier New'
110 | Font.Style = []
111 | ParentCtl3D = False
112 | ParentFont = False
113 | ScrollBars = ssBoth
114 | TabOrder = 5
115 | end
116 | object ButtonDisconnect: TButton
117 | Left = 8
118 | Top = 39
119 | Width = 75
120 | Height = 25
121 | Caption = 'Disconnect'
122 | TabOrder = 6
123 | OnClick = ButtonDisconnectClick
124 | end
125 | object ButtonPublishRed: TButton
126 | Left = 600
127 | Top = 8
128 | Width = 75
129 | Height = 25
130 | Caption = 'Publish Red'
131 | TabOrder = 7
132 | OnClick = ButtonPublishRedClick
133 | end
134 | object ButtonOpenChannel: TButton
135 | Left = 95
136 | Top = 8
137 | Width = 90
138 | Height = 25
139 | Caption = 'Open Channel'
140 | TabOrder = 8
141 | OnClick = ButtonOpenChannelClick
142 | end
143 | object ButtonCloseChannel: TButton
144 | Left = 95
145 | Top = 40
146 | Width = 90
147 | Height = 25
148 | Caption = 'Close Channel'
149 | TabOrder = 9
150 | OnClick = ButtonCloseChannelClick
151 | end
152 | object ButtonExchangeDeclare: TButton
153 | Left = 199
154 | Top = 8
155 | Width = 106
156 | Height = 25
157 | Caption = 'Declare Exchange'
158 | TabOrder = 10
159 | OnClick = ButtonExchangeDeclareClick
160 | end
161 | object ButtonExchangeDelete: TButton
162 | Left = 199
163 | Top = 40
164 | Width = 106
165 | Height = 25
166 | Caption = 'Delete Exchange'
167 | TabOrder = 11
168 | OnClick = ButtonExchangeDeleteClick
169 | end
170 | object ButtonQueueDeclare: TButton
171 | Left = 322
172 | Top = 8
173 | Width = 87
174 | Height = 25
175 | Caption = 'Declare Queue'
176 | TabOrder = 12
177 | OnClick = ButtonQueueDeclareClick
178 | end
179 | object ButtonQueueDelete: TButton
180 | Left = 322
181 | Top = 39
182 | Width = 87
183 | Height = 25
184 | Caption = 'Delete Queue'
185 | TabOrder = 13
186 | OnClick = ButtonQueueDeleteClick
187 | end
188 | object ButtonQueueBind: TButton
189 | Left = 415
190 | Top = 8
191 | Width = 82
192 | Height = 25
193 | Caption = 'Bind Queue'
194 | TabOrder = 14
195 | OnClick = ButtonQueueBindClick
196 | end
197 | object ButtonQueueUnbind: TButton
198 | Left = 415
199 | Top = 39
200 | Width = 82
201 | Height = 25
202 | Caption = 'Unbind queue'
203 | TabOrder = 15
204 | OnClick = ButtonQueueUnbindClick
205 | end
206 | object ButtonPublishBlue: TButton
207 | Left = 600
208 | Top = 39
209 | Width = 75
210 | Height = 25
211 | Caption = 'Publish Blue'
212 | TabOrder = 16
213 | OnClick = ButtonPublishBlueClick
214 | end
215 | object ButtonGetRed: TButton
216 | Left = 696
217 | Top = 9
218 | Width = 75
219 | Height = 25
220 | Caption = 'Get red'
221 | TabOrder = 17
222 | OnClick = ButtonGetRedClick
223 | end
224 | object ButtonGetBlue: TButton
225 | Left = 696
226 | Top = 40
227 | Width = 75
228 | Height = 25
229 | Caption = 'Get Blue'
230 | TabOrder = 18
231 | OnClick = ButtonGetBlueClick
232 | end
233 | object ButtonConfirmSelect: TButton
234 | Left = 864
235 | Top = 8
236 | Width = 89
237 | Height = 25
238 | Caption = 'Confirm Select'
239 | TabOrder = 19
240 | OnClick = ButtonConfirmSelectClick
241 | end
242 | object ButtonConsumeBlue: TButton
243 | Left = 976
244 | Top = 8
245 | Width = 91
246 | Height = 25
247 | Caption = 'Consume Blue'
248 | TabOrder = 20
249 | OnClick = ButtonConsumeBlueClick
250 | end
251 | object Panel1: TPanel
252 | Left = 911
253 | Top = 630
254 | Width = 299
255 | Height = 183
256 | Anchors = [akRight, akBottom]
257 | BorderStyle = bsSingle
258 | Caption = 'Panel1'
259 | Ctl3D = False
260 | ParentCtl3D = False
261 | ShowCaption = False
262 | TabOrder = 21
263 | object LabelStatus: TLabel
264 | Left = 8
265 | Top = 8
266 | Width = 56
267 | Height = 13
268 | Caption = 'LabelStatus'
269 | end
270 | end
271 | object ButtonPurgeRed: TButton
272 | Left = 503
273 | Top = 8
274 | Width = 75
275 | Height = 25
276 | Caption = 'Purge Red'
277 | TabOrder = 22
278 | OnClick = ButtonPurgeRedClick
279 | end
280 | object ButtonCancelBlue: TButton
281 | Left = 976
282 | Top = 40
283 | Width = 91
284 | Height = 25
285 | Caption = 'Cancel Blue'
286 | TabOrder = 23
287 | OnClick = ButtonCancelBlueClick
288 | end
289 | object ButtonReject: TButton
290 | Left = 777
291 | Top = 9
292 | Width = 75
293 | Height = 25
294 | Caption = 'Reject red'
295 | TabOrder = 24
296 | OnClick = ButtonRejectClick
297 | end
298 | object ButtonThreadConsume: TButton
299 | Left = 1073
300 | Top = 8
301 | Width = 96
302 | Height = 25
303 | Caption = 'Consume Thread'
304 | TabOrder = 25
305 | OnClick = ButtonThreadConsumeClick
306 | end
307 | object ButtonCancelRed: TButton
308 | Left = 1073
309 | Top = 40
310 | Width = 96
311 | Height = 25
312 | Caption = 'Cancel Red'
313 | TabOrder = 26
314 | OnClick = ButtonCancelRedClick
315 | end
316 | object ButtonBigExchange: TButton
317 | Left = 199
318 | Top = 71
319 | Width = 106
320 | Height = 25
321 | Caption = 'Declare Big Exchange'
322 | TabOrder = 27
323 | OnClick = ButtonBigExchangeClick
324 | end
325 | object Button1: TButton
326 | Left = 322
327 | Top = 70
328 | Width = 87
329 | Height = 25
330 | Caption = 'Declare Big Queue'
331 | TabOrder = 28
332 | OnClick = Button1Click
333 | end
334 | object Button2: TButton
335 | Left = 415
336 | Top = 70
337 | Width = 82
338 | Height = 25
339 | Caption = 'Bind big queue'
340 | TabOrder = 29
341 | OnClick = Button2Click
342 | end
343 | object Button3: TButton
344 | Left = 600
345 | Top = 70
346 | Width = 75
347 | Height = 25
348 | Caption = 'Publish big'
349 | TabOrder = 30
350 | OnClick = Button3Click
351 | end
352 | object Button4: TButton
353 | Left = 696
354 | Top = 71
355 | Width = 75
356 | Height = 25
357 | Caption = 'Get big'
358 | TabOrder = 31
359 | OnClick = Button4Click
360 | end
361 | object Timer1: TTimer
362 | Interval = 200
363 | OnTimer = Timer1Timer
364 | Left = 1167
365 | Top = 613
366 | end
367 | end
368 |
--------------------------------------------------------------------------------
/AMQP/Samples/Threads/ThreadSample.dfm:
--------------------------------------------------------------------------------
1 | object Form1: TForm1
2 | Left = 0
3 | Top = 0
4 | Caption = 'Form1'
5 | ClientHeight = 337
6 | ClientWidth = 635
7 | Color = clBtnFace
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -11
11 | Font.Name = 'Tahoma'
12 | Font.Style = []
13 | OldCreateOrder = False
14 | PixelsPerInch = 96
15 | TextHeight = 13
16 | end
17 |
--------------------------------------------------------------------------------
/AMQP/Samples/Threads/ThreadSample.dpr:
--------------------------------------------------------------------------------
1 | // JCL_DEBUG_EXPERT_GENERATEJDBG OFF
2 | // JCL_DEBUG_EXPERT_INSERTJDBG OFF
3 | program ThreadSample;
4 |
5 | uses
6 | Vcl.Forms,
7 | ThreadSampleWin in 'ThreadSampleWin.pas' {ThreadSampleForm},
8 | AMQP.Channel in '..\..\Source\AMQP.Channel.pas',
9 | AMQP.Classes in '..\..\Source\AMQP.Classes.pas',
10 | AMQP.Connection in '..\..\Source\AMQP.Connection.pas',
11 | AMQP.Frame in '..\..\Source\AMQP.Frame.pas',
12 | AMQP.Header in '..\..\Source\AMQP.Header.pas',
13 | AMQP.Helper in '..\..\Source\AMQP.Helper.pas',
14 | AMQP.Interfaces in '..\..\Source\AMQP.Interfaces.pas',
15 | AMQP.Message in '..\..\Source\AMQP.Message.pas',
16 | AMQP.MessageProperties in '..\..\Source\AMQP.MessageProperties.pas',
17 | AMQP.Method in '..\..\Source\AMQP.Method.pas',
18 | AMQP.Payload in '..\..\Source\AMQP.Payload.pas',
19 | AMQP.Protocol in '..\..\Source\AMQP.Protocol.pas',
20 | AMQP.StreamHelper in '..\..\Source\AMQP.StreamHelper.pas',
21 | AMQP.Types in '..\..\Source\AMQP.Types.pas',
22 | AMQP.IMessageProperties in '..\..\Source\AMQP.IMessageProperties.pas',
23 | AMQP.Arguments in '..\..\Source\AMQP.Arguments.pas';
24 |
25 | {$R *.res}
26 |
27 | begin
28 | Application.Initialize;
29 | Application.MainFormOnTaskbar := True;
30 | Application.CreateForm(TThreadSampleForm, ThreadSampleForm);
31 | Application.Run;
32 | end.
33 |
--------------------------------------------------------------------------------
/AMQP/Samples/Threads/ThreadSample.pas:
--------------------------------------------------------------------------------
1 | unit ThreadSample;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
8 |
9 | type
10 | TForm1 = class(TForm)
11 | private
12 | { Private declarations }
13 | public
14 | { Public declarations }
15 | end;
16 |
17 | var
18 | Form1: TForm1;
19 |
20 | implementation
21 |
22 | {$R *.dfm}
23 |
24 | end.
25 |
--------------------------------------------------------------------------------
/AMQP/Samples/Threads/ThreadSample.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/AMQP/Samples/Threads/ThreadSample.res
--------------------------------------------------------------------------------
/AMQP/Samples/Threads/ThreadSampleWin.dfm:
--------------------------------------------------------------------------------
1 | object ThreadSampleForm: TThreadSampleForm
2 | Left = 0
3 | Top = 0
4 | Caption = 'Thread sample'
5 | ClientHeight = 433
6 | ClientWidth = 789
7 | Color = clBtnFace
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -11
11 | Font.Name = 'Tahoma'
12 | Font.Style = []
13 | OldCreateOrder = False
14 | OnClose = FormClose
15 | OnShow = FormShow
16 | DesignSize = (
17 | 789
18 | 433)
19 | PixelsPerInch = 96
20 | TextHeight = 13
21 | object Label1: TLabel
22 | Left = 96
23 | Top = 8
24 | Width = 72
25 | Height = 13
26 | Caption = 'Message count'
27 | end
28 | object Label2: TLabel
29 | Left = 192
30 | Top = 8
31 | Width = 38
32 | Height = 13
33 | Caption = 'Interval'
34 | end
35 | object MemoConsumer2: TMemo
36 | Left = 537
37 | Top = 72
38 | Width = 244
39 | Height = 353
40 | Anchors = [akTop, akRight, akBottom]
41 | ScrollBars = ssBoth
42 | TabOrder = 0
43 | end
44 | object MemoProducer: TMemo
45 | Left = 8
46 | Top = 72
47 | Width = 244
48 | Height = 353
49 | Anchors = [akLeft, akTop, akBottom]
50 | ScrollBars = ssBoth
51 | TabOrder = 1
52 | end
53 | object ButtonStartConsumer2: TButton
54 | Left = 537
55 | Top = 8
56 | Width = 75
57 | Height = 25
58 | Anchors = [akTop, akRight]
59 | Caption = 'Consume'
60 | TabOrder = 2
61 | OnClick = ButtonStartConsumer2Click
62 | end
63 | object ButtonStartProducer: TButton
64 | Left = 8
65 | Top = 9
66 | Width = 75
67 | Height = 25
68 | Caption = 'Produce'
69 | TabOrder = 3
70 | OnClick = ButtonStartProducerClick
71 | end
72 | object ButtonStopProducer: TButton
73 | Left = 8
74 | Top = 40
75 | Width = 75
76 | Height = 25
77 | Caption = 'Stop'
78 | TabOrder = 4
79 | OnClick = ButtonStopProducerClick
80 | end
81 | object ButtonStopConsumer2: TButton
82 | Left = 537
83 | Top = 41
84 | Width = 75
85 | Height = 25
86 | Anchors = [akTop, akRight]
87 | Caption = 'Stop'
88 | TabOrder = 5
89 | OnClick = ButtonStopConsumer2Click
90 | end
91 | object SpinEditCount: TSpinEdit
92 | Left = 97
93 | Top = 28
94 | Width = 64
95 | Height = 22
96 | MaxValue = 0
97 | MinValue = 0
98 | TabOrder = 6
99 | Value = 100
100 | end
101 | object SpinEditInterval: TSpinEdit
102 | Left = 188
103 | Top = 28
104 | Width = 64
105 | Height = 22
106 | MaxValue = 0
107 | MinValue = 0
108 | TabOrder = 7
109 | Value = 100
110 | end
111 | object MemoConsumer1: TMemo
112 | Left = 287
113 | Top = 72
114 | Width = 244
115 | Height = 353
116 | Anchors = [akTop, akRight, akBottom]
117 | ScrollBars = ssBoth
118 | TabOrder = 8
119 | end
120 | object ButtonStartConsumer1: TButton
121 | Left = 287
122 | Top = 8
123 | Width = 75
124 | Height = 25
125 | Anchors = [akTop, akRight]
126 | Caption = 'Consume'
127 | TabOrder = 9
128 | OnClick = ButtonStartConsumer1Click
129 | end
130 | object ButtonStopConsumer1: TButton
131 | Left = 287
132 | Top = 41
133 | Width = 75
134 | Height = 25
135 | Anchors = [akTop, akRight]
136 | Caption = 'Stop'
137 | TabOrder = 10
138 | OnClick = ButtonStopConsumer1Click
139 | end
140 | end
141 |
--------------------------------------------------------------------------------
/AMQP/Samples/Threads/ThreadSampleWin.pas:
--------------------------------------------------------------------------------
1 | unit ThreadSampleWin;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.StdCtrls,
7 | Vcl.Samples.Spin, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, AMQP.Connection, AMQP.Interfaces, AMQP.Classes;
8 |
9 | type
10 | TProducerThread = Class(TThread)
11 | Strict Private
12 | FAMQP: TAMQPConnection;
13 | FMaxWork: Integer;
14 | FSleepMS: Integer;
15 | Procedure WriteLine( Text: String );
16 | Protected
17 | Procedure Execute; Override;
18 | Constructor Create( AAMQP: TAMQPConnection; AMaxWork, ASleepMS: Integer ); Reintroduce;
19 | End;
20 |
21 | TConsumerThread = Class(TThread)
22 | Strict Private
23 | FAMQP: TAMQPConnection;
24 | FChannel: IAMQPChannel;
25 | FMemo: TMemo;
26 | Procedure WriteLine( Text: String );
27 | Protected
28 | Procedure TerminatedSet; Override;
29 | Procedure Execute; Override;
30 | Constructor Create( AAMQP: TAMQPConnection; AMemo: TMemo ); Reintroduce;
31 | End;
32 |
33 | TThreadSampleForm = class(TForm)
34 | MemoConsumer2: TMemo;
35 | MemoProducer: TMemo;
36 | ButtonStartConsumer2: TButton;
37 | ButtonStartProducer: TButton;
38 | ButtonStopProducer: TButton;
39 | ButtonStopConsumer2: TButton;
40 | SpinEditCount: TSpinEdit;
41 | SpinEditInterval: TSpinEdit;
42 | Label1: TLabel;
43 | Label2: TLabel;
44 | MemoConsumer1: TMemo;
45 | ButtonStartConsumer1: TButton;
46 | ButtonStopConsumer1: TButton;
47 | procedure FormShow(Sender: TObject);
48 | procedure FormClose(Sender: TObject; var Action: TCloseAction);
49 | procedure ButtonStartProducerClick(Sender: TObject);
50 | procedure ButtonStopProducerClick(Sender: TObject);
51 | procedure ButtonStartConsumer2Click(Sender: TObject);
52 | procedure ButtonStopConsumer2Click(Sender: TObject);
53 | procedure ButtonStartConsumer1Click(Sender: TObject);
54 | procedure ButtonStopConsumer1Click(Sender: TObject);
55 | private
56 | { Private declarations }
57 | public
58 | AMQP: TAMQPConnection;
59 | Producer: TProducerThread;
60 | Consumer1: TConsumerThread;
61 | Consumer2: TConsumerThread;
62 | end;
63 |
64 | var
65 | ThreadSampleForm: TThreadSampleForm;
66 |
67 | implementation
68 |
69 | Uses
70 | AMQP.Message, AMQP.StreamHelper;
71 |
72 | {$R *.dfm}
73 |
74 | procedure TThreadSampleForm.ButtonStartConsumer1Click(Sender: TObject);
75 | begin
76 | ButtonStopConsumer1.Click;
77 | Consumer1 := TConsumerThread.Create( AMQP, MemoConsumer1 );
78 | end;
79 |
80 | procedure TThreadSampleForm.ButtonStartConsumer2Click(Sender: TObject);
81 | begin
82 | ButtonStopConsumer2.Click;
83 | Consumer2 := TConsumerThread.Create( AMQP, MemoConsumer2 );
84 | end;
85 |
86 | procedure TThreadSampleForm.ButtonStartProducerClick(Sender: TObject);
87 | begin
88 | ButtonStopProducer.Click;
89 | Producer := TProducerThread.Create( AMQP, SpinEditCount.Value, SpinEditInterval.Value );
90 | end;
91 |
92 | procedure TThreadSampleForm.ButtonStopConsumer1Click(Sender: TObject);
93 | begin
94 | If Consumer1 <> nil then
95 | Consumer1.Free;
96 | Consumer1 := nil;
97 | end;
98 |
99 | procedure TThreadSampleForm.ButtonStopConsumer2Click(Sender: TObject);
100 | begin
101 | If Consumer2 <> nil then
102 | Consumer2.Free;
103 | Consumer2 := nil;
104 | end;
105 |
106 | procedure TThreadSampleForm.ButtonStopProducerClick(Sender: TObject);
107 | begin
108 | If Producer <> nil then
109 | Producer.Free;
110 | Producer := nil;
111 | end;
112 |
113 | procedure TThreadSampleForm.FormClose(Sender: TObject; var Action: TCloseAction);
114 | begin
115 | AMQP.Free;
116 | end;
117 |
118 | procedure TThreadSampleForm.FormShow(Sender: TObject);
119 | var
120 | Channel: IAMQPChannel;
121 | begin
122 | Producer := nil;
123 | Consumer1 := nil;
124 | Consumer2 := nil;
125 | AMQP := TAMQPConnection.Create;
126 | AMQP.HeartbeatSecs := 120;
127 | AMQP.Host := 'localhost';
128 | AMQP.Port := 5672;
129 | AMQP.VirtualHost := '/';
130 | AMQP.Username := 'TestUser';
131 | AMQP.Password := 'password';
132 | AMQP.Connect;
133 | Channel := AMQP.OpenChannel;
134 | Channel.ExchangeDeclare( 'Work', 'direct' );
135 | Channel.QueueDeclare( 'WorkQueue' );
136 | Channel.QueueBind( 'WorkQueue', 'Work', 'work.unit' );
137 | end;
138 |
139 | { TConsumerThread }
140 |
141 | constructor TConsumerThread.Create(AAMQP: TAMQPConnection; AMemo: TMemo);
142 | begin
143 | FAMQP := AAMQP;
144 | FMemo := AMemo;
145 | inherited Create;
146 | end;
147 |
148 | procedure TConsumerThread.Execute;
149 | var
150 | Queue : TAMQPMessageQueue;
151 | Msg : TAMQPMessage;
152 | begin
153 | WriteLine( 'Thread starting' );
154 | NameThreadForDebugging( 'ConsumerThread' );
155 | Queue := TAMQPMessageQueue.Create;
156 | FChannel := FAMQP.OpenChannel;
157 | Try
158 | FChannel.BasicConsume( Queue, 'WorkQueue', 'consumer' );
159 | Repeat
160 | Msg := Queue.Get;
161 | if Msg = nil then
162 | Terminate;
163 | if not Terminated then
164 | Begin
165 | WriteLine( 'Consumed: ' + Msg.Body.AsString[ TEncoding.ASCII ] );
166 | Msg.Ack;
167 | Msg.Free;
168 | End;
169 | Until Terminated;
170 | Finally
171 | FChannel := nil;
172 | Queue.Free;
173 | End;
174 | WriteLine( 'Thread stopped' );
175 | end;
176 |
177 | procedure TConsumerThread.TerminatedSet;
178 | begin
179 | inherited;
180 | if FChannel.State = cOpen then
181 | FChannel.Close;
182 | end;
183 |
184 | procedure TConsumerThread.WriteLine(Text: String);
185 | begin
186 | Queue( Procedure
187 | Begin
188 | FMemo.Lines.Add( Text );
189 | End );
190 | end;
191 |
192 | { TProducerThread }
193 |
194 | constructor TProducerThread.Create(AAMQP: TAMQPConnection; AMaxWork, ASleepMS: Integer);
195 | begin
196 | FAMQP := AAMQP;
197 | FMaxWork := AMaxWork;
198 | FSleepMS := ASleepMS;
199 | inherited Create;
200 | end;
201 |
202 | procedure TProducerThread.Execute;
203 | var
204 | Channel : IAMQPChannel;
205 | Work : String;
206 | Counter : Integer;
207 | begin
208 | WriteLine( 'Thread starting' );
209 | NameThreadForDebugging( 'ProducerThread' );
210 | Counter := 1;
211 | Channel := FAMQP.OpenChannel;
212 | Try
213 | Repeat
214 | Work := 'Work unit ' + Counter.ToString;
215 | WriteLine( 'Produced: ' + Work );
216 | Channel.BasicPublish( 'Work', 'work.unit', Work );
217 | Inc( Counter );
218 | Sleep( FSleepMS );
219 | Until Terminated or (Counter > FMaxWork);
220 | Finally
221 | Channel := nil;
222 | End;
223 | WriteLine( 'Thread stopped' );
224 | end;
225 |
226 | procedure TProducerThread.WriteLine(Text: String);
227 | begin
228 | Queue( Procedure
229 | Begin
230 | ThreadSampleForm.MemoProducer.Lines.Add( Text );
231 | End );
232 | end;
233 |
234 | end.
235 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.Arguments.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.Arguments;
2 |
3 | interface
4 |
5 | Const
6 | AMQP_TTL_SECOND = 1000;
7 | AMQP_TTL_MINUTE = AMQP_TTL_SECOND * 60;
8 | AMQP_TTL_HOUR = AMQP_TTL_MINUTE * 60;
9 | AMQP_TTL_DAY = AMQP_TTL_HOUR * 24;
10 |
11 | Type
12 | TArgument = Record
13 | Name: String;
14 | Value: Variant;
15 | End;
16 |
17 | TArguments = Array of TArgument;
18 |
19 | TArgumentHelper = Record Helper for TArguments
20 | Function Add( Name: String; Value: Variant ): TArguments;
21 | Function SetMessageTTL( TimeToLiveMS: Int64 ): TArguments;
22 | End;
23 |
24 | Function MakeArguments: TArguments; overload;
25 | Function MakeArguments( Name: String; Value: Variant ): TArguments; overload;
26 |
27 | implementation
28 |
29 | Function MakeArguments( Name: String; Value: Variant ): TArguments;
30 | var
31 | Arg: TArgument;
32 | Begin
33 | Arg.Name := Name;
34 | Arg.Value := Value;
35 | Result := [ Arg ];
36 | End;
37 |
38 | Function MakeArguments: TArguments;
39 | Begin
40 | Result := [];
41 | End;
42 |
43 | { TArgumentHelper }
44 |
45 | function TArgumentHelper.Add(Name: String; Value: Variant): TArguments;
46 | begin
47 | Result := self + MakeArguments( Name, Value );
48 | end;
49 |
50 | function TArgumentHelper.SetMessageTTL(TimeToLiveMS: Int64): TArguments;
51 | begin
52 | Result := MakeArguments( 'x-message-ttl', TimeToLiveMS );
53 | end;
54 |
55 | end.
56 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.Classes.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.Classes;
2 |
3 | interface
4 |
5 | Uses
6 | System.SysUtils, System.Classes, System.SyncObjs, System.Generics.Collections,
7 | AMQP.Frame, AMQP.Message, AMQP.Method, AMQP.Types;
8 |
9 | Type
10 | AMQPException = Class(Exception);
11 |
12 | TAMQPServerProperties = Class
13 | Strict Private
14 | FCapabilities : TStringList;
15 | FMechanisms : TStringList;
16 | FLocales : TStringList;
17 | FClusterName : String;
18 | FCopyright : String;
19 | FInformation : String;
20 | FPlatform : String;
21 | FProduct : String;
22 | FVersion : String;
23 | FKnownHosts : String;
24 | FVersionMajor : Integer;
25 | FVersionMinor : Integer;
26 | FChannelMax : Integer;
27 | FFrameMax : Integer;
28 | FHeartbeat : Integer;
29 | Public
30 | Property Capabilities : TStringList read FCapabilities;
31 | Property Mechanisms : TStringList read FMechanisms;
32 | Property Locales : TStringList read FLocales;
33 | Property ClusterName : String read FClusterName;
34 | Property Copyright : String read FCopyright;
35 | Property Information : String read FInformation;
36 | Property &Platform : String read FPlatform;
37 | Property Product : String read FProduct;
38 | Property Version : String read FVersion;
39 | Property KnownHosts : String read FKnownHosts;
40 | Property ProtocolVersionMajor : Integer read FVersionMajor;
41 | Property ProtocolVersionMinor : Integer read FVersionMinor;
42 | Property ChannelMax : Integer read FChannelMax;
43 | Property FrameMax : Integer read FFrameMax;
44 | Property Heartbeat : Integer read FHeartbeat;
45 |
46 | Procedure ReadConnectionStart( AConnectionStart: TAMQPMethod );
47 | Procedure ReadConnectionTune( AConnectionTune: TAMQPMethod );
48 | Procedure ReadConnectionOpenOK( AConnectionOpenOK: TAMQPMethod );
49 |
50 | Constructor Create;
51 | Destructor Destroy; Override;
52 | End;
53 |
54 | TBlockingQueue = Class
55 | Strict Protected
56 | FGuard : TCriticalSection;
57 | FCondition : TConditionVariableCS;
58 | FQueue : TQueue;
59 | Public
60 | Function Count: Integer; Virtual;
61 | Function Get: T; Virtual;
62 | Procedure Put( Item: T ); Virtual;
63 |
64 | Constructor Create; Virtual;
65 | Destructor Destroy; Override;
66 | End;
67 |
68 | TAMQPQueue = TBlockingQueue;
69 |
70 | TAMQPMessageQueue = TBlockingQueue;
71 |
72 | implementation
73 |
74 | { TAMQPServerProperties }
75 |
76 | constructor TAMQPServerProperties.Create;
77 | begin
78 | FCapabilities := TStringList.Create;
79 | FMechanisms := TStringList.Create;
80 | FLocales := TStringList.Create;
81 | FMechanisms.StrictDelimiter := True;
82 | FMechanisms.Delimiter := ' ';
83 | FLocales.StrictDelimiter := True;
84 | FLocales.Delimiter := ' ';
85 | FClusterName := '';
86 | FCopyright := '';
87 | FInformation := '';
88 | FPlatform := '';
89 | FProduct := '';
90 | FVersion := '';
91 | FKnownHosts := '';
92 | FVersionMajor := 0;
93 | FVersionMinor := 0;
94 | FChannelMax := 0;
95 | FFrameMax := 0;
96 | FHeartbeat := 0;
97 | end;
98 |
99 | Procedure TAMQPServerProperties.ReadConnectionStart( AConnectionStart: TAMQPMethod );
100 | var
101 | ServerProperties: TFieldTable;
102 | ServerCapabilities: TFieldTable;
103 | Pair: TFieldValuePair;
104 | begin
105 | FMechanisms.DelimitedText := AConnectionStart.Field['mechanisms'].AsLongString.Value;
106 | FLocales.DelimitedText := AConnectionStart.Field['locales'].AsLongString.Value;
107 | ServerProperties := AConnectionStart.Field['server-properties'].AsFieldTable;
108 | FVersionMajor := AConnectionStart.Field['version-major'].AsShortShortUInt.Value;
109 | FVersionMinor := AConnectionStart.Field['version-minor'].AsShortShortUInt.Value;
110 | FClusterName := ServerProperties.Field['cluster_name'].AsShortString.Value;
111 | FCopyright := ServerProperties.Field['copyright'].AsShortString.Value;
112 | FInformation := ServerProperties.Field['information'].AsShortString.Value;
113 | FPlatform := ServerProperties.Field['platform'].AsShortString.Value;
114 | FProduct := ServerProperties.Field['product'].AsShortString.Value;
115 | FVersion := ServerProperties.Field['version'].AsShortString.Value;
116 | ServerCapabilities := ServerProperties.Field['capabilities'].AsFieldTable;
117 | for Pair in ServerCapabilities do
118 | FCapabilities.Values[ Pair.Name.Value ] := Pair.Value.AsString('');
119 | end;
120 |
121 | Procedure TAMQPServerProperties.ReadConnectionTune( AConnectionTune: TAMQPMethod );
122 | begin
123 | FChannelMax := AConnectionTune.Field['channel-max'].AsShortUInt.Value;
124 | FFrameMax := AConnectionTune.Field['frame-max'].AsLongUInt.Value;
125 | FHeartbeat := AConnectionTune.Field['heartbeat'].AsShortUInt.Value;
126 | end;
127 |
128 | Procedure TAMQPServerProperties.ReadConnectionOpenOK( AConnectionOpenOK: TAMQPMethod );
129 | begin
130 | FKnownHosts := AConnectionOpenOK.Field['known-hosts'].AsShortString.Value;
131 | end;
132 |
133 | destructor TAMQPServerProperties.Destroy;
134 | begin
135 | FCapabilities.Free;
136 | FMechanisms.Free;
137 | FLocales.Free;
138 | inherited;
139 | end;
140 |
141 | { TBlockingQueue }
142 |
143 | function TBlockingQueue.Count: Integer;
144 | begin
145 | FGuard.Acquire;
146 | try
147 | Result := FQueue.Count;
148 | finally
149 | FGuard.Release;
150 | end;
151 | end;
152 |
153 | constructor TBlockingQueue.Create;
154 | begin
155 | inherited;
156 | FGuard := TCriticalSection.Create;
157 | FCondition := TConditionVariableCS.Create;
158 | FQueue := TQueue.Create;
159 | end;
160 |
161 | destructor TBlockingQueue.Destroy;
162 | begin
163 | FQueue.Free;
164 | FQueue := nil;
165 | FCondition.Free;
166 | FCondition := nil;
167 | FGuard.Free;
168 | FGuard := nil;
169 | inherited;
170 | end;
171 |
172 | function TBlockingQueue.Get: T;
173 | begin
174 | FGuard.Acquire;
175 | try
176 | while FQueue.Count = 0 do
177 | begin
178 | FCondition.WaitFor(FGuard);
179 | end;
180 | Result := FQueue.Dequeue;
181 | finally
182 | FGuard.Release;
183 | end;
184 | end;
185 |
186 | procedure TBlockingQueue.Put(Item: T);
187 | begin
188 | FGuard.Acquire;
189 | try
190 | FQueue.Enqueue( Item );
191 | FCondition.ReleaseAll;
192 | finally
193 | FGuard.Release;
194 | end;
195 | end;
196 |
197 | end.
198 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.Frame.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.Frame;
2 |
3 | interface
4 |
5 | Uses
6 | AMQP.Payload;
7 |
8 | const
9 | FRAME_TYPE_METHOD = 1;
10 | FRAME_TYPE_HEADER = 2;
11 | FRAME_TYPE_CONTENT = 3;
12 | FRAME_TYPE_HEARTBEAT = 8;
13 | FRAME_END = $CE;
14 | FRAME_MIN_SIZE: Word = 4096;
15 |
16 | Type
17 | TFrameKind = ( fkMethod = FRAME_TYPE_METHOD,
18 | fkHeader = FRAME_TYPE_HEADER,
19 | fkBody = FRAME_TYPE_CONTENT,
20 | fkHeartbeat = FRAME_TYPE_HEARTBEAT );
21 |
22 | IAMQPFrame = interface ['{4BE40EEF-D60D-477D-9315-3005DD6C135E}']
23 | Function Kind : TFrameKind;
24 | Function Channel : Word;
25 | Function Size : Cardinal;
26 | Function Payload : TAMQPPayload;
27 | Function FrameEnd : Byte;
28 | Procedure SetKind( AKind: TFrameKind );
29 | Procedure SetChannel( AChannel: Word );
30 | Procedure SetSize( ASize: Cardinal );
31 | Procedure SetPayload( APayload: TAMQPPayload );
32 | Procedure SetFrameEnd( AFrameEnd: Byte );
33 | end;
34 |
35 | TAMQPFrame = Class( TInterfacedObject, IAMQPFrame )
36 | Strict Private
37 | FKind : TFrameKind;
38 | FChannel : Word;
39 | FSize : Cardinal;
40 | FPayload : TAMQPPayload;
41 | FFrameEnd : Byte;
42 | Public
43 | Function Kind : TFrameKind;
44 | Function Channel : Word;
45 | Function Size : Cardinal;
46 | Function Payload : TAMQPPayload;
47 | Function FrameEnd : Byte;
48 |
49 | Procedure SetKind( AKind: TFrameKind );
50 | Procedure SetChannel( AChannel: Word );
51 | Procedure SetSize( ASize: Cardinal );
52 | Procedure SetPayload( APayload: TAMQPPayload );
53 | Procedure SetFrameEnd( AFrameEnd: Byte );
54 |
55 | Procedure Clear;
56 | Constructor Create;
57 | Destructor Destroy; Override;
58 | End;
59 |
60 | implementation
61 |
62 | { TAMQPFrame }
63 |
64 | function TAMQPFrame.Channel: Word;
65 | begin
66 | Result := FChannel;
67 | end;
68 |
69 | procedure TAMQPFrame.Clear;
70 | begin
71 | Payload.Free;
72 | FKind := fkMethod;
73 | FChannel := 0;
74 | FSize := 0;
75 | FPayload := nil;
76 | FFrameEnd := 0;
77 | end;
78 |
79 | constructor TAMQPFrame.Create;
80 | begin
81 | FKind := fkMethod;
82 | FChannel := 0;
83 | FSize := 0;
84 | FPayload := nil;
85 | FFrameEnd := 0;
86 | end;
87 |
88 | destructor TAMQPFrame.Destroy;
89 | begin
90 | FPayload.Free;
91 | inherited;
92 | end;
93 |
94 | function TAMQPFrame.FrameEnd: Byte;
95 | begin
96 | Result := FFrameEnd;
97 | end;
98 |
99 | function TAMQPFrame.Kind: TFrameKind;
100 | begin
101 | Result := FKind;
102 | end;
103 |
104 | function TAMQPFrame.Payload: TAMQPPayload;
105 | begin
106 | Result := FPayload;
107 | end;
108 |
109 |
110 | procedure TAMQPFrame.SetChannel(AChannel: Word);
111 | begin
112 | FChannel := AChannel;
113 | end;
114 |
115 | procedure TAMQPFrame.SetFrameEnd(AFrameEnd: Byte);
116 | begin
117 | FFrameEnd := AFrameEnd;
118 | end;
119 |
120 | procedure TAMQPFrame.SetKind(AKind: TFrameKind);
121 | begin
122 | FKind := AKind;
123 | end;
124 |
125 | procedure TAMQPFrame.SetPayload(APayload: TAMQPPayload);
126 | begin
127 | FPayload := APayload;
128 | end;
129 |
130 | procedure TAMQPFrame.SetSize(ASize: Cardinal);
131 | begin
132 | FSize := ASize;
133 | end;
134 |
135 | function TAMQPFrame.Size: Cardinal;
136 | begin
137 | Result := FSize;
138 | end;
139 |
140 | end.
141 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.Header.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.Header;
2 |
3 | interface
4 |
5 | Uses
6 | System.Classes, AMQP.Payload, AMQP.IMessageProperties;
7 |
8 | Type
9 | TAMQPHeader = Class(TAMQPPayload)
10 | strict private
11 | FClassID : UInt16;
12 | FWeight : UInt16;
13 | FBodySize : UInt64;
14 | FPropertyList : IAMQPMessageProperties;
15 | Public
16 | Property ClassID : UInt16 read FClassID;
17 | Property Weight : UInt16 read FWeight;
18 | Property BodySize : UInt64 read FBodySize;
19 | Property PropertyList : IAMQPMessageProperties read FPropertyList;
20 | Procedure Assign( AHeader: TAMQPHeader );
21 | Procedure LoadFromStream( AStream: TStream ); Override;
22 | Constructor Create; Override;
23 | Destructor Destroy; Override;
24 | End;
25 |
26 | implementation
27 |
28 | Uses
29 | AMQP.MessageProperties, AMQP.StreamHelper;
30 |
31 | { TAMQPHeader }
32 |
33 | procedure TAMQPHeader.Assign(AHeader: TAMQPHeader);
34 | begin
35 | FClassID := AHeader.ClassID;
36 | FWeight := AHeader.Weight;
37 | FBodySize := AHeader.BodySize;
38 | FPropertyList.Assign( AHeader.PropertyList );
39 | end;
40 |
41 | constructor TAMQPHeader.Create;
42 | begin
43 | inherited;
44 | Name := 'Header';
45 | FClassID := 0;
46 | FWeight := 0;
47 | FBodySize := 0;
48 | FPropertyList := TAMQPMessageProperties.Create( 'Delphi' );
49 | end;
50 |
51 | destructor TAMQPHeader.Destroy;
52 | begin
53 | FPropertyList := nil;
54 | inherited;
55 | end;
56 |
57 | procedure TAMQPHeader.LoadFromStream(AStream: TStream);
58 | begin
59 | AStream.ReadUInt16( FClassID );
60 | AStream.ReadUInt16( FWeight );
61 | AStream.ReadUInt64( FBodySize );
62 | FPropertyList.LoadFromStream( AStream );
63 | end;
64 |
65 | end.
66 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.Helper.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.Helper;
2 |
3 | interface
4 |
5 | Uses
6 | AMQP.Payload, AMQP.Header, AMQP.Method;
7 |
8 | Type
9 | TAMQPPayloadHelper = Class Helper for TAMQPPayload
10 | Public
11 | Function AsMethod : TAMQPMethod;
12 | Function AsHeader : TAMQPHeader;
13 | Function AsBody : TAMQPBody;
14 | End;
15 |
16 | implementation
17 |
18 | { TAMQPPayloadHelper }
19 |
20 | function TAMQPPayloadHelper.AsBody: TAMQPBody;
21 | begin
22 | Result := Self as TAMQPBody;
23 | end;
24 |
25 | function TAMQPPayloadHelper.AsHeader: TAMQPHeader;
26 | begin
27 | Result := Self as TAMQPHeader;
28 | end;
29 |
30 | function TAMQPPayloadHelper.AsMethod: TAMQPMethod;
31 | begin
32 | Result := Self as TAMQPMethod;
33 | end;
34 |
35 | end.
36 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.IMessageProperties.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.IMessageProperties;
2 |
3 | interface
4 |
5 | Uses
6 | System.Classes, AMQP.Types;
7 |
8 | Type
9 | IAMQPMessageProperties = interface ['{2E874719-4F4E-4B62-BBD0-4F9E4C56C7CD}']
10 | Function ContentType : TShortString;
11 | Function ContentEncoding : TShortString;
12 | Function ApplicationHeaders : TFieldTable;
13 | Function DeliveryMode : TShortShortUInt;
14 | Function Priority : TShortShortUInt;
15 | Function CorrelationID : TShortString;
16 | Function ReplyTo : TShortString;
17 | Function Expiration : TShortString;
18 | Function MessageID : TShortString;
19 | Function Timestamp : TTimestamp;
20 | Function &Type : TShortString;
21 | Function UserID : TShortString;
22 | Function AppID : TShortString;
23 | Function Reserved : TShortString;
24 |
25 | Procedure SaveToStream( AStream: TStream );
26 | Procedure LoadFromStream( AStream: TStream );
27 | Procedure Assign( AMessageProperties: IAMQPMessageProperties );
28 | end;
29 |
30 | implementation
31 |
32 | end.
33 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.Interfaces.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.Interfaces;
2 |
3 | interface
4 |
5 | Uses
6 | System.SysUtils, System.Classes, AMQP.Classes, AMQP.Method, AMQP.Message, AMQP.Frame, AMQP.IMessageProperties, AMQP.Arguments;
7 |
8 | Type
9 | TAMQPChannelState = ( cOpen, cClosed );
10 |
11 | TConsumerMethod = Reference to Procedure( AMQPMessage: TAMQPMessage; var SendAck: Boolean );
12 |
13 | TExchangeType = ( etDirect, etTopic, etFanout, etHeaders );
14 |
15 | Const
16 | ExchangeTypeStr : Array[TExchangeType] of string = ( 'direct', 'topic', 'fanout', 'headers' );
17 |
18 | Type
19 | IAMQPChannel = interface(IAMQPBaseChannel) ['{6620C29F-0354-4C66-A3AC-4D5F7BB7113A}']
20 | Function GetID : Integer;
21 | Function GetQueue : TAMQPQueue;
22 | Function GetState : TAMQPChannelState;
23 |
24 | Property ID : Integer read GetID;
25 | Property Queue : TAMQPQueue read GetQueue;
26 | Property State : TAMQPChannelState read GetState;
27 |
28 | Procedure ExchangeDeclare( AExchangeName, AType: String; APassive: Boolean = False; ADurable: Boolean = True; ANoWait: Boolean = False ); overload;
29 | Procedure ExchangeDeclare( AExchangeName: String; AType: TExchangeType; APassive: Boolean = False; ADurable: Boolean = True; ANoWait: Boolean = False ); overload;
30 | Procedure ExchangeDelete( AExchangeName: String; AIfUnused: Boolean = True; ANoWait: Boolean = False );
31 | Procedure QueueDeclare( AQueueName: String; APassive: Boolean = False; ADurable: Boolean = True; AExclusive: Boolean = False;
32 | AAutoDelete: Boolean = False; ANoWait: Boolean = False; Arguments: TArguments = [] );
33 | Procedure QueueBind( AQueueName, AExchangeName, ARoutingKey: String; ANoWait: Boolean = False );
34 | Procedure QueuePurge( AQueueName: String; ANoWait: Boolean = False );
35 | Procedure QueueDelete( AQueueName: String; AIfUnused: Boolean = True; AIfEmpty: Boolean = True; ANoWait: Boolean = False );
36 | Procedure QueueUnBind( AQueueName, AExchangeName, ARoutingKey: String );
37 |
38 | Procedure BasicPublish( AExchange, ARoutingKey: String; AData: TStream ); Overload;
39 | Procedure BasicPublish( AExchange, ARoutingKey: String; AData: TStream; AMandatory: Boolean ); Overload;
40 | Procedure BasicPublish( AExchange, ARoutingKey: String; AData: TStream; AMandatory: Boolean; AMessageProperties: IAMQPMessageProperties ); Overload;
41 | Procedure BasicPublish( AExchange, ARoutingKey: String; Const AData: String; AMandatory: Boolean = False ); Overload;
42 |
43 | Function BasicGet( AQueueName: String; ANoAck: Boolean = False ): TAMQPMessage;
44 | Procedure BasicAck( AMessage: TAMQPMessage; AMultiple: Boolean = False ); Overload;
45 | //Procedure BasicAck( ADeliveryTag: UInt64; AMultiple: Boolean = False ); Overload;
46 | Procedure BasicConsume( AMessageHandler: TConsumerMethod; AQueueName, AConsumerTag: String; ANoLocal: Boolean = False;
47 | ANoAck: Boolean = False; AExclusive: Boolean = False; ANoWait: Boolean = False ); Overload;
48 | Procedure BasicConsume( AMessageQueue: TAMQPMessageQueue; AQueueName, AConsumerTag: String; ANoLocal: Boolean = False;
49 | ANoAck: Boolean = False; AExclusive: Boolean = False; ANoWait: Boolean = False ); Overload;
50 | Procedure BasicCancel( AConsumerTag: String; ANoWait: Boolean = False );
51 | Procedure BasicReject( AMessage: TAMQPMessage; ARequeue: Boolean = True ); overload;
52 | //Procedure BasicReject( ADeliveryTag: UInt64; ARequeue: Boolean = True ); overload;
53 |
54 | Procedure ConfirmSelect( ANoWait: Boolean = False );
55 | procedure ReceiveFrame( AFrame: TAMQPFrame );
56 |
57 | Procedure Close;
58 | Procedure ChannelClosed;
59 | end;
60 |
61 | IAMQPConnection = interface ['{4736645E-A4E1-4E3B-B1D5-BC218A6C6CCC}']
62 | Function IsOpen: Boolean;
63 | Function DefaultMessageProperties: IAMQPMessageProperties;
64 | //Procedure WriteFrame( FrameType: Byte; Channel: Word; Payload: TStream; Size: Integer );
65 | procedure WriteMethod( Channel: Word; Method: TAMQPMethod );
66 | procedure WriteContent( Channel, ClassID: Word; Content: TStream; MessageProperties: IAMQPMessageProperties );
67 | Procedure HeartbeatReceived;
68 | Procedure InternalDisconnect( CloseConnection: Boolean );
69 | Procedure ServerDisconnect( Msg: String );
70 | Procedure CloseChannel( Channel: IAMQPChannel );
71 | end;
72 |
73 | implementation
74 |
75 | end.
76 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.Message.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.Message;
2 |
3 | interface
4 |
5 | Uses
6 | System.Classes, AMQP.Header, AMQP.Frame;
7 |
8 | Type
9 | IAMQPBaseChannel = interface ['{A5198398-B9DC-461B-8ECF-69A0BD0AD49E}']
10 | Procedure BasicAck( ADeliveryTag: UInt64; AMultiple: Boolean = False ); Overload;
11 | Procedure BasicReject( ADeliveryTag: UInt64; ARequeue: Boolean = True ); overload;
12 | end;
13 |
14 | TAMQPMessage = Class
15 | Private
16 | FChannel : IAMQPBaseChannel;
17 | FDeliveryTag : UInt64;
18 | FRedelivered : Boolean;
19 | FConsumerTag : String;
20 | FExchange : String;
21 | FRoutingKey : String;
22 | FMessageCount : UInt32;
23 | FBody : TMemoryStream;
24 | FHeader : TAMQPHeader;
25 | Public
26 | Property Channel : IAMQPBaseChannel read FChannel write FChannel;
27 | Property ConsumerTag : String read FConsumerTag;
28 | Property DeliveryTag : UInt64 read FDeliveryTag;
29 | Property Redelivered : Boolean read FRedelivered;
30 | Property Exchange : String read FExchange;
31 | Property RoutingKey : String read FRoutingKey;
32 | Property MessageCount : UInt32 read FMessageCount;
33 | Property Header : TAMQPHeader read FHeader;
34 | Property Body : TMemoryStream read FBody;
35 |
36 | Procedure ReadFromData( AMethodFrame, AHeaderFrame: IAMQPFrame; var ABody: TMemoryStream );
37 | Procedure Ack;
38 | Procedure Reject;
39 |
40 | Constructor Create;
41 | Destructor Destroy; Override;
42 | End;
43 |
44 | implementation
45 |
46 | Uses
47 | System.SysUtils, AMQP.Method, AMQP.Helper;
48 |
49 | { TAMQPMessage }
50 |
51 | procedure TAMQPMessage.Ack;
52 | begin
53 | FChannel.BasicAck( DeliveryTag );
54 | end;
55 |
56 | constructor TAMQPMessage.Create;
57 | Begin
58 | FConsumerTag := '';
59 | FDeliveryTag := 0;
60 | FRedelivered := False;
61 | FExchange := '';
62 | FRoutingKey := '';
63 | FMessageCount := 0;
64 | FChannel := nil;
65 | FHeader := TAMQPHeader.Create;
66 | FBody := TMemoryStream.Create;
67 | End;
68 |
69 | procedure TAMQPMessage.ReadFromData(AMethodFrame, AHeaderFrame: IAMQPFrame; var ABody: TMemoryStream);
70 | var
71 | AMethod: TAMQPMethod;
72 | begin
73 | //Copy GetOK properties
74 | AMethod := AMethodFrame.Payload.AsMethod;
75 | FDeliveryTag := AMethod.Field[ 'delivery-tag' ].AsLongLongUInt.Value;
76 | FRedelivered := AMethod.Field[ 'redelivered' ].AsBoolean.Value;
77 | FExchange := AMethod.Field[ 'exchange' ].AsShortString.Value;
78 | FRoutingKey := AMethod.Field[ 'routing-key' ].AsShortString.Value;
79 | if AMethod.FindField( 'consumer-tag' ) <> nil then
80 | FConsumerTag := AMethod.Field[ 'consumer-tag' ].AsShortString.Value;
81 | if AMethod.FindField( 'message-count' ) <> nil then
82 | FMessageCount := AMethod.Field[ 'message-count' ].AsLongUInt.Value;
83 | //Steal header (cheaper/faster than copying it)
84 | FHeader.Free;
85 | FHeader := AHeaderFrame.Payload.AsHeader;
86 | AHeaderFrame.SetPayload( nil ); //Steal payload
87 | //Steal body
88 | FBody.Free;
89 | FBody := ABody;
90 | ABody := nil; //Steal body
91 | FBody.Position := 0;
92 | end;
93 |
94 | procedure TAMQPMessage.Reject;
95 | begin
96 | FChannel.BasicReject( DeliveryTag );
97 | end;
98 |
99 | destructor TAMQPMessage.Destroy;
100 | begin
101 | FBody.Free;
102 | FHeader.Free;
103 | FChannel := nil;
104 | inherited;
105 | end;
106 |
107 | end.
108 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.MessageProperties.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.MessageProperties;
2 |
3 | interface
4 |
5 | Uses
6 | System.Classes, AMQP.Types, AMQP.IMessageProperties;
7 |
8 | Type
9 | TAMQPMessageProperties = class(TInterfacedObject, IAMQPMessageProperties)
10 | Strict Private
11 | FContentType : TShortString; //MIME content type, e.g. 'application/json'
12 | FContentEncoding : TShortString; //MIME content encoding, e.g. 'utf8'
13 | FApplicationHeaders : TFieldTable; //message header field table
14 | FDeliveryMode : TShortShortUInt; //nonpersistent (1) or persistent (2)
15 | FPriority : TShortShortUInt; //message priority, 0 to 9
16 | FCorrelationID : TShortString; //application correlation identifier
17 | FReplyTo : TShortString; //address to reply to
18 | FExpiration : TShortString; //message expiration specification
19 | FMessageID : TShortString; //application message identifier
20 | FTimestamp : TTimestamp; //message timestamp
21 | FType : TShortString; //message type name
22 | FUserID : TShortString; //creating user id
23 | FAppID : TShortString; //creating application id
24 | FReserved : TShortString; //reserved, must be empty (ClusterID ?)
25 | Protected
26 | Function ContentType : TShortString;
27 | Function ContentEncoding : TShortString;
28 | Function ApplicationHeaders : TFieldTable;
29 | Function DeliveryMode : TShortShortUInt;
30 | Function Priority : TShortShortUInt;
31 | Function CorrelationID : TShortString;
32 | Function ReplyTo : TShortString;
33 | Function Expiration : TShortString;
34 | Function MessageID : TShortString;
35 | Function Timestamp : TTimestamp;
36 | Function &Type : TShortString;
37 | Function UserID : TShortString;
38 | Function AppID : TShortString;
39 | Function Reserved : TShortString;
40 | Public
41 | Procedure SaveToStream( AStream: TStream );
42 | Procedure LoadFromStream( AStream: TStream );
43 | Procedure Assign( AMessageProperties: IAMQPMessageProperties );
44 | Constructor Create( const AApplicationID: String );
45 | Destructor Destroy; Override;
46 | end;
47 |
48 | implementation
49 |
50 | Uses
51 | AMQP.StreamHelper;
52 |
53 | { TAMQPMessageProperties }
54 |
55 | procedure TAMQPMessageProperties.Assign(AMessageProperties: IAMQPMessageProperties);
56 | begin
57 | FContentType.Value := AMessageProperties.ContentType.Value;
58 | FContentEncoding.Value := AMessageProperties.ContentEncoding.Value;
59 | FApplicationHeaders.Assign( AMessageProperties.ApplicationHeaders );
60 | FDeliveryMode.Value := AMessageProperties.DeliveryMode.Value;
61 | FPriority.Value := AMessageProperties.Priority.Value;
62 | FCorrelationID.Value := AMessageProperties.CorrelationID.Value;
63 | FReplyTo.Value := AMessageProperties.ReplyTo.Value;
64 | FExpiration.Value := AMessageProperties.Expiration.Value;
65 | FMessageID.Value := AMessageProperties.MessageID.Value;
66 | FTimestamp.Value := AMessageProperties.Timestamp.Value;
67 | FType.Value := AMessageProperties.&Type.Value;
68 | FUserID.Value := AMessageProperties.UserID.Value;
69 | FAppID.Value := AMessageProperties.AppID.Value;
70 | FReserved.Value := AMessageProperties.Reserved.Value;
71 | end;
72 |
73 | constructor TAMQPMessageProperties.Create(const AApplicationID: String);
74 | begin
75 | FContentType := TShortString.Create( 'text/plain' );
76 | FContentEncoding := TShortString.Create( 'utf-8' );
77 | FApplicationHeaders := TFieldTable.Create;
78 | FDeliveryMode := TShortShortUInt.Create( 2 );
79 | FPriority := TShortShortUInt.Create( 1 );
80 | FCorrelationID := TShortString.Create( '' );
81 | FReplyTo := TShortString.Create( '' );
82 | FExpiration := TShortString.Create( '' );
83 | FMessageID := TShortString.Create( '' );
84 | FTimestamp := TLongLongUInt.Create( 0 );
85 | FType := TShortString.Create( '' );
86 | FUserID := TShortString.Create( '' );
87 | FAppID := TShortString.Create( AApplicationID );
88 | FReserved := TShortString.Create( '' );
89 | end;
90 |
91 | destructor TAMQPMessageProperties.Destroy;
92 | begin
93 | FContentType.Free;
94 | FContentEncoding.Free;
95 | FApplicationHeaders.Free;
96 | FDeliveryMode.Free;
97 | FPriority.Free;
98 | FCorrelationID.Free;
99 | FReplyTo.Free;
100 | FExpiration.Free;
101 | FMessageID.Free;
102 | FTimestamp.Free;
103 | FType.Free;
104 | FUserID.Free;
105 | FAppID.Free;
106 | FReserved.Free;
107 | inherited;
108 | end;
109 |
110 | function TAMQPMessageProperties.AppID: TShortString;
111 | begin
112 | Result := FAppID;
113 | end;
114 |
115 | function TAMQPMessageProperties.ApplicationHeaders: TFieldTable;
116 | begin
117 | Result := FApplicationHeaders;
118 | end;
119 |
120 | function TAMQPMessageProperties.ContentEncoding: TShortString;
121 | begin
122 | Result := FContentEncoding;
123 | end;
124 |
125 | function TAMQPMessageProperties.ContentType: TShortString;
126 | begin
127 | Result := FContentType;
128 | end;
129 |
130 | function TAMQPMessageProperties.CorrelationID: TShortString;
131 | begin
132 | Result := FCorrelationID;
133 | end;
134 |
135 | function TAMQPMessageProperties.DeliveryMode: TShortShortUInt;
136 | begin
137 | Result := FDeliveryMode;
138 | end;
139 |
140 | function TAMQPMessageProperties.Expiration: TShortString;
141 | begin
142 | Result := FExpiration;
143 | end;
144 |
145 | function TAMQPMessageProperties.MessageID: TShortString;
146 | begin
147 | Result := FMessageID;
148 | end;
149 |
150 | function TAMQPMessageProperties.Priority: TShortShortUInt;
151 | begin
152 | Result := FPriority;
153 | end;
154 |
155 | function TAMQPMessageProperties.ReplyTo: TShortString;
156 | begin
157 | Result := FReplyTo;
158 | end;
159 |
160 | function TAMQPMessageProperties.Reserved: TShortString;
161 | begin
162 | Result := FReplyTo;
163 | end;
164 |
165 | function TAMQPMessageProperties.Timestamp: TTimestamp;
166 | begin
167 | Result := FTimestamp;
168 | end;
169 |
170 | function TAMQPMessageProperties.&Type: TShortString;
171 | begin
172 | Result := FType;
173 | end;
174 |
175 | function TAMQPMessageProperties.UserID: TShortString;
176 | begin
177 | Result := FUserID;
178 | end;
179 |
180 | procedure TAMQPMessageProperties.LoadFromStream(AStream: TStream);
181 | var
182 | Flags: UInt16;
183 | begin
184 | AStream.ReadUInt16( Flags );
185 | if Flags and $8000 = $8000 then FContentType.LoadFromStream( AStream );
186 | if Flags and $4000 = $4000 then FContentEncoding.LoadFromStream( AStream );
187 | if Flags and $2000 = $2000 then FApplicationHeaders.LoadFromStream( AStream );
188 | if Flags and $1000 = $1000 then FDeliveryMode.LoadFromStream( AStream );
189 | if Flags and $0800 = $0800 then FPriority.LoadFromStream( AStream );
190 | if Flags and $0400 = $0400 then FCorrelationID.LoadFromStream( AStream );
191 | if Flags and $0200 = $0200 then FReplyTo.LoadFromStream( AStream );
192 | if Flags and $0100 = $0100 then FExpiration.LoadFromStream( AStream );
193 | if Flags and $0080 = $0080 then FMessageID.LoadFromStream( AStream );
194 | if Flags and $0040 = $0040 then FTimestamp.LoadFromStream( AStream );
195 | if Flags and $0020 = $0020 then FType.LoadFromStream( AStream );
196 | if Flags and $0010 = $0010 then FUserID.LoadFromStream( AStream );
197 | if Flags and $0008 = $0008 then FAppID.LoadFromStream( AStream );
198 | if Flags and $0004 = $0004 then FReserved.LoadFromStream( AStream );
199 | end;
200 |
201 | procedure TAMQPMessageProperties.SaveToStream(AStream: TStream);
202 | var
203 | PropertyFlags: UInt16;
204 | Data: TMemoryStream;
205 |
206 | Procedure SaveField( ASaveField: Boolean; ABit: Byte; AValue: TAMQPValue );
207 | Begin
208 | if ASaveField then
209 | Begin
210 | PropertyFlags := PropertyFlags + 1 shl ABit;
211 | AValue.SaveToStream( Data );
212 | End;
213 | End;
214 |
215 | begin
216 | PropertyFlags := 0;
217 | Data := TMemoryStream.Create;
218 | Try
219 | SaveField( ContentType.Value <> '', 15, ContentType );
220 | SaveField( ContentEncoding.Value <> '', 14, ContentEncoding );
221 | SaveField( ApplicationHeaders.Count <> 0, 13, ApplicationHeaders );
222 | SaveField( DeliveryMode.Value <> 0, 12, DeliveryMode );
223 | SaveField( Priority.Value <> 0, 11, Priority );
224 | SaveField( CorrelationID.Value <> '', 10, CorrelationID );
225 | SaveField( ReplyTo.Value <> '', 9, ReplyTo );
226 | SaveField( Expiration.Value <> '', 8, Expiration );
227 | SaveField( MessageID.Value <> '', 7, MessageID );
228 | SaveField( Timestamp.Value <> 0, 6, Timestamp );
229 | SaveField( FType.Value <> '', 5, FType );
230 | SaveField( UserID.Value <> '', 4, UserID );
231 | SaveField( AppID.Value <> '', 3, AppID );
232 | SaveField( Reserved.Value <> '', 2, Reserved );
233 |
234 | AStream.WriteUInt16( PropertyFlags );
235 | AStream.CopyFrom( Data, 0 );
236 | Finally
237 | Data.Free;
238 | End;
239 | end;
240 |
241 | end.
242 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.Payload.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.Payload;
2 |
3 | interface
4 |
5 | Uses
6 | System.Classes;
7 |
8 | Type
9 | TAMQPPayload = Class
10 | strict private
11 | FName: String;
12 | Public
13 | Property Name: String read FName write FName;
14 | Procedure LoadFromStream( AStream: TStream ); Virtual; Abstract;
15 | Constructor Create; Virtual;
16 | End;
17 |
18 | TAMQPBody = Class( TAMQPPayload )
19 | strict private
20 | FStream: TMemoryStream;
21 | Public
22 | Property Stream: TMemoryStream read FStream;
23 | Procedure LoadFromStream( AStream: TStream ); Override;
24 | Constructor Create; Override;
25 | Destructor Destroy; Override;
26 | End;
27 |
28 | implementation
29 |
30 | { TAMQPPayload }
31 |
32 | constructor TAMQPPayload.Create;
33 | begin
34 | FName := '';
35 | end;
36 |
37 | { TAMQPBody }
38 |
39 | constructor TAMQPBody.Create;
40 | begin
41 | inherited;
42 | FStream := TMemoryStream.Create;
43 | end;
44 |
45 | destructor TAMQPBody.Destroy;
46 | begin
47 | FStream.Free;
48 | inherited;
49 | end;
50 |
51 | procedure TAMQPBody.LoadFromStream(AStream: TStream);
52 | begin
53 | FStream.Clear;
54 | FStream.CopyFrom( AStream, AStream.Size - AStream.Position );
55 | FStream.Position := 0;
56 | end;
57 |
58 | end.
59 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.Protocol.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.Protocol;
2 |
3 | interface
4 |
5 | Uses
6 | IdGlobal;
7 |
8 | Type
9 | TAMQPMethodID = Record
10 | ClassID : UInt16;
11 | MethodID : UInt16;
12 | End;
13 |
14 | Const
15 | AMQP_Header: TIdBytes = [65, 77, 81, 80, 0, 0, 9, 1]; //'AMQP' + #0 + #0 + #9 + #1
16 |
17 | AMQP_CLASS_CONNECTION = 10;
18 | AMQP_CLASS_CHANNEL = 20;
19 | AMQP_CLASS_EXCHANGE = 40;
20 | AMQP_CLASS_QUEUE = 50;
21 | AMQP_CLASS_BASIC = 60;
22 | AMQP_CLASS_CONFIRM = 85;
23 | AMQP_CLASS_TX = 90;
24 |
25 | AMQP_CONNECTION_START : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONNECTION; MethodID: 10 );
26 | AMQP_CONNECTION_START_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONNECTION; MethodID: 11 );
27 | AMQP_CONNECTION_SECURE : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONNECTION; MethodID: 20 );
28 | AMQP_CONNECTION_SECURE_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONNECTION; MethodID: 21 );
29 | AMQP_CONNECTION_TUNE : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONNECTION; MethodID: 30 );
30 | AMQP_CONNECTION_TUNE_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONNECTION; MethodID: 31 );
31 | AMQP_CONNECTION_OPEN : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONNECTION; MethodID: 40 );
32 | AMQP_CONNECTION_OPEN_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONNECTION; MethodID: 41 );
33 | AMQP_CONNECTION_CLOSE : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONNECTION; MethodID: 50 );
34 | AMQP_CONNECTION_CLOSE_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONNECTION; MethodID: 51 );
35 |
36 | AMQP_CHANNEL_OPEN : TAMQPMethodID = ( ClassID: AMQP_CLASS_CHANNEL; MethodID: 10 );
37 | AMQP_CHANNEL_OPEN_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_CHANNEL; MethodID: 11 );
38 | AMQP_CHANNEL_FLOW : TAMQPMethodID = ( ClassID: AMQP_CLASS_CHANNEL; MethodID: 20 ); //TODO
39 | AMQP_CHANNEL_FLOW_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_CHANNEL; MethodID: 21 ); //TODO
40 | AMQP_CHANNEL_CLOSE : TAMQPMethodID = ( ClassID: AMQP_CLASS_CHANNEL; MethodID: 40 );
41 | AMQP_CHANNEL_CLOSE_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_CHANNEL; MethodID: 41 );
42 |
43 | AMQP_EXCHANGE_DECLARE : TAMQPMethodID = ( ClassID: AMQP_CLASS_EXCHANGE; MethodID: 10 );
44 | AMQP_EXCHANGE_DECLARE_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_EXCHANGE; MethodID: 11 );
45 | AMQP_EXCHANGE_DELETE : TAMQPMethodID = ( ClassID: AMQP_CLASS_EXCHANGE; MethodID: 20 );
46 | AMQP_EXCHANGE_DELETE_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_EXCHANGE; MethodID: 21 );
47 |
48 | AMQP_QUEUE_DECLARE : TAMQPMethodID = ( ClassID: AMQP_CLASS_QUEUE; MethodID: 10 );
49 | AMQP_QUEUE_DECLARE_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_QUEUE; MethodID: 11 );
50 | AMQP_QUEUE_BIND : TAMQPMethodID = ( ClassID: AMQP_CLASS_QUEUE; MethodID: 20 );
51 | AMQP_QUEUE_BIND_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_QUEUE; MethodID: 21 );
52 | AMQP_QUEUE_UNBIND : TAMQPMethodID = ( ClassID: AMQP_CLASS_QUEUE; MethodID: 50 );
53 | AMQP_QUEUE_UNBIND_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_QUEUE; MethodID: 51 );
54 | AMQP_QUEUE_PURGE : TAMQPMethodID = ( ClassID: AMQP_CLASS_QUEUE; MethodID: 30 );
55 | AMQP_QUEUE_PURGE_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_QUEUE; MethodID: 31 );
56 | AMQP_QUEUE_DELETE : TAMQPMethodID = ( ClassID: AMQP_CLASS_QUEUE; MethodID: 40 );
57 | AMQP_QUEUE_DELETE_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_QUEUE; MethodID: 41 );
58 |
59 | AMQP_BASIC_QOS : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 10 ); //TODO
60 | AMQP_BASIC_QOS_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 11 ); //TODO
61 | AMQP_BASIC_CONSUME : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 20 );
62 | AMQP_BASIC_CONSUME_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 21 );
63 | AMQP_BASIC_CANCEL : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 30 );
64 | AMQP_BASIC_CANCEL_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 31 );
65 | AMQP_BASIC_PUBLISH : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 40 );
66 | AMQP_BASIC_RETURN : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 50 );
67 | AMQP_BASIC_DELIVER : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 60 );
68 | AMQP_BASIC_GET : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 70 );
69 | AMQP_BASIC_GET_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 71 );
70 | AMQP_BASIC_GET_EMPTY : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 72 );
71 | AMQP_BASIC_ACK : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 80 );
72 | AMQP_BASIC_REJECT : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 90 );
73 | AMQP_BASIC_RECOVER_ASYNC : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 100 ); //TODO
74 | AMQP_BASIC_RECOVER : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 110 ); //TODO
75 | AMQP_BASIC_RECOVER_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_BASIC; MethodID: 111 ); //TODO
76 |
77 | AMQP_CONFIRM_SELECT : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONFIRM; MethodID: 10 );
78 | AMQP_CONFIRM_SELECT_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_CONFIRM; MethodID: 11 );
79 |
80 | AMQP_TX_SELECT : TAMQPMethodID = ( ClassID: AMQP_CLASS_TX; MethodID: 10 ); //TODO
81 | AMQP_TX_SELECT_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_TX; MethodID: 11 ); //TODO
82 | AMQP_TX_COMMIT : TAMQPMethodID = ( ClassID: AMQP_CLASS_TX; MethodID: 20 ); //TODO
83 | AMQP_TX_COMMIT_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_TX; MethodID: 21 ); //TODO
84 | AMQP_TX_ROLLBACK : TAMQPMethodID = ( ClassID: AMQP_CLASS_TX; MethodID: 30 ); //TODO
85 | AMQP_TX_ROLLBACK_OK : TAMQPMethodID = ( ClassID: AMQP_CLASS_TX; MethodID: 31 ); //TODO
86 |
87 | // CONTENT_METHODS : array[0..3] of TAMQPMethodID = (
88 | // AMQP_BASIC_PUBLISH,
89 | // AMQP_BASIC_RETURN,
90 | // AMQP_BASIC_DELIVER,
91 | // AMQP_BASIC_GET_OK
92 | // );
93 |
94 | implementation
95 |
96 | end.
97 |
--------------------------------------------------------------------------------
/AMQP/Source/AMQP.StreamHelper.pas:
--------------------------------------------------------------------------------
1 | unit AMQP.StreamHelper;
2 |
3 | interface
4 |
5 | Uses
6 | System.SysUtils, System.Classes, IdGlobal;
7 |
8 | Type
9 | TStreamHelper = Class helper for TStream
10 | Private
11 | function GetAsString(AEncoding: TEncoding): String;
12 | procedure SetAsString(AEncoding: TEncoding; const Value: String);
13 | Public
14 | Procedure WriteMSB( var Buffer; Count: Cardinal );
15 | Procedure WriteOctet( B: Byte );
16 | Procedure WriteUInt8( I: UInt8 );
17 | Procedure WriteUInt16( I: UInt16 );
18 | Procedure WriteUInt32( I: UInt32 );
19 | Procedure WriteUInt64( I: UInt64 );
20 | Procedure WriteInt8( I: Int8 );
21 | Procedure WriteInt16( I: Int16 );
22 | Procedure WriteInt32( I: Int32 );
23 | Procedure WriteInt64( I: Int64 );
24 | Procedure WriteShortStr( S: String );
25 | Procedure ReadMSB( var Buffer; Count: Integer );
26 | Procedure ReadOctet( var B: Byte );
27 | Procedure ReadUInt8( var I: UInt8 );
28 | Procedure ReadUInt16( var I: UInt16 );
29 | Procedure ReadUInt32( var I: UInt32 );
30 | Procedure ReadUInt64( var I: UInt64 );
31 | Procedure ReadInt8( var I: Int8 );
32 | Procedure ReadInt16( var I: Int16 );
33 | Procedure ReadInt32( var I: Int32 );
34 | Procedure ReadInt64( var I: Int64 );
35 | Procedure ReadShortStr( var S: String );
36 | Procedure ReadLongStr( var S: String );
37 | Function AsBytes: TIdBytes;
38 | Property AsString[ Encoding: TEncoding ]: String read GetAsString write SetAsString;
39 | End;
40 |
41 | implementation
42 |
43 | { TStreamHelper }
44 |
45 | function TStreamHelper.AsBytes: TIdBytes;
46 | var
47 | OldPosition: Integer;
48 | begin
49 | OldPosition := Position;
50 | Position := 0;
51 | SetLength( Result, Size );
52 | ReadBuffer( Result[0], Size );
53 | Position := OldPosition;
54 | end;
55 |
56 | function TStreamHelper.GetAsString(AEncoding: TEncoding): String;
57 | var
58 | StringStream: TStringStream;
59 | begin
60 | StringStream := TStringStream.Create( '', AEncoding );
61 | Try
62 | StringStream.CopyFrom( Self, -1 );
63 | Result := StringStream.DataString;
64 | Finally
65 | StringStream.Free;
66 | End;
67 | end;
68 |
69 | procedure TStreamHelper.ReadInt16(var I: Int16);
70 | begin
71 | ReadMSB( I, 2 );
72 | end;
73 |
74 | procedure TStreamHelper.ReadInt32(var I: Int32);
75 | begin
76 | ReadMSB( I, 4 );
77 | end;
78 |
79 | procedure TStreamHelper.ReadInt64(var I: Int64);
80 | begin
81 | ReadMSB( I, 8 );
82 | end;
83 |
84 | procedure TStreamHelper.ReadInt8(var I: Int8);
85 | begin
86 | Read( I, 1 );
87 | end;
88 |
89 | procedure TStreamHelper.ReadLongStr(var S: String);
90 | var
91 | Str: AnsiString;
92 | Len: UInt32;
93 | begin
94 | ReadUInt32( Len );
95 | SetLength( Str, Len );
96 | if Len > 0 then
97 | Read( Str[1], Len );
98 | S := String( Str );
99 | end;
100 |
101 | Procedure TStreamHelper.ReadMSB(var Buffer; Count: Integer);
102 | var
103 | Cnt: Integer;
104 | begin
105 | For Cnt := 0 to Count-1 do
106 | Read( PByteArray(@Buffer)[Count - Cnt - 1], 1 );
107 | end;
108 |
109 | procedure TStreamHelper.ReadOctet(var B: Byte);
110 | begin
111 | Read( B, 1 );
112 | end;
113 |
114 | procedure TStreamHelper.ReadShortStr(var S: String);
115 | var
116 | Str: AnsiString;
117 | Len: Byte;
118 | begin
119 | ReadUInt8( Len );
120 | SetLength( Str, Len );
121 | if Len > 0 then
122 | Read( Str[1], Len );
123 | S := String( Str );
124 | end;
125 |
126 | procedure TStreamHelper.ReadUInt16(var I: UInt16);
127 | begin
128 | ReadMSB( I, 2 );
129 | end;
130 |
131 | procedure TStreamHelper.ReadUInt32(var I: UInt32);
132 | begin
133 | ReadMSB( I, 4 );
134 | end;
135 |
136 | procedure TStreamHelper.ReadUInt64(var I: UInt64);
137 | begin
138 | ReadMSB( I, 8 );
139 | end;
140 |
141 | procedure TStreamHelper.ReadUInt8(var I: UInt8);
142 | begin
143 | Read( I, 1 );
144 | end;
145 |
146 | procedure TStreamHelper.SetAsString(AEncoding: TEncoding; const Value: String);
147 | var
148 | StringStream: TStringStream;
149 | begin
150 | StringStream := TStringStream.Create( Value, AEncoding );
151 | Try
152 | Self.CopyFrom( StringStream, -1 );
153 | Finally
154 | StringStream.Free;
155 | End;
156 | end;
157 |
158 | procedure TStreamHelper.WriteInt16(I: Int16);
159 | begin
160 | WriteMSB( I, 2 );
161 | end;
162 |
163 | procedure TStreamHelper.WriteInt32(I: Int32);
164 | begin
165 | WriteMSB( I, 4 );
166 | end;
167 |
168 | procedure TStreamHelper.WriteInt64(I: Int64);
169 | begin
170 | WriteMSB( I, 8 );
171 | end;
172 |
173 | procedure TStreamHelper.WriteInt8(I: Int8);
174 | begin
175 | WriteMSB( I, 1 );
176 | end;
177 |
178 | procedure TStreamHelper.WriteMSB(var Buffer; Count: Cardinal);
179 | var
180 | Index: Integer;
181 | begin
182 | For Index := Count-1 downto 0 do
183 | WriteData( PByteArray(@Buffer)[Index], 1 );
184 | end;
185 |
186 | procedure TStreamHelper.WriteOctet(B: Byte);
187 | begin
188 | WriteMSB( B, 1 );
189 | end;
190 |
191 | procedure TStreamHelper.WriteShortStr(S: String);
192 | var
193 | Char: AnsiChar;
194 | Str: AnsiString;
195 | B: Byte;
196 | begin
197 | B := S.Length;
198 | Str := AnsiString( S );
199 | WriteData( B );
200 | for Char in Str do
201 | WriteData( Char );
202 | end;
203 |
204 | procedure TStreamHelper.WriteUInt64(I: UInt64);
205 | begin
206 | WriteMSB( I, 8 );
207 | end;
208 |
209 | procedure TStreamHelper.WriteUInt16(I: UInt16);
210 | begin
211 | WriteMSB( I, 2 );
212 | end;
213 |
214 | procedure TStreamHelper.WriteUInt32(I: UInt32);
215 | begin
216 | WriteMSB( I, 4 );
217 | end;
218 |
219 | procedure TStreamHelper.WriteUInt8(I: UInt8);
220 | begin
221 | WriteMSB( I, 1 );
222 | end;
223 |
224 | end.
225 |
--------------------------------------------------------------------------------
/EasyDelphiQ/EasyDelphiQ.Classes.pas:
--------------------------------------------------------------------------------
1 | unit EasyDelphiQ.Classes;
2 |
3 | interface
4 |
5 | Uses
6 | System.SysUtils, AMQP.Interfaces, EasyDelphiQ.Interfaces;
7 |
8 | Type
9 | EEasyDelphiQConnectionFailed = Class(Exception);
10 |
11 | TQueue = class(TInterfacedObject, IQueue)
12 | Private
13 | FChannel: IAMQPChannel;
14 | FName: String;
15 | FTopic: String;
16 | FSubscriberID: String;
17 | FExchange: String;
18 | FClassName: String;
19 | Public
20 | Function Name: String;
21 | Function Topic: String;
22 | Function SubscriberID: String;
23 | Function Exchange: String;
24 | Function ClassName: String;
25 | Procedure Reconnect( Channel: IAMQPChannel );
26 | Constructor Create( AChannel: IAMQPChannel; AName: String; ATopic: String; ASubscriberID: String; AExchange: String;
27 | AClassName: String );
28 | End;
29 |
30 | TExchange = class(TInterfacedObject, IExchange)
31 | Private
32 | FChannel: IAMQPChannel;
33 | FName: String;
34 | FExchangeType: TExchangeType;
35 | Public
36 | Function Name: String;
37 | Function ExchangeType: TExchangeType;
38 | Procedure Reconnect( Channel: IAMQPChannel );
39 | Constructor Create( AChannel: IAMQPChannel; AName: String; AExchangeType: TExchangeType );
40 | End;
41 |
42 | TSubscriptionResult = Class(TInterfacedObject, ISubscriptionResult)
43 | Private
44 | FChannel: IAMQPChannel;
45 | FQueue: IQueue;
46 | Public
47 | Function Queue: IQueue;
48 | Procedure Cancel;
49 | Constructor Create( AChannel: IAMQPChannel; AQueue: IQueue );
50 | End;
51 |
52 | implementation
53 |
54 | { TQueue }
55 |
56 | function TQueue.ClassName: String;
57 | begin
58 | Result := FClassName;
59 | end;
60 |
61 | constructor TQueue.Create(AChannel: IAMQPChannel; AName, ATopic, ASubscriberID, AExchange, AClassName: String);
62 | begin
63 | FChannel := AChannel;
64 | FName := AName;
65 | FTopic := ATopic;
66 | FSubscriberID := ASubscriberID;
67 | FExchange := AExchange;
68 | FClassName := AClassName;
69 | end;
70 |
71 | function TQueue.Exchange: String;
72 | begin
73 | Result := FExchange;
74 | end;
75 |
76 | function TQueue.Name: String;
77 | begin
78 | Result := FName;
79 | end;
80 |
81 | procedure TQueue.Reconnect(Channel: IAMQPChannel);
82 | begin
83 | FChannel := nil;
84 | FChannel := Channel;
85 | end;
86 |
87 | function TQueue.SubscriberID: String;
88 | begin
89 | Result := FSubscriberID;
90 | end;
91 |
92 | function TQueue.Topic: String;
93 | begin
94 | Result := FTopic;
95 | end;
96 |
97 | { TExchange }
98 |
99 | constructor TExchange.Create(AChannel: IAMQPChannel; AName: String; AExchangeType: TExchangeType);
100 | begin
101 | FChannel := AChannel;
102 | FName := AName;
103 | FExchangeType := AExchangeType;
104 | end;
105 |
106 | function TExchange.ExchangeType: TExchangeType;
107 | begin
108 | Result := FExchangeType;
109 | end;
110 |
111 | function TExchange.Name: String;
112 | begin
113 | Result := FName;
114 | end;
115 |
116 | procedure TExchange.Reconnect(Channel: IAMQPChannel);
117 | begin
118 | FChannel := nil;
119 | FChannel := Channel;
120 | end;
121 |
122 | { TSubscriptionResult }
123 |
124 | procedure TSubscriptionResult.Cancel;
125 | begin
126 | Try
127 | FChannel.BasicCancel( FQueue.SubscriberID );
128 | Except
129 | On E: Exception do
130 | ; //If subscription does not exist then ignore (if we, for instance, have been disconnected already)
131 | End;
132 | end;
133 |
134 | constructor TSubscriptionResult.Create(AChannel: IAMQPChannel; AQueue: IQueue);
135 | begin
136 | FChannel := AChannel;
137 | FQueue := AQueue;
138 | end;
139 |
140 | function TSubscriptionResult.Queue: IQueue;
141 | begin
142 | Result := FQueue;
143 | end;
144 |
145 | end.
146 |
--------------------------------------------------------------------------------
/EasyDelphiQ/EasyDelphiQ.DTO.pas:
--------------------------------------------------------------------------------
1 | unit EasyDelphiQ.DTO;
2 |
3 | interface
4 |
5 | Type
6 | AssemblyNameAttribute = class(TCustomAttribute)
7 | Private
8 | FName: String;
9 | Public
10 | property Name: String read FName write FName;
11 | constructor create(AName: String);
12 | end;
13 |
14 | TClassInformation = record
15 | Private
16 | FClassName: String;
17 | FUnitName: String;
18 | FAssemblyName: String;
19 | Function GetAssemblyNameFromRTI( Obj: TObject ): String;
20 | Public
21 | Function GetAssemblyName: String;
22 | Function GetQueueName(ASubscriberID: String): String;
23 | Function GetExchangeName: String;
24 | Function GetUnitName: String;
25 | Function GetClassName: String;
26 | Function GetFullyQualifiedClassName: String;
27 | Constructor Create( Obj: TObject );
28 | end;
29 |
30 | implementation
31 |
32 | uses
33 | System.Rtti;
34 |
35 | { AssemblyNameAttribute }
36 |
37 | constructor AssemblyNameAttribute.create(AName: String);
38 | begin
39 | FName := AName;
40 | end;
41 |
42 | { TClassInformation }
43 |
44 | Function TClassInformation.GetAssemblyNameFromRTI( Obj: TObject ): String;
45 | var
46 | ctx: TRttiContext;
47 | T: TRttiType;
48 | A: TCustomAttribute;
49 | Begin
50 | ctx := TRttiContext.Create;
51 | Try
52 | T := ctx.GetType( obj.ClassInfo );
53 | For A in T.GetAttributes do
54 | if A is AssemblyNameAttribute then
55 | Result := AssemblyNameAttribute(A).Name;
56 | Finally
57 | ctx.Free;
58 | End;
59 | End;
60 |
61 | constructor TClassInformation.Create(Obj: TObject);
62 | begin
63 | FUnitName := Obj.UnitName;
64 | FClassName := Obj.ClassName;
65 | FAssemblyName := GetAssemblyNameFromRTI( Obj );
66 | end;
67 |
68 | function TClassInformation.GetAssemblyName: String;
69 | begin
70 | Result := FAssemblyName;
71 | end;
72 |
73 | function TClassInformation.GetClassName: String;
74 | begin
75 | Result := FClassName;
76 | end;
77 |
78 | function TClassInformation.GetExchangeName: String;
79 | begin
80 | Result := GetFullyQualifiedClassName + ':' + FAssemblyName;
81 | end;
82 |
83 | function TClassInformation.GetFullyQualifiedClassName: String;
84 | begin
85 | Result := FUnitName + '.' + FClassName;
86 | end;
87 |
88 | function TClassInformation.GetQueueName(ASubscriberID: String): String;
89 | begin
90 | Result := FUnitName + '_' + FClassName + ':' + FAssemblyName + '_' + ASubscriberID;
91 | end;
92 |
93 | function TClassInformation.GetUnitName: String;
94 | begin
95 | Result := FUnitName;
96 | end;
97 |
98 | end.
99 |
--------------------------------------------------------------------------------
/EasyDelphiQ/EasyDelphiQ.Interfaces.pas:
--------------------------------------------------------------------------------
1 | unit EasyDelphiQ.Interfaces;
2 |
3 | interface
4 |
5 | Uses
6 | AMQP.Interfaces;
7 |
8 | Type
9 | IQueue = Interface ['{B6686F6E-3772-47C8-A30C-6FC26AB12084}']
10 | Function Name: String;
11 | Function Topic: String;
12 | Function SubscriberID: String;
13 | Function Exchange: String;
14 | Function ClassName: String;
15 | Procedure Reconnect( Channel: IAMQPChannel );
16 | End;
17 |
18 | IExchange = Interface ['{58CB0E85-5E41-475D-BBCE-C7DCFA401AA9}']
19 | Function Name: String;
20 | Function ExchangeType: TExchangeType;
21 | Procedure Reconnect( Channel: IAMQPChannel );
22 | End;
23 |
24 | ISubscriptionResult = Interface ['{6B4F0D36-EE7C-47EC-92B9-4A7222476054}']
25 | Function Queue: IQueue;
26 | Procedure Cancel;
27 | End;
28 |
29 |
30 | implementation
31 |
32 | end.
33 |
--------------------------------------------------------------------------------
/EasyDelphiQ/Testbench/MainWin.dfm:
--------------------------------------------------------------------------------
1 | object MainForm: TMainForm
2 | Left = 0
3 | Top = 0
4 | Caption = 'QTestbench'
5 | ClientHeight = 337
6 | ClientWidth = 635
7 | Color = clBtnFace
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -11
11 | Font.Name = 'Tahoma'
12 | Font.Style = []
13 | OldCreateOrder = False
14 | OnCreate = FormCreate
15 | OnDestroy = FormDestroy
16 | DesignSize = (
17 | 635
18 | 337)
19 | PixelsPerInch = 96
20 | TextHeight = 13
21 | object ButtonPublish: TButton
22 | Left = 8
23 | Top = 8
24 | Width = 75
25 | Height = 25
26 | Caption = 'Publish'
27 | TabOrder = 0
28 | OnClick = ButtonPublishClick
29 | end
30 | object Memo1: TMemo
31 | Left = 8
32 | Top = 64
33 | Width = 619
34 | Height = 265
35 | Anchors = [akLeft, akTop, akRight, akBottom]
36 | ScrollBars = ssVertical
37 | TabOrder = 1
38 | end
39 | object ButtonGet: TButton
40 | Left = 89
41 | Top = 8
42 | Width = 75
43 | Height = 25
44 | Caption = 'Get'
45 | TabOrder = 2
46 | OnClick = ButtonGetClick
47 | end
48 | object ButtonSubscribe: TButton
49 | Left = 170
50 | Top = 8
51 | Width = 115
52 | Height = 25
53 | Caption = 'Subscribe TestDTO'
54 | TabOrder = 3
55 | OnClick = ButtonSubscribeClick
56 | end
57 | object ButtonCancelSubscription: TButton
58 | Left = 291
59 | Top = 8
60 | Width = 118
61 | Height = 25
62 | Caption = 'Cancel subscription'
63 | TabOrder = 4
64 | OnClick = ButtonCancelSubscriptionClick
65 | end
66 | object SubscribeTimeseries: TButton
67 | Left = 170
68 | Top = 33
69 | Width = 115
70 | Height = 25
71 | Caption = 'Subscribe Timeseries'
72 | TabOrder = 5
73 | OnClick = SubscribeTimeseriesClick
74 | end
75 | end
76 |
--------------------------------------------------------------------------------
/EasyDelphiQ/Testbench/MainWin.pas:
--------------------------------------------------------------------------------
1 | unit MainWin;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, EasyDelphiQ, EasyDelphiQ.Interfaces, Some.namespace,
8 | Neas.PowermanApi.Notifications.DTOs.V1, System.Generics.Collections;
9 |
10 | type
11 | TMainForm = class(TForm)
12 | ButtonPublish: TButton;
13 | Memo1: TMemo;
14 | ButtonGet: TButton;
15 | ButtonSubscribe: TButton;
16 | ButtonCancelSubscription: TButton;
17 | SubscribeTimeseries: TButton;
18 | procedure ButtonPublishClick(Sender: TObject);
19 | procedure FormCreate(Sender: TObject);
20 | procedure FormDestroy(Sender: TObject);
21 | procedure ButtonGetClick(Sender: TObject);
22 | procedure ButtonSubscribeClick(Sender: TObject);
23 | procedure ButtonCancelSubscriptionClick(Sender: TObject);
24 | procedure SubscribeTimeseriesClick(Sender: TObject);
25 | private
26 | FBus: TBus;
27 | FBusPM: TBus;
28 | FSubscription: ISubscriptionResult;
29 | FSubscriptionPM: ISubscriptionResult;
30 | FList: TThreadList;
31 | Procedure BusConnected(Sender: TObject);
32 | Procedure BusDisconnected(Sender: TObject);
33 | Procedure Handler( var Msg: TestDTO );
34 | Procedure HandlerPM( var Msg: ProductionGroupDataSerieCollectionV1 );
35 | Procedure WMUSER(var Msg: TMessage); Message WM_USER;
36 | procedure ReadMessagesFromList;
37 | public
38 | end;
39 |
40 | var
41 | MainForm: TMainForm;
42 |
43 | implementation
44 |
45 | Uses
46 | EasyDelphiQ.DTO, AMQP.Arguments, DJSON;
47 |
48 | {$R *.dfm}
49 |
50 | procedure TMainForm.BusConnected(Sender: TObject);
51 | begin
52 | Memo1.Lines.Add( 'Connected' );
53 | end;
54 |
55 | procedure TMainForm.BusDisconnected(Sender: TObject);
56 | begin
57 | Memo1.Lines.Add( 'Disconnected' );
58 | end;
59 |
60 | procedure TMainForm.ButtonPublishClick(Sender: TObject);
61 | var
62 | DTO: TestDTO;
63 | begin
64 | DTO := TestDTO.Create;
65 | Try
66 | DTO.ID := 42;
67 | DTO.Name := 'Zaphod';
68 | FBus.Publish( DTO );
69 | Memo1.Lines.Add( 'Message published' );
70 | Finally
71 | DTO.Free;
72 | End;
73 | end;
74 |
75 | procedure TMainForm.ButtonGetClick(Sender: TObject);
76 | var
77 | DTO: TestDTO;
78 | begin
79 | DTO := FBus.Get( 'Testbench' );
80 | if DTO = nil then
81 | Memo1.Lines.Add( 'No message' )
82 | else
83 | Try
84 | Memo1.Lines.Add( 'Received:' );
85 | Memo1.Lines.Add( ' DTO.ID: ' + DTO.ID.ToString );
86 | Memo1.Lines.Add( ' DTO.Name: ' + DTO.Name );
87 | Finally
88 | DTO.Free;
89 | End;
90 | end;
91 |
92 | procedure TMainForm.ButtonSubscribeClick(Sender: TObject);
93 | begin
94 | FSubscription := FBus.Subscribe( 'Testbench', Handler, MakeArguments.SetMessageTTL( 30000 ) );
95 | end;
96 |
97 | procedure TMainForm.ButtonCancelSubscriptionClick(Sender: TObject);
98 | begin
99 | FSubscription.Cancel;
100 | FSubscription := nil;
101 | end;
102 |
103 | procedure TMainForm.FormCreate(Sender: TObject);
104 | begin
105 | ReportMemoryLeaksOnShutdown := True;
106 | FBus := RabbitHutch.CreateBus( 'host=localhost;username=TestUser;password=password' );
107 | FBus.OnConnected := BusConnected;
108 | FBus.OnDisconnected := BusDisconnected;
109 | FSubscription := nil;
110 |
111 | FBusPM := RabbitHutch.CreateBus( 'host=rabbitmq_test;username=rabbit;password=rabbit' );
112 | FBusPM.OnConnected := BusConnected;
113 | FBusPM.OnDisconnected := BusDisconnected;
114 | FSubscriptionPM := nil;
115 |
116 | FList := TThreadList.Create;
117 | end;
118 |
119 | procedure TMainForm.FormDestroy(Sender: TObject);
120 | begin
121 | FBus.Free;
122 | FBusPM.Free;
123 | FList.Free;
124 | end;
125 |
126 | procedure TMainForm.Handler(var Msg: TestDTO);
127 | var
128 | DTO: TestDTO;
129 | begin
130 | DTO := Msg; //Necessary to capture the object in the anonymous method below
131 | TThread.Queue( nil,
132 | Procedure
133 | begin
134 | Memo1.Lines.Add( 'Received:' );
135 | Memo1.Lines.Add( ' DTO.ID: ' + DTO.ID.ToString );
136 | Memo1.Lines.Add( ' DTO.Name: ' + DTO.Name );
137 | DTO.Free; //Free the object here - we are done with it
138 | end );
139 | Msg := nil; //Don't free the object here
140 | end;
141 |
142 | procedure TMainForm.HandlerPM(var Msg: ProductionGroupDataSerieCollectionV1);
143 | begin
144 | FList.Add( Msg );
145 | Msg := nil;
146 | PostMessage( Handle, WM_USER, 0, 0 )
147 | end;
148 |
149 | procedure TMainForm.SubscribeTimeseriesClick(Sender: TObject);
150 | begin
151 | FSubscriptionPM := FBusPM.Subscribe( 'NexusDevTest', 'PowermanTest', '', HandlerPM,
152 | MakeArguments.Add( 'x-message-ttl', 20000 ) );
153 | end;
154 |
155 | procedure TMainForm.WMUSER(var Msg: TMessage);
156 | begin
157 | ReadMessagesFromList;
158 | end;
159 |
160 | procedure TMainForm.ReadMessagesFromList;
161 | var
162 | List: TList;
163 | Msg: ProductionGroupDataSerieCollectionV1;
164 | Dataseries: ProductionGroupDataSerieV1;
165 | begin
166 | List := FList.LockList;
167 | Try
168 | for Msg in List do
169 | Begin
170 | Memo1.Lines.Add( 'Powerman Notification (' + Msg.Count.ToString + ' dataseries)' );
171 | for Dataseries in Msg do
172 | Memo1.Lines.Add( TJSONSerializer.Serialize(Dataseries) );
173 | Msg.Free;
174 | End;
175 | List.Clear;
176 | Finally
177 | FList.UnlockList;
178 | End;
179 | end;
180 |
181 | end.
182 |
--------------------------------------------------------------------------------
/EasyDelphiQ/Testbench/Neas.PowermanApi.Notifications.DTOs.V1.pas:
--------------------------------------------------------------------------------
1 | unit Neas.PowermanApi.Notifications.DTOs.V1;
2 |
3 | interface
4 |
5 | Uses
6 | System.Generics.Collections, EasyDelphiQ.DTO;
7 |
8 | Type
9 | {$SCOPEDENUMS ON}
10 | TDataSerieTypeV1 = ( ConsPlanNoRegMWh, ConsPrognosisMWh,
11 | IntegrationTest1, IntegrationTest2, IntegrationTest3,
12 | IntradayActivated_MWH_DOWN, IntradayActivated_MWH_UP,
13 | IntradayActivated_VALUE_DOWN, IntradayActivated_VALUE_UP,
14 | ManRsvActivation_Balance_MWH_DOWN, ManRsvActivation_Balance_MWH_UP,
15 | ManRsvActivation_Balance_VALUE_DOWN, ManRsvActivation_Balance_VALUE_UP,
16 | ManRsvActivation_Special_MWH_DOWN, ManRsvActivation_Special_MWH_UP,
17 | ManRsvActivation_Special_VALUE_DOWN, ManRsvActivation_Special_VALUE_UP,
18 | ProdPlanNoRegLowerMWh, ProdPlanNoRegMWh, ProdPlanNoRegUpperMWh,
19 | ProdPrognosisLowerMWh, ProdPrognosisMWh, ProdPrognosisUpperMWh,
20 | SpotBlockConsPlanMWh, SpotBlockProdPlanMWh,
21 | SpotConsPlanMWh, SpotProdPlanMWh,
22 | Undefined );
23 |
24 | TUnitTypeV1 = ( DKK, MWh, Undefined );
25 |
26 | TDataStatus = ( Approved, Estimated, Manual, Missing, Undefined );
27 | {$SCOPEDENUMS OFF}
28 |
29 | TDatapoint = class
30 | Strict Private
31 | private
32 | FStartTime: TDateTime;
33 | FEndTime: TDateTime;
34 | FStatus: TDataStatus;
35 | FValue: Double;
36 | Public
37 | Property StartTime : TDateTime read FStartTime write FStartTime;
38 | Property EndTime : TDateTime read FEndTime write FEndTime;
39 | Property Status : TDataStatus read FStatus write FStatus;
40 | Property Value : Double read FValue write FValue;
41 | Constructor Create;
42 | end;
43 |
44 | TDatapointList = TObjectList;
45 |
46 | ProductionGroupDataSerieV1 = Class
47 | Strict private
48 | FType : TDataSerieTypeV1;
49 | FProductionGroupID : Integer;
50 | FUnitType : TUnitTypeV1;
51 | FUpdateTime : TDateTime;
52 | FDataPoints : TDatapointList;
53 | public
54 | Property &Type : TDataSerieTypeV1 read FType write FType;
55 | Property ProductionGroupID : Integer read FProductionGroupID write FProductionGroupID;
56 | Property UnitType : TUnitTypeV1 read FUnitType write FUnitType;
57 | Property UpdateTime : TDateTime read FUpdateTime write FUpdateTime;
58 | Property DataPoints : TDatapointList read FDataPoints;
59 | Constructor Create;
60 | Destructor Destroy; Override;
61 | End;
62 |
63 | //Exchange name: {Namespace/UnitName}.{ClassName}:{AssemblyName}
64 | // Neas.PowermanApi.Notifications.DTOs.V1.ProductionGroupDataSerieCollectionV1:Neas.PowermanApi.Notifications.DTOs
65 | [AssemblyName('Neas.PowermanApi.Notifications.DTOs')]
66 | ProductionGroupDataSerieCollectionV1 = Class( TObjectList )
67 | Public
68 | Constructor Create; Reintroduce;
69 | End;
70 |
71 | implementation
72 |
73 | Uses
74 | System.Math;
75 |
76 | { TDatapointList }
77 |
78 | constructor TDatapoint.Create;
79 | begin
80 | FStartTime := 0;
81 | FEndTime := 0;
82 | FStatus := TDataStatus.Undefined;
83 | FValue := NAN;
84 | end;
85 |
86 | { DataSerieV1 }
87 |
88 | constructor ProductionGroupDataSerieV1.Create;
89 | begin
90 | FType := TDataSerieTypeV1.Undefined;
91 | FProductionGroupID := -1;
92 | FUnitType := TUnitTypeV1.Undefined;
93 | FUpdateTime := 0;
94 | FDataPoints := TDatapointList.Create;
95 | end;
96 |
97 | destructor ProductionGroupDataSerieV1.Destroy;
98 | begin
99 | FDataPoints.Free;
100 | inherited;
101 | end;
102 |
103 | { ProductionGroupDataSerieCollectionV1 }
104 |
105 | constructor ProductionGroupDataSerieCollectionV1.Create;
106 | begin
107 | inherited Create( True );
108 | end;
109 |
110 | end.
111 |
--------------------------------------------------------------------------------
/EasyDelphiQ/Testbench/QTestbench.dpr:
--------------------------------------------------------------------------------
1 | // JCL_DEBUG_EXPERT_GENERATEJDBG OFF
2 | // JCL_DEBUG_EXPERT_INSERTJDBG OFF
3 | program QTestbench;
4 |
5 | uses
6 | Vcl.Forms,
7 | MainWin in 'MainWin.pas' {MainForm},
8 | Some.namespace in 'Some.namespace.pas',
9 | EasyDelphiQ.DTO in '..\EasyDelphiQ.DTO.pas',
10 | EasyDelphiQ in '..\EasyDelphiQ.pas',
11 | AMQP.Channel in '..\..\AMQP\Source\AMQP.Channel.pas',
12 | AMQP.Classes in '..\..\AMQP\Source\AMQP.Classes.pas',
13 | AMQP.Connection in '..\..\AMQP\Source\AMQP.Connection.pas',
14 | AMQP.Frame in '..\..\AMQP\Source\AMQP.Frame.pas',
15 | AMQP.Header in '..\..\AMQP\Source\AMQP.Header.pas',
16 | AMQP.Helper in '..\..\AMQP\Source\AMQP.Helper.pas',
17 | AMQP.Interfaces in '..\..\AMQP\Source\AMQP.Interfaces.pas',
18 | AMQP.Message in '..\..\AMQP\Source\AMQP.Message.pas',
19 | AMQP.MessageProperties in '..\..\AMQP\Source\AMQP.MessageProperties.pas',
20 | AMQP.Method in '..\..\AMQP\Source\AMQP.Method.pas',
21 | AMQP.Payload in '..\..\AMQP\Source\AMQP.Payload.pas',
22 | AMQP.Protocol in '..\..\AMQP\Source\AMQP.Protocol.pas',
23 | AMQP.StreamHelper in '..\..\AMQP\Source\AMQP.StreamHelper.pas',
24 | AMQP.Types in '..\..\AMQP\Source\AMQP.Types.pas',
25 | WinHttp_TLB in '..\..\JSON\WinHttp_TLB.pas',
26 | EasyDelphiQ.Interfaces in '..\EasyDelphiQ.Interfaces.pas',
27 | EasyDelphiQ.Classes in '..\EasyDelphiQ.Classes.pas',
28 | Neas.PowermanApi.Notifications.DTOs.V1 in 'Neas.PowermanApi.Notifications.DTOs.V1.pas',
29 | AMQP.IMessageProperties in '..\..\AMQP\Source\AMQP.IMessageProperties.pas',
30 | DJSON in '..\..\JSON\DJSON.pas',
31 | AMQP.Arguments in '..\..\AMQP\Source\AMQP.Arguments.pas';
32 |
33 | {$R *.res}
34 |
35 | begin
36 | Application.Initialize;
37 | Application.MainFormOnTaskbar := True;
38 | Application.Title := 'AMQP Testbench';
39 | Application.CreateForm(TMainForm, MainForm);
40 | Application.Run;
41 | end.
42 |
--------------------------------------------------------------------------------
/EasyDelphiQ/Testbench/QTestbench.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/EasyDelphiQ/Testbench/QTestbench.res
--------------------------------------------------------------------------------
/EasyDelphiQ/Testbench/Some.namespace.pas:
--------------------------------------------------------------------------------
1 | unit Some.namespace;
2 |
3 | interface
4 |
5 | Uses
6 | EasyDelphiQ.DTO;
7 |
8 | Type
9 | [AssemblyName('MyAssembly')]
10 | TestDTO = Class
11 | private
12 | FName: String;
13 | FID: Integer;
14 | Public
15 | Property ID : Integer read FID write FID;
16 | Property Name : String read FName write FName;
17 | Constructor Create;
18 | End;
19 |
20 | implementation
21 |
22 | { TestDTO }
23 |
24 | constructor TestDTO.Create;
25 | begin
26 | FID := 0;
27 | FName := '';
28 | end;
29 |
30 | end.
31 |
--------------------------------------------------------------------------------
/JSON/DTO.pas:
--------------------------------------------------------------------------------
1 | Unit DTO;
2 |
3 | Interface
4 |
5 | Uses
6 | System.Generics.Collections;
7 |
8 | Type
9 | TDatapointsItem = class
10 | Private
11 | FStartTimeUTC: String;
12 | FEndTimeUTC: String;
13 | FRepresentedCapacity: Integer;
14 | FValueMWh: Double;
15 | Public
16 | Property StartTimeUTC: String read FStartTimeUTC write FStartTimeUTC;
17 | Property EndTimeUTC: String read FEndTimeUTC write FEndTimeUTC;
18 | Property RepresentedCapacity: Integer read FRepresentedCapacity write FRepresentedCapacity;
19 | Property ValueMWh: Double read FValueMWh write FValueMWh;
20 | Constructor Create;
21 | End;
22 |
23 | TDTOItem = class
24 | Private
25 | FProductionGroupId: Integer;
26 | FType: String;
27 | FDatapoints: TObjectList;
28 | Public
29 | Property ProductionGroupId: Integer read FProductionGroupId write FProductionGroupId;
30 | Property &Type: String read FType write FType;
31 | Property Datapoints: TObjectList read FDatapoints;
32 | Constructor Create;
33 | Destructor Destroy; Override;
34 | End;
35 |
36 | Implementation
37 |
38 | { TDatapointsItem }
39 |
40 | Constructor TDatapointsItem.Create;
41 | Begin
42 | FStartTimeUTC := '';
43 | FEndTimeUTC := '';
44 | FRepresentedCapacity := 0;
45 | FValueMWh := 0;
46 | End;
47 |
48 | { TDTOItem }
49 |
50 | Constructor TDTOItem.Create;
51 | Begin
52 | FProductionGroupId := 0;
53 | FType := '';
54 | FDatapoints := TObjectList.Create;
55 | End;
56 |
57 | Destructor TDTOItem.Destroy;
58 | Begin
59 | FDatapoints.Free;
60 | Inherited;
61 | End;
62 |
63 | End.
64 |
65 |
--------------------------------------------------------------------------------
/JSON/JSON Samples/Nexus.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/JSON/JSON Samples/Nexus.txt
--------------------------------------------------------------------------------
/JSON/JSONProject.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {EF9AC729-89D7-48B7-BD8F-DCE9B2F0641C}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Default.Personality.12
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/JSON/Project1.dpr:
--------------------------------------------------------------------------------
1 | // JCL_DEBUG_EXPERT_GENERATEJDBG OFF
2 | // JCL_DEBUG_EXPERT_INSERTJDBG OFF
3 | program Project1;
4 |
5 | uses
6 | Vcl.Forms,
7 | Unit1 in 'Unit1.pas' {Form1},
8 | TimeseriesDTO in 'TimeseriesDTO.pas',
9 | uLkJSON in 'uLkJSON.pas',
10 | JSON in 'JSON.pas';
11 |
12 | {$R *.res}
13 |
14 | begin
15 | Application.Initialize;
16 | Application.MainFormOnTaskbar := True;
17 | Application.CreateForm(TForm1, Form1);
18 | Application.Run;
19 | end.
20 |
--------------------------------------------------------------------------------
/JSON/Project1.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {A081063B-60AA-46AE-B17D-278F14F1C272}
4 | 14.4
5 | VCL
6 | Project1.dpr
7 | True
8 | Debug
9 | Win32
10 | 1
11 | Application
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Cfg_1
34 | true
35 | true
36 |
37 |
38 | true
39 | Base
40 | true
41 |
42 |
43 | true
44 | Cfg_2
45 | true
46 | true
47 |
48 |
49 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
50 | $(BDS)\bin\delphi_PROJECTICON.ico
51 | .\$(Platform)\$(Config)
52 | .\$(Platform)\$(Config)
53 | false
54 | false
55 | false
56 | false
57 | false
58 |
59 |
60 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
61 | 1033
62 | true
63 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
64 | frx17;fs17;bindcompfmx;GR32_RSXE3;DBXSqliteDriver;vcldbx;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;TeeDB;bindcomp;inetdb;inetdbbde;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DBXOdbcDriver;DataSnapServer;Tee;iosPackage;DataSnapProviderClient;xmlrtl;DBXSybaseASEDriver;ibxpress;DbxCommonDriver;svnui;vclimg;IndyProtocols;DBXMySQLDriver;dbxcds;MetropolisUILiveTile;vclactnband;bindengine;vcldb;soaprtl;bindcompdbx;vcldsnap;bindcompvcl;FMXTee;TeeUI;vclie;GR32_DSGN_RSXE3;DBXDb2Driver;vcltouch;websnap;DBXOracleDriver;CustomIPTransport;vclribbon;VclSmp;dsnap;DBXInformixDriver;IndyIPServer;Intraweb;fmxase;vcl;DataSnapConnectors;IndyCore;CodeSiteExpressPkg;DBXMSSQLDriver;CloudService;DBXFirebirdDriver;dsnapcon;frxDB17;inet;fsDB17;fmxobj;FmxTeeUI;SynEdit_RXE3;IndyIPCommon;vclx;frxe17;inetdbxpress;webdsnap;svn;DBXSybaseASADriver;fmxdae;MiscCompPck;bdertl;dbexpress;DataSnapIndy10ServerTransport;adortl;IndyIPClient;$(DCC_UsePackage)
65 | $(BDS)\bin\default_app.manifest
66 |
67 |
68 | bindcompfmx;DBXSqliteDriver;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;TeeDB;bindcomp;inetdb;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DBXOdbcDriver;DataSnapServer;Tee;DataSnapProviderClient;xmlrtl;DBXSybaseASEDriver;ibxpress;DbxCommonDriver;vclimg;IndyProtocols;DBXMySQLDriver;dbxcds;MetropolisUILiveTile;vclactnband;bindengine;vcldb;soaprtl;bindcompdbx;vcldsnap;bindcompvcl;FMXTee;TeeUI;vclie;DBXDb2Driver;vcltouch;websnap;DBXOracleDriver;CustomIPTransport;vclribbon;VclSmp;dsnap;DBXInformixDriver;IndyIPServer;Intraweb;fmxase;vcl;DataSnapConnectors;IndyCore;DBXMSSQLDriver;CloudService;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FmxTeeUI;IndyIPCommon;vclx;inetdbxpress;webdsnap;DBXSybaseASADriver;fmxdae;dbexpress;DataSnapIndy10ServerTransport;adortl;IndyIPClient;$(DCC_UsePackage)
69 |
70 |
71 | DEBUG;$(DCC_Define)
72 | true
73 | false
74 | true
75 | true
76 | true
77 |
78 |
79 | true
80 | true
81 | true
82 | false
83 |
84 |
85 | false
86 | RELEASE;$(DCC_Define)
87 | 0
88 | false
89 |
90 |
91 | true
92 | true
93 | true
94 | true
95 |
96 |
97 |
98 | MainSource
99 |
100 |
101 |
102 | dfm
103 |
104 |
105 |
106 |
107 |
108 |
109 | Cfg_2
110 | Base
111 |
112 |
113 | Base
114 |
115 |
116 | Cfg_1
117 | Base
118 |
119 |
120 |
121 | Delphi.Personality.12
122 |
123 |
124 |
125 |
126 | False
127 | False
128 | 1
129 | 0
130 | 0
131 | 0
132 | False
133 | False
134 | False
135 | False
136 | False
137 | 1030
138 | 1252
139 |
140 |
141 |
142 |
143 | 1.0.0.0
144 |
145 |
146 |
147 |
148 |
149 | 1.0.0.0
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 | Project1.dpr
162 |
163 |
164 |
165 |
166 | True
167 | False
168 |
169 |
170 | 12
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/JSON/Sample1.dpr:
--------------------------------------------------------------------------------
1 | // JCL_DEBUG_EXPERT_GENERATEJDBG OFF
2 | // JCL_DEBUG_EXPERT_INSERTJDBG OFF
3 | program Sample1;
4 |
5 | uses
6 | //FastMM4,
7 | Vcl.Forms,
8 | Sample1Form in 'Sample1Form.pas' {Form1},
9 | TimeseriesDTO in 'TimeseriesDTO.pas',
10 | JSON in 'JSON.pas',
11 | JSON2DTO in 'JSON2DTO.pas',
12 | DTO in 'DTO.pas';
13 |
14 | {$R *.res}
15 |
16 | begin
17 | ReportMemoryLeaksOnShutdown := True;
18 | Application.Initialize;
19 | Application.MainFormOnTaskbar := True;
20 | Application.CreateForm(TForm1, Form1);
21 | Application.Run;
22 | end.
23 |
--------------------------------------------------------------------------------
/JSON/Sample1.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {A081063B-60AA-46AE-B17D-278F14F1C272}
4 | 16.1
5 | VCL
6 | Sample1.dpr
7 | True
8 | Debug
9 | Win32
10 | 1
11 | Application
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Cfg_1
34 | true
35 | true
36 |
37 |
38 | true
39 | Base
40 | true
41 |
42 |
43 | true
44 | Cfg_2
45 | true
46 | true
47 |
48 |
49 | Sample1
50 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
51 | $(BDS)\bin\delphi_PROJECTICON.ico
52 | .\$(Platform)\$(Config)
53 | .\$(Platform)\$(Config)
54 | false
55 | false
56 | false
57 | false
58 | false
59 |
60 |
61 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
62 | 1033
63 | true
64 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
65 | frx17;fs17;bindcompfmx;GR32_RSXE3;DBXSqliteDriver;vcldbx;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;TeeDB;bindcomp;inetdb;inetdbbde;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DBXOdbcDriver;DataSnapServer;Tee;iosPackage;DataSnapProviderClient;xmlrtl;DBXSybaseASEDriver;ibxpress;DbxCommonDriver;svnui;vclimg;IndyProtocols;DBXMySQLDriver;dbxcds;MetropolisUILiveTile;vclactnband;bindengine;vcldb;soaprtl;bindcompdbx;vcldsnap;bindcompvcl;FMXTee;TeeUI;vclie;GR32_DSGN_RSXE3;DBXDb2Driver;vcltouch;websnap;DBXOracleDriver;CustomIPTransport;vclribbon;VclSmp;dsnap;DBXInformixDriver;IndyIPServer;Intraweb;fmxase;vcl;DataSnapConnectors;IndyCore;CodeSiteExpressPkg;DBXMSSQLDriver;CloudService;DBXFirebirdDriver;dsnapcon;frxDB17;inet;fsDB17;fmxobj;FmxTeeUI;SynEdit_RXE3;IndyIPCommon;vclx;frxe17;inetdbxpress;webdsnap;svn;DBXSybaseASADriver;fmxdae;MiscCompPck;bdertl;dbexpress;DataSnapIndy10ServerTransport;adortl;IndyIPClient;$(DCC_UsePackage)
66 | $(BDS)\bin\default_app.manifest
67 |
68 |
69 | bindcompfmx;DBXSqliteDriver;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;TeeDB;bindcomp;inetdb;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DBXOdbcDriver;DataSnapServer;Tee;DataSnapProviderClient;xmlrtl;DBXSybaseASEDriver;ibxpress;DbxCommonDriver;vclimg;IndyProtocols;DBXMySQLDriver;dbxcds;MetropolisUILiveTile;vclactnband;bindengine;vcldb;soaprtl;bindcompdbx;vcldsnap;bindcompvcl;FMXTee;TeeUI;vclie;DBXDb2Driver;vcltouch;websnap;DBXOracleDriver;CustomIPTransport;vclribbon;VclSmp;dsnap;DBXInformixDriver;IndyIPServer;Intraweb;fmxase;vcl;DataSnapConnectors;IndyCore;DBXMSSQLDriver;CloudService;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FmxTeeUI;IndyIPCommon;vclx;inetdbxpress;webdsnap;DBXSybaseASADriver;fmxdae;dbexpress;DataSnapIndy10ServerTransport;adortl;IndyIPClient;$(DCC_UsePackage)
70 |
71 |
72 | DEBUG;$(DCC_Define)
73 | true
74 | false
75 | true
76 | true
77 | true
78 |
79 |
80 | true
81 | true
82 | true
83 | false
84 |
85 |
86 | false
87 | RELEASE;$(DCC_Define)
88 | 0
89 | 0
90 |
91 |
92 | true
93 | true
94 | true
95 | true
96 |
97 |
98 |
99 | MainSource
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | Cfg_2
111 | Base
112 |
113 |
114 | Base
115 |
116 |
117 | Cfg_1
118 | Base
119 |
120 |
121 |
122 | Delphi.Personality.12
123 |
124 |
125 |
126 |
127 | False
128 | False
129 | 1
130 | 0
131 | 0
132 | 0
133 | False
134 | False
135 | False
136 | False
137 | False
138 | 1030
139 | 1252
140 |
141 |
142 |
143 |
144 | 1.0.0.0
145 |
146 |
147 |
148 |
149 |
150 | 1.0.0.0
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | Sample1.dpr
163 |
164 |
165 |
166 |
167 | True
168 | False
169 |
170 |
171 | C:\Users\Jesper\Documents\RAD Studio\Projects\JSON\Test\Sample1Tests.dproj
172 |
173 |
174 | 12
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/JSON/Sample1.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/JSON/Sample1.res
--------------------------------------------------------------------------------
/JSON/Sample1Form.pas:
--------------------------------------------------------------------------------
1 | unit Sample1Form;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
7 | Vcl.Controls, Vcl.StdCtrls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids, Vcl.ExtCtrls, System.Generics.Collections,
8 | System.Diagnostics, TimeseriesDTO, DJSON;
9 |
10 | type
11 | TStuff = Class
12 | strict private
13 | FName: String;
14 | FNumber: Integer;
15 | FIDList: TList;
16 | FLines: TStringList;
17 | private
18 | FADate: TDatetime;
19 | Public
20 | Property Name: String read FName write FName;
21 | Property Number: Integer read FNumber write FNumber;
22 | Property ADate: TDatetime read FADate write FADate;
23 | Property IDList: TList read FIDList;
24 | Property Lines: TStringList read FLines;
25 | Constructor Create;
26 | Destructor Destroy; Override;
27 | End;
28 |
29 | TEnum = ( eBobby, eThomas, eKurt );
30 |
31 | TOuter = Class
32 | strict private
33 | FItems: TObjectList;
34 | FKind: Integer;
35 | FContent: String;
36 | private
37 | FSomeBool: Boolean;
38 | FNameEnum: TEnum;
39 | Public
40 | Property Content: String read FContent write FContent;
41 | Property Kind: Integer read FKind write FKind;
42 | Property NameEnum: TEnum read FNameEnum write FNameEnum;
43 | Property SomeBool: Boolean read FSomeBool write FSomeBool;
44 | Property Items: TObjectList read FItems;
45 | Constructor Create;
46 | Destructor Destroy; Override;
47 | End;
48 |
49 | TForm1 = class(TForm)
50 | Memo1: TMemo;
51 | MemoJSON: TMemo;
52 | ButtonJSONToList: TButton;
53 | ButtonParseToObjectSpeed: TButton;
54 | ButtonParseSpeed: TButton;
55 | StringGrid1: TStringGrid;
56 | ButtonJSONToObject: TButton;
57 | Label1: TLabel;
58 | Label2: TLabel;
59 | LabelProductionGroupID: TLabel;
60 | LabelType: TLabel;
61 | ListBox1: TListBox;
62 | ButtonClear: TButton;
63 | Bevel1: TBevel;
64 | Bevel2: TBevel;
65 | ButtonGet: TButton;
66 | EditURL: TEdit;
67 | ButtonURLToObject: TButton;
68 | Button1: TButton;
69 | Button2: TButton;
70 | Button3: TButton;
71 | Button4: TButton;
72 | procedure FormCreate(Sender: TObject);
73 | procedure ButtonJSONToObjectClick(Sender: TObject);
74 | procedure ButtonJSONToListClick(Sender: TObject);
75 | procedure ButtonParseToObjectSpeedClick(Sender: TObject);
76 | procedure ButtonParseSpeedClick(Sender: TObject);
77 | procedure ButtonClearClick(Sender: TObject);
78 | procedure FormDestroy(Sender: TObject);
79 | procedure ListBox1Click(Sender: TObject);
80 | procedure ButtonGetClick(Sender: TObject);
81 | procedure ButtonURLToObjectClick(Sender: TObject);
82 | procedure Button1Click(Sender: TObject);
83 | procedure Button2Click(Sender: TObject);
84 | procedure Button3Click(Sender: TObject);
85 | procedure Button4Click(Sender: TObject);
86 | private
87 | List: TObjectList;
88 | procedure ClearList;
89 | public
90 | Procedure AddTimeseries( TimeSeries: TTimeseries );
91 | Procedure Show( Timeseries: TTimeseries ); Overload;
92 | end;
93 |
94 | var
95 | Form1: TForm1;
96 |
97 | implementation
98 |
99 | Uses
100 | System.DateUtils, JSON2DTO;
101 |
102 | {$R *.dfm}
103 |
104 | { TForm1 }
105 |
106 | procedure TForm1.AddTimeseries(TimeSeries: TTimeseries);
107 | begin
108 | List.Add( TimeSeries );
109 | ListBox1.ItemIndex := ListBox1.Items.Add( IntToStr(TimeSeries.ProductionGroupID) + ' : ' + TimeSeries.&Type );
110 | Show( TimeSeries );
111 | end;
112 |
113 | procedure TForm1.ButtonJSONToListClick(Sender: TObject);
114 | var
115 | TS: TTimeseries;
116 | Timer: TStopwatch;
117 | begin
118 | ClearList;
119 | Memo1.Lines.Clear;
120 | Timer := TStopwatch.StartNew;
121 | TJSONParser.Parse( MemoJSON.Text, List ); { <--- The magic! }
122 | Memo1.Lines.Add( 'Parsing: ' + IntToStr(Timer.ElapsedMilliseconds) + ' ms.' );
123 | for TS in List do
124 | ListBox1.Items.Add( IntToStr(TS.ProductionGroupID) + ' : ' + TS.&Type );
125 | ListBox1.ItemIndex := -1;
126 | end;
127 |
128 | procedure TForm1.ButtonGetClick(Sender: TObject);
129 | begin
130 | MemoJSON.Text := TJSON.Get( EditURL.Text );
131 | end;
132 |
133 | procedure TForm1.Button1Click(Sender: TObject);
134 | begin
135 | Memo1.Clear;
136 | TDTOGenerator.Parse( MemoJSON.Text, 'Imported', 'DTO.Imported', Memo1.Lines, '' );
137 | end;
138 |
139 | procedure TForm1.Button2Click(Sender: TObject);
140 | begin
141 | MemoJSON.Clear;
142 | MemoJSON.Lines.Add( '{' );
143 | MemoJSON.Lines.Add( ' "ID": 45,' );
144 | MemoJSON.Lines.Add( ' "Source":' );
145 | MemoJSON.Lines.Add( ' {' );
146 | MemoJSON.Lines.Add( ' "ID": 14,' );
147 | MemoJSON.Lines.Add( ' "Value": 0.0,' );
148 | MemoJSON.Lines.Add( ' "Name": "Jesper",' );
149 | MemoJSON.Lines.Add( ' "Alias": "Ripper"' );
150 | MemoJSON.Lines.Add( ' }' );
151 | // MemoJSON.Lines.Add( ' "Timeseries":' );
152 | // MemoJSON.Lines.Add( ' [' );
153 | // MemoJSON.Lines.Add( ' { "Timestamp": "2015-01-01T00:00", "Value": 45.98 },' );
154 | // MemoJSON.Lines.Add( ' { "Timestamp": "2015-01-01T00:15", "Value": 13.12 }' );
155 | // MemoJSON.Lines.Add( ' ]' );
156 | MemoJSON.Lines.Add( '}' );
157 | end;
158 |
159 | procedure TForm1.Button3Click(Sender: TObject);
160 | var
161 | JSON: TJSON_Element;
162 | begin
163 | MemoJSON.Text := TJSON.Get( 'http://itunes.apple.com/search?term=metallica' );
164 | //Pretty print
165 | JSON := nil;
166 | Try
167 | JSON := TJSON.ParseText( MemoJSON.Text );
168 | MemoJSON.Text := JSON.ToJSON;
169 | Finally
170 | JSON.Free;
171 | End;
172 | end;
173 |
174 | procedure TForm1.Button4Click(Sender: TObject);
175 | var
176 | JSON: TJSON_Element;
177 | begin
178 | MemoJSON.Text := TJSON.Get( 'http://lyrics.wikia.com/api.php?artist=Metallica&fmt=json' );
179 | //Pretty print
180 | JSON := nil;
181 | Try
182 | JSON := TJSON.ParseText( MemoJSON.Text );
183 | MemoJSON.Text := JSON.ToJSON;
184 | Finally
185 | JSON.Free;
186 | End;
187 | end;
188 |
189 | procedure TForm1.ButtonClearClick(Sender: TObject);
190 | begin
191 | ClearList;
192 | end;
193 |
194 | procedure TForm1.ButtonParseToObjectSpeedClick(Sender: TObject);
195 | Const
196 | Cnt = 100;
197 | Var
198 | i: Integer;
199 | Timeseries: TTimeseries;
200 | Timer: TStopwatch;
201 | begin
202 | Memo1.Lines.Clear;
203 | Timeseries := nil;
204 | Try
205 | Timer := TStopwatch.StartNew;
206 | for i := 1 to Cnt do
207 | Begin
208 | Timeseries.Free;
209 | Timeseries := TTimeseries.Create;
210 | TJSONParser.Parse( MemoJSON.Text, Timeseries ); { <--- The magic! }
211 | End;
212 | Memo1.Lines.Add( 'Parsing: ' + FloatToStrF(Timer.ElapsedMilliseconds/Cnt, ffFixed, 10, 3) + ' ms. (avg.)' );
213 | Show( Timeseries );
214 | Finally
215 | Timeseries.Free;
216 | End;
217 | end;
218 |
219 | procedure TForm1.ButtonURLToObjectClick(Sender: TObject);
220 | var
221 | TS: TTimeseries;
222 | begin
223 | ClearList;
224 | TJSON.Get( EditURL.text, List );
225 | for TS in List do
226 | ListBox1.Items.Add( IntToStr(TS.ProductionGroupID) + ' : ' + TS.&Type );
227 | ListBox1.ItemIndex := -1;
228 | end;
229 |
230 | procedure TForm1.ButtonParseSpeedClick(Sender: TObject);
231 | Const
232 | Cnt = 1000;
233 | var
234 | J: TJSON_Element;
235 | Timer: TStopwatch;
236 | i: Integer;
237 | JSON: String;
238 | begin
239 | Memo1.Lines.Clear;
240 | JSON := MemoJSON.Text;
241 | J:= nil;
242 | Timer := TStopwatch.StartNew;
243 | for i := 1 to Cnt do
244 | Begin
245 | J.Free;
246 | J := TJSON.ParseText( JSON );
247 | End;
248 | With Memo1.Lines do
249 | Try
250 | BeginUpdate;
251 | Add( 'JSON Parsing: ' + FloatToStrF(Timer.ElapsedMilliseconds/Cnt, ffFixed, 10, 3) + ' ms. (avg.)' );
252 | If J.SelfType = jtObject then
253 | Add( 'Object' )
254 | else If (J.SelfType = jtArray) and
255 | (TJSON_Array(J).Count = 1) and
256 | (TJSON_Array(J).Elements[0].SelfType = jtObject) then
257 | Add( 'Object (in Array)' )
258 | else If (J.SelfType = jtArray) then
259 | Add( 'Array' );
260 | Add('');
261 | Add('Re-serialized:');
262 | Add( J.ToJSON );
263 | Finally
264 | EndUpdate;
265 | J.Free;
266 | End;
267 | end;
268 |
269 | procedure TForm1.Show(Timeseries: TTimeseries);
270 | var
271 | Datapoint: TDatapoint;
272 | Row: Integer;
273 | begin
274 | LabelProductionGroupID.Caption := IntToStr(Timeseries.ProductionGroupID);
275 | LabelType.Caption := Timeseries.&Type;
276 | StringGrid1.RowCount := 1 + Timeseries.Datapoints.Count;
277 | Row := 1;
278 | for Datapoint in Timeseries.Datapoints do
279 | Begin
280 | StringGrid1.Cells[0,Row] := DateTimeToStr(Datapoint.StartTimeUTC);
281 | StringGrid1.Cells[1,Row] := DateTimeToStr(Datapoint.EndTimeUTC);
282 | StringGrid1.Cells[2,Row] := FloatToStr(Datapoint.RepresentedCapacity);
283 | StringGrid1.Cells[3,Row] := FloatToStr(Datapoint.ValueMWh);
284 | Inc(Row);
285 | End;
286 | end;
287 |
288 | procedure TForm1.ClearList;
289 | begin
290 | List.Clear;
291 | ListBox1.Clear;
292 | StringGrid1.RowCount := 2;
293 | StringGrid1.Rows[0].CommaText := '"Start time","End time","Capacity","Value (MWh)"';
294 | StringGrid1.Rows[1].CommaText := '';
295 | end;
296 |
297 | procedure TForm1.FormCreate(Sender: TObject);
298 | begin
299 | ReportMemoryLeaksOnShutdown := True;
300 | List := TObjectList.Create;
301 | ClearList;
302 | end;
303 |
304 | procedure TForm1.FormDestroy(Sender: TObject);
305 | begin
306 | List.Free;
307 | end;
308 |
309 | procedure TForm1.ListBox1Click(Sender: TObject);
310 | begin
311 | if ListBox1.ItemIndex <> -1 then
312 | Show( List[ ListBox1.ItemIndex ] );
313 | end;
314 |
315 | procedure TForm1.ButtonJSONToObjectClick(Sender: TObject);
316 | var
317 | TimeSeries: TTimeseries;
318 | begin
319 | TimeSeries := TTimeseries.Create;
320 | TJSONParser.Parse( MemoJSON.Text, TimeSeries );
321 | AddTimeseries( TimeSeries );
322 | Show( TimeSeries );
323 | Memo1.Text := TJSONSerializer.Serialize(TimeSeries);
324 | end;
325 |
326 | { TStuff }
327 |
328 | constructor TStuff.Create;
329 | begin
330 | FName := '';
331 | FNumber := 0;
332 | FIDList := TList.Create;
333 | FLines := TStringList.Create;
334 | FADate := EncodeDateTime( 2014, 02, 15, 06, 15, 00, 0 );
335 | end;
336 |
337 | destructor TStuff.Destroy;
338 | begin
339 | FIDList.Free;
340 | FLines.Free;
341 | inherited;
342 | end;
343 |
344 | { TOuter }
345 |
346 | constructor TOuter.Create;
347 | begin
348 | FKind := 0;
349 | FContent := '';
350 | FItems := TObjectList.Create;
351 | FSomeBool := True;
352 | FNameEnum := eThomas;
353 | end;
354 |
355 | destructor TOuter.Destroy;
356 | begin
357 | FItems.Free;
358 | inherited;
359 | end;
360 |
361 | end.
362 |
363 |
--------------------------------------------------------------------------------
/JSON/Test/Sample1Tests.dpr:
--------------------------------------------------------------------------------
1 | program Sample1Tests;
2 |
3 | {$IFDEF CONSOLE_TESTRUNNER}
4 | {$APPTYPE CONSOLE}
5 | {$ENDIF}
6 |
7 | uses
8 | FastMM4,
9 | DUnitTestRunner,
10 | TestJSON in 'TestJSON.pas',
11 | DJSON in '..\DJSON.pas',
12 | TestObjects in 'TestObjects.pas',
13 | WinHttp_TLB in '..\WinHttp_TLB.pas';
14 |
15 | {R *.RES}
16 |
17 | begin
18 | DUnitTestRunner.RunRegisteredTests;
19 | end.
20 |
21 |
--------------------------------------------------------------------------------
/JSON/Test/TestObjects.pas:
--------------------------------------------------------------------------------
1 | unit TestObjects;
2 |
3 | interface
4 |
5 | Uses
6 | System.Generics.Collections, System.Classes;
7 |
8 | Type
9 | TEnum = (First, Middle, Last);
10 |
11 | TSimple = Class
12 | private
13 | FInt: Integer;
14 | FC: Char;
15 | FDay: TDate;
16 | FStr: String;
17 | FTimestamp: TDateTime;
18 | FNumber: Double;
19 | FBool: Boolean;
20 | FInt64: Int64;
21 | FWord: Word;
22 | FByte: Byte;
23 | FEnum: TEnum;
24 | Public
25 | Property Str: String read FStr write FStr;
26 | Property C: Char read FC write FC;
27 | Property Int: Integer read FInt write FInt;
28 | Property Bool: Boolean read FBool write FBool;
29 | Property Number: Double read FNumber write FNumber;
30 | Property Day: TDate read FDay write FDay;
31 | Property Timestamp: TDateTime read FTimestamp write FTimestamp;
32 | Property Enum: TEnum read FEnum write FEnum;
33 | Property AByte: Byte read FByte write FByte;
34 | Property AWord: Word read FWord write FWord;
35 | Property AInt64: Int64 read FInt64 write FInt64;
36 | Constructor Create;
37 | End;
38 |
39 | TSimpleLists = Class
40 | private
41 | FInt : TList;
42 | FC : TList;
43 | FDay : TList;
44 | FStr : TList;
45 | FTimestamp : TList;
46 | FNumber : TList;
47 | FBool : TList;
48 | FStrList : TStringList;
49 | Public
50 | Property Str : TList read FStr;
51 | Property StrList : TStringList read FStrList;
52 | Property C : TList read FC;
53 | Property Int : TList read FInt;
54 | Property Bool : TList read FBool;
55 | Property Number : TList read FNumber;
56 | Property Day : TList read FDay;
57 | Property Timestamp : TList read FTimestamp;
58 | Constructor Create;
59 | Destructor Destroy; Override;
60 | End;
61 |
62 | TSimpleContainer = Class
63 | private
64 | FName: String;
65 | FObjects: TObjectList;
66 | Public
67 | Property Name: String read FName write FName;
68 | Property Objects: TObjectList read FObjects write FObjects;
69 | Constructor Create;
70 | Destructor Destroy; Override;
71 | End;
72 |
73 | implementation
74 |
75 | Uses
76 | System.SysUtils, System.DateUtils;
77 |
78 | { TSimple }
79 |
80 | constructor TSimple.Create;
81 | begin
82 | FInt := 0;
83 | FC := 'A';
84 | FDay := EncodeDate( 2014, 1, 1 );
85 | FTimestamp := EncodeDateTime( 2014, 1, 1, 0, 0, 0, 0 );
86 | FStr := '';
87 | FNumber := 0;
88 | FBool := False;
89 | FInt64 := 0;
90 | FWord := 0;
91 | FByte := 0;
92 | FEnum := First;
93 | end;
94 |
95 | { TSimpleLists }
96 |
97 | constructor TSimpleLists.Create;
98 | begin
99 | FInt := TList.Create;
100 | FC := TList.Create;
101 | FDay := TList.Create;
102 | FStr := TList.Create;
103 | FStrList := TStringList.Create;
104 | FTimestamp := TList.Create;
105 | FNumber := TList.Create;
106 | FBool := TList.Create;
107 | end;
108 |
109 | destructor TSimpleLists.Destroy;
110 | begin
111 | FInt.Free;
112 | FC.Free;
113 | FDay.Free;
114 | FStr.Free;
115 | FStrList.Free;
116 | FTimestamp.Free;
117 | FNumber.Free;
118 | FBool.Free;
119 | inherited;
120 | end;
121 |
122 | { TSimpleContainer }
123 |
124 | constructor TSimpleContainer.Create;
125 | begin
126 | FName := '';
127 | FObjects := TObjectList.Create;
128 | end;
129 |
130 | destructor TSimpleContainer.Destroy;
131 | begin
132 | FObjects.Free;
133 | inherited;
134 | end;
135 |
136 | end.
137 |
--------------------------------------------------------------------------------
/JSON/TimeseriesDTO.pas:
--------------------------------------------------------------------------------
1 | unit TimeseriesDTO;
2 |
3 | interface
4 |
5 | Uses
6 | System.Classes, System.Generics.Collections;
7 |
8 | Type
9 | TDatapoint = Class
10 | private
11 | FStartTimeUTC: TDateTime;
12 | FEndTimeUTC: TDateTime;
13 | FRepresentedCapacity: Double;
14 | FValueMWh: Double;
15 | Public
16 | Property StartTimeUTC: TDateTime read FStartTimeUTC write FStartTimeUTC;
17 | Property EndTimeUTC: TDateTime read FEndTimeUTC write FEndTimeUTC;
18 | Property RepresentedCapacity: Double read FRepresentedCapacity write FRepresentedCapacity;
19 | Property ValueMWh: Double read FValueMWh write FValueMWh;
20 | Constructor Create;
21 | End;
22 |
23 | TTimeseries = Class
24 | private
25 | FProductionGroupID: Integer;
26 | FType: String;
27 | FDatapoints: TObjectList;
28 | Public
29 | Property ProductionGroupID: Integer read FProductionGroupID write FProductionGroupID;
30 | Property &Type: String read FType write FType;
31 | Property Datapoints: TObjectList read FDatapoints;
32 | Constructor Create;
33 | Destructor Destroy; Override;
34 | End;
35 |
36 | implementation
37 |
38 | Uses
39 | System.Math;
40 |
41 | { TDatapoint }
42 |
43 | constructor TDatapoint.Create;
44 | begin
45 | FStartTimeUTC := 0;
46 | FEndTimeUTC := 0;
47 | FRepresentedCapacity := NAN;
48 | FValueMWh := NAN;
49 | end;
50 |
51 | { TTimeseries }
52 |
53 | constructor TTimeseries.Create;
54 | begin
55 | FType := '';
56 | FProductionGroupID := 0;
57 | FDatapoints := TObjectList.Create;
58 | end;
59 |
60 | destructor TTimeseries.Destroy;
61 | begin
62 | FDatapoints.Free;
63 | inherited;
64 | end;
65 |
66 | end.
67 |
--------------------------------------------------------------------------------
/JSON/Wizard/JSON.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/JSON/Wizard/JSON.bmp
--------------------------------------------------------------------------------
/JSON/Wizard/JSON.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/JSON/Wizard/JSON.ico
--------------------------------------------------------------------------------
/JSON/Wizard/JSON.rc:
--------------------------------------------------------------------------------
1 | JSONDTOCODE RCDATA JSONDTO.TXT
2 | JSONICON ICON JSONFile.ICO
3 |
4 |
--------------------------------------------------------------------------------
/JSON/Wizard/JSONDTO.txt:
--------------------------------------------------------------------------------
1 | program %s;
2 |
3 | uses
4 | Forms;
5 |
6 | {$R *.res}
7 |
8 | begin
9 | Application.Initialize;
10 | Application.Run;
11 | end.
12 | |unit %s;
13 |
14 | interface
15 |
16 | uses
17 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
18 | Dialogs;
19 |
20 | type
21 | T%s = class(T%s)
22 | private
23 | { Private declarations }
24 | public
25 | { Public declarations }
26 | end;
27 |
28 | var
29 | %1:s: T%1:s;
30 |
31 | implementation
32 |
33 | {$R *.dfm}
34 |
35 |
36 | end.
37 | |
38 | |
39 |
--------------------------------------------------------------------------------
/JSON/Wizard/JSONDTOExpt.pas:
--------------------------------------------------------------------------------
1 | unit JSONDTOExpt;
2 |
3 | interface
4 |
5 | procedure Register;
6 |
7 | implementation
8 |
9 | uses
10 | System.Classes, System.SysUtils, WinAPI.Windows, VCL.Dialogs, ToolsApi, WizardWin;
11 |
12 | {$R JSON.res}
13 |
14 | type
15 | TGxModuleCreatorWizard = class( TNotifierObject, IOTAWizard, IOTARepositoryWizard,
16 | IOTARepositoryWizard60, IOTARepositoryWizard80, IOTAFormWizard)
17 | public
18 | // IOTAWizard
19 | function GetIDString: string;
20 | function GetName: string;
21 | function GetState: TWizardState;
22 | procedure Execute;
23 | // IOTARepositoryWizard
24 | function GetAuthor: string;
25 | function GetComment: string;
26 | function GetPage: string;
27 | function GetGlyph: Cardinal;
28 | // IOTARepositoryWizard60
29 | function GetDesigner: string;
30 | // IOTARepositoryWizard80
31 | function GetPersonality: string;
32 | function GetGalleryCategory: IOTAGalleryCategory;
33 | end;
34 |
35 | TGxModuleCreator = class(TInterfacedObject, IOTACreator, IOTAModuleCreator)
36 | private
37 | FSource: String;
38 | public
39 | // IOTACreator
40 | function GetCreatorType: string;
41 | function GetExisting: Boolean;
42 | function GetFileSystem: string;
43 | function GetOwner: IOTAModule;
44 | function GetUnnamed: Boolean;
45 | // IOTAModuleCreator
46 | function GetAncestorName: string;
47 | function GetImplFileName: string;
48 | function GetIntfFileName: string;
49 | function GetFormName: string;
50 | function GetMainForm: Boolean;
51 | function GetShowForm: Boolean;
52 | function GetShowSource: Boolean;
53 | function NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile;
54 | function NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
55 | function NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
56 | procedure FormCreated(const FormEditor: IOTAFormEditor);
57 | Constructor Create( ASource: String ); Reintroduce;
58 | end;
59 |
60 | TGxSourceFile = class(TInterfacedObject, IOTAFile)
61 | private
62 | FSource: string;
63 | public
64 | function GetSource: string;
65 | function GetAge: TDateTime;
66 | constructor Create(const Source: string);
67 | end;
68 |
69 |
70 | { TGxModuleCreatorWizard }
71 |
72 | procedure TGxModuleCreatorWizard.Execute;
73 | var
74 | Source: String;
75 | begin
76 | WizardForm := TWizardForm.Create(nil);
77 | Try
78 | Source := WizardForm.Execute;
79 | if Source <> '' then
80 | (BorlandIDEServices as IOTAModuleServices).CreateModule(TGxModuleCreator.Create(Source));
81 | Finally
82 | WizardForm.Free;
83 | End;
84 | end;
85 |
86 | function TGxModuleCreatorWizard.GetAuthor: string;
87 | begin
88 | Result := 'Jesper B. Christensen';
89 | end;
90 |
91 | function TGxModuleCreatorWizard.GetComment: string;
92 | begin
93 | Result := 'JSON DTO Importer';
94 | end;
95 |
96 | function TGxModuleCreatorWizard.GetDesigner: string;
97 | begin
98 | Result := dVCL;
99 | end;
100 |
101 | function TGxModuleCreatorWizard.GetGalleryCategory: IOTAGalleryCategory;
102 | var
103 | Category: IOTAGalleryCategory;
104 | CatManager: IOTAGalleryCategoryManager;
105 | begin
106 | CatManager := (BorlandIDEServices as IOTAGalleryCategoryManager);
107 | Assert(Assigned(CatManager));
108 | Category := CatManager.FindCategory(sCategoryDelphiNewFiles);
109 | Assert(Assigned(Category));
110 | Result := Category;
111 | end;
112 |
113 | function TGxModuleCreatorWizard.GetPersonality: string;
114 | begin
115 | Result := sDelphiPersonality;
116 | end;
117 |
118 | function TGxModuleCreatorWizard.GetGlyph: Cardinal;
119 | begin
120 | Result := LoadIcon(HInstance, 'JSONICON');
121 | end;
122 |
123 | function TGxModuleCreatorWizard.GetIDString: string;
124 | begin
125 | Result := 'JBC.JSONDTOCreatorWizard';
126 | end;
127 |
128 | function TGxModuleCreatorWizard.GetName: string;
129 | begin
130 | Result := 'JSON DTO Importer';
131 | end;
132 |
133 | function TGxModuleCreatorWizard.GetPage: string;
134 | begin
135 | Result := 'New';
136 | end;
137 |
138 | function TGxModuleCreatorWizard.GetState: TWizardState;
139 | begin
140 | Result := [wsEnabled];
141 | end;
142 |
143 | { TGxModuleCreator }
144 |
145 | constructor TGxModuleCreator.Create( ASource: String );
146 | begin
147 | inherited Create;
148 | FSource := ASource;
149 | end;
150 |
151 | procedure TGxModuleCreator.FormCreated(const FormEditor: IOTAFormEditor);
152 | begin
153 | // Nothing
154 | end;
155 |
156 | function TGxModuleCreator.GetAncestorName: string;
157 | begin
158 | Result := '';
159 | end;
160 |
161 | function TGxModuleCreator.GetCreatorType: string;
162 | begin
163 | // Return sUnit or sText as appropriate
164 | Result := sUnit;
165 | end;
166 |
167 | function TGxModuleCreator.GetExisting: Boolean;
168 | begin
169 | Result := False;
170 | end;
171 |
172 | function TGxModuleCreator.GetFileSystem: string;
173 | begin
174 | Result := '';
175 | end;
176 |
177 | function TGxModuleCreator.GetFormName: string;
178 | begin
179 | Result := '';
180 | end;
181 |
182 | function TGxModuleCreator.GetImplFileName: string;
183 | begin
184 | // Result := 'NewDTO.pas';
185 | Result := '';
186 | end;
187 |
188 | function TGxModuleCreator.GetIntfFileName: string;
189 | begin
190 | Result := '';
191 | end;
192 |
193 | function TGxModuleCreator.GetMainForm: Boolean;
194 | begin
195 | Result := False;
196 | end;
197 |
198 | function TGxModuleCreator.GetOwner: IOTAModule;
199 | //var
200 | // ModuleServices: IOTAModuleServices;
201 | // Module: IOTAModule;
202 | // NewModule: IOTAModule;
203 | begin
204 | Result := (BorlandIDEServices as IOTAModuleServices).GetActiveProject;
205 | // You may prefer to return the project group's ActiveProject instead
206 | // Result := nil;
207 | // ModuleServices := (BorlandIDEServices as IOTAModuleServices);
208 | // Module := ModuleServices.CurrentModule;
209 | //
210 | // if Module <> nil then
211 | // begin
212 | // if Module.QueryInterface(IOTAProject, NewModule) = S_OK then
213 | // Result := NewModule
214 | //
215 | // else if Module.OwnerModuleCount > 0 then
216 | // begin
217 | // NewModule := Module.OwnerModules[0];
218 | // if NewModule <> nil then
219 | // if NewModule.QueryInterface(IOTAProject, Result) <> S_OK then
220 | // Result := nil;
221 | // end;
222 | // end;
223 | end;
224 |
225 | function TGxModuleCreator.GetShowForm: Boolean;
226 | begin
227 | Result := False;
228 | end;
229 |
230 | function TGxModuleCreator.GetShowSource: Boolean;
231 | begin
232 | Result := True;
233 | end;
234 |
235 | function TGxModuleCreator.GetUnnamed: Boolean;
236 | begin
237 | Result := True;
238 | end;
239 |
240 | function TGxModuleCreator.NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile;
241 | begin
242 | Result := nil;
243 | end;
244 |
245 | function TGxModuleCreator.NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
246 | begin
247 | Result := TGxSourceFile.Create(Format(FSource, [ModuleIdent, FormIdent,
248 | AncestorIdent, FormIdent, FormIdent]));
249 | end;
250 |
251 | function TGxModuleCreator.NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
252 | begin
253 | Result := nil;
254 | end;
255 |
256 | { TGxSourceFile }
257 |
258 | constructor TGxSourceFile.Create(const Source: string);
259 | begin
260 | FSource := Source;
261 | end;
262 |
263 | function TGxSourceFile.GetAge: TDateTime;
264 | begin
265 | Result := -1;
266 | end;
267 |
268 | function TGxSourceFile.GetSource: string;
269 | begin
270 | Result := FSource;
271 | end;
272 |
273 | procedure Register;
274 | begin
275 | RegisterPackageWizard(TGxModuleCreatorWizard.Create);
276 | end;
277 |
278 |
279 | initialization
280 | // InitModuleSources;
281 | finalization
282 | // DoneModuleSources;
283 | end.
284 |
--------------------------------------------------------------------------------
/JSON/Wizard/JSONDTOWiz.dpk:
--------------------------------------------------------------------------------
1 |
2 | //---------------------------------------------------------------------------
3 |
4 | // This software is Copyright (c) 2011 Embarcadero Technologies, Inc.
5 | // You may only use this software if you are an authorized licensee
6 | // of Delphi, C++Builder or RAD Studio (Embarcadero Products).
7 | // This software is considered a Redistributable as defined under
8 | // the software license agreement that comes with the Embarcadero Products
9 | // and is subject to that software license agreement.
10 |
11 | //---------------------------------------------------------------------------
12 | // JCL_DEBUG_EXPERT_GENERATEJDBG OFF
13 | // JCL_DEBUG_EXPERT_INSERTJDBG OFF
14 | package JSONDTOWiz;
15 |
16 | {$R *.res}
17 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
18 | {$ALIGN 8}
19 | {$ASSERTIONS ON}
20 | {$BOOLEVAL OFF}
21 | {$DEBUGINFO ON}
22 | {$EXTENDEDSYNTAX ON}
23 | {$IMPORTEDDATA ON}
24 | {$IOCHECKS ON}
25 | {$LOCALSYMBOLS ON}
26 | {$LONGSTRINGS ON}
27 | {$OPENSTRINGS ON}
28 | {$OPTIMIZATION ON}
29 | {$OVERFLOWCHECKS OFF}
30 | {$RANGECHECKS OFF}
31 | {$REFERENCEINFO ON}
32 | {$SAFEDIVIDE OFF}
33 | {$STACKFRAMES OFF}
34 | {$TYPEDADDRESS OFF}
35 | {$VARSTRINGCHECKS ON}
36 | {$WRITEABLECONST OFF}
37 | {$MINENUMSIZE 1}
38 | {$IMAGEBASE $400000}
39 | {$DEFINE DEBUG}
40 | {$ENDIF IMPLICITBUILDING}
41 | {$DESIGNONLY}
42 | {$IMPLICITBUILD OFF}
43 |
44 | requires
45 | rtl,
46 | vcl,
47 | designide,
48 | IndyProtocols,
49 | IndyCore,
50 | IndySystem;
51 |
52 | contains
53 | JSONDTOExpt in 'JSONDTOExpt.pas',
54 | WizardWin in 'WizardWin.pas' {WizardForm},
55 | JSON2DTO in '..\JSON2DTO.pas',
56 | WinHttp_TLB in '..\WinHttp_TLB.pas',
57 | JSON in '..\JSON.pas';
58 |
59 | end.
60 |
--------------------------------------------------------------------------------
/JSON/Wizard/JSONDTOWiz.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {924ddcca-9772-4b0f-ba7b-b7273fa7b613}
4 | JSONDTOWiz.dpk
5 | Debug
6 | DCC32
7 | ..\..\..\..\..\..\..\..\testuser\My Documents\RAD Studio\Projects\Bpl\XPAppWiz.bpl
8 | 16.1
9 | Debug
10 | VCL
11 | True
12 | Win32
13 | 1
14 | Package
15 |
16 |
17 | true
18 |
19 |
20 | true
21 | Base
22 | true
23 |
24 |
25 | true
26 | Base
27 | true
28 |
29 |
30 | true
31 | Base
32 | true
33 |
34 |
35 | true
36 | Base
37 | true
38 |
39 |
40 | true
41 | Base
42 | true
43 |
44 |
45 | true
46 | Cfg_2
47 | true
48 | true
49 |
50 |
51 | JSONDTOWiz
52 | 1033
53 | Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace)
54 | true
55 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
56 | true
57 | 00400000
58 | C:\trunk\bin\XPAppWiz.bpl
59 | true
60 | true
61 | true
62 |
63 |
64 | rtl;vcl;IndyProtocols;IndyCore;IndySystem;$(DCC_UsePackage)
65 | 1033
66 | true
67 | System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
68 | JSONFile.ico
69 |
70 |
71 | rtl;vcl;IndyProtocols;IndyCore;IndySystem;$(DCC_UsePackage)
72 | JSONFile.ico
73 |
74 |
75 | Debug
76 | package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=preferExternal;largeHeap=False;theme=TitleBar;hardwareAccelerated=true
77 | false
78 |
79 |
80 | 7.0
81 | 0
82 | False
83 | 0
84 | RELEASE
85 |
86 |
87 | 7.0
88 | DEBUG
89 |
90 |
91 | 3
92 |
93 |
94 |
95 | MainSource
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | dfm
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | Cfg_2
117 | Base
118 |
119 |
120 | Base
121 |
122 |
123 | Cfg_1
124 | Base
125 |
126 |
127 |
128 |
129 | Delphi.Personality.12
130 | Package
131 |
132 |
133 |
134 | False
135 |
136 |
137 |
138 | False
139 | True
140 | False
141 |
142 |
143 | True
144 | False
145 | 1
146 | 0
147 | 0
148 | 0
149 | False
150 | False
151 | False
152 | False
153 | False
154 | 1033
155 | 1252
156 |
157 |
158 |
159 |
160 | 1.0.0.0
161 |
162 |
163 |
164 |
165 |
166 | 1.0.0.0
167 |
168 |
169 |
170 | JSONDTOWiz.dpk
171 |
172 |
173 |
174 | False
175 | False
176 | False
177 | True
178 | False
179 |
180 |
181 | 12
182 |
183 |
184 |
185 |
--------------------------------------------------------------------------------
/JSON/Wizard/JSONFile.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/JSON/Wizard/JSONFile.ico
--------------------------------------------------------------------------------
/JSON/Wizard/WizardWin.dfm:
--------------------------------------------------------------------------------
1 | object WizardForm: TWizardForm
2 | Left = 0
3 | Top = 0
4 | Caption = 'Import JSON DTO'
5 | ClientHeight = 432
6 | ClientWidth = 1005
7 | Color = 14737632
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -11
11 | Font.Name = 'Tahoma'
12 | Font.Style = []
13 | OldCreateOrder = False
14 | Position = poScreenCenter
15 | OnCreate = FormCreate
16 | OnDestroy = FormDestroy
17 | DesignSize = (
18 | 1005
19 | 432)
20 | PixelsPerInch = 96
21 | TextHeight = 13
22 | object Shape1: TShape
23 | Left = 0
24 | Top = 386
25 | Width = 1005
26 | Height = 46
27 | Align = alBottom
28 | Brush.Color = 16767954
29 | Pen.Color = 5329233
30 | end
31 | object LabelInvalidJSON: TLabel
32 | Left = 97
33 | Top = 404
34 | Width = 61
35 | Height = 13
36 | Anchors = [akLeft, akBottom]
37 | Caption = 'Invalid JSON'
38 | Font.Charset = DEFAULT_CHARSET
39 | Font.Color = clRed
40 | Font.Height = -11
41 | Font.Name = 'Tahoma'
42 | Font.Style = []
43 | ParentFont = False
44 | Visible = False
45 | end
46 | object Label1: TLabel
47 | Left = 512
48 | Top = 359
49 | Width = 58
50 | Height = 13
51 | Anchors = [akRight, akBottom]
52 | Caption = 'Class name:'
53 | end
54 | object Label2: TLabel
55 | Left = 8
56 | Top = 40
57 | Width = 26
58 | Height = 13
59 | Caption = 'JSON'
60 | end
61 | object Label3: TLabel
62 | Left = 512
63 | Top = 40
64 | Width = 56
65 | Height = 13
66 | Anchors = [akTop, akRight]
67 | Caption = 'DTO source'
68 | end
69 | object ButtonImport: TButton
70 | Left = 11
71 | Top = 397
72 | Width = 75
73 | Height = 25
74 | Anchors = [akLeft, akBottom]
75 | Caption = 'Import'
76 | Enabled = False
77 | TabOrder = 5
78 | OnClick = ButtonImportClick
79 | end
80 | object ButtonCancel: TButton
81 | Left = 919
82 | Top = 397
83 | Width = 75
84 | Height = 25
85 | Anchors = [akRight, akBottom]
86 | Cancel = True
87 | Caption = 'Cancel'
88 | TabOrder = 6
89 | OnClick = ButtonCancelClick
90 | end
91 | object EditURL: TEdit
92 | Left = 8
93 | Top = 11
94 | Width = 907
95 | Height = 20
96 | Anchors = [akLeft, akTop, akRight]
97 | Ctl3D = False
98 | Font.Charset = DEFAULT_CHARSET
99 | Font.Color = clWindowText
100 | Font.Height = 14
101 | Font.Name = 'Consolas'
102 | Font.Style = []
103 | ParentCtl3D = False
104 | ParentFont = False
105 | TabOrder = 0
106 | Text = 'http://itunes.apple.com/search?term=metallica'
107 | OnKeyDown = EditURLKeyDown
108 | OnKeyPress = EditURLKeyPress
109 | OnKeyUp = EditURLKeyUp
110 | end
111 | object ButtonGet: TButton
112 | Left = 922
113 | Top = 8
114 | Width = 75
115 | Height = 25
116 | Anchors = [akTop, akRight]
117 | Caption = 'Get'
118 | TabOrder = 1
119 | OnClick = ButtonGetClick
120 | end
121 | object EditName: TEdit
122 | Left = 576
123 | Top = 357
124 | Width = 169
125 | Height = 20
126 | Anchors = [akRight, akBottom]
127 | Ctl3D = False
128 | Font.Charset = DEFAULT_CHARSET
129 | Font.Color = clWindowText
130 | Font.Height = 14
131 | Font.Name = 'Consolas'
132 | Font.Style = []
133 | ParentCtl3D = False
134 | ParentFont = False
135 | TabOrder = 4
136 | Text = 'NewDTO'
137 | OnChange = EditNameChange
138 | end
139 | object PanelJSON: TPanel
140 | Left = 8
141 | Top = 58
142 | Width = 497
143 | Height = 290
144 | Anchors = [akLeft, akTop, akRight, akBottom]
145 | BevelOuter = bvNone
146 | BorderStyle = bsSingle
147 | Caption = 'PanelJSON'
148 | Ctl3D = False
149 | ParentCtl3D = False
150 | ShowCaption = False
151 | TabOrder = 2
152 | object MemoJSON: TMemo
153 | Left = 0
154 | Top = 0
155 | Width = 495
156 | Height = 288
157 | Align = alClient
158 | BevelInner = bvLowered
159 | BevelOuter = bvRaised
160 | BorderStyle = bsNone
161 | Ctl3D = True
162 | Font.Charset = DEFAULT_CHARSET
163 | Font.Color = clWindowText
164 | Font.Height = 14
165 | Font.Name = 'Consolas'
166 | Font.Style = []
167 | Lines.Strings = (
168 | '['
169 | ' {'
170 | ' "Name": "Thomas",'
171 | ' "ID": 1'
172 | ' },'
173 | ' {'
174 | ' "Name": "Maria",'
175 | ' "ID": 2'
176 | ' }'
177 | ']')
178 | ParentCtl3D = False
179 | ParentFont = False
180 | ScrollBars = ssBoth
181 | TabOrder = 0
182 | OnChange = MemoJSONChange
183 | end
184 | end
185 | object PanelSource: TPanel
186 | Left = 511
187 | Top = 58
188 | Width = 486
189 | Height = 290
190 | Anchors = [akTop, akRight, akBottom]
191 | BevelOuter = bvNone
192 | BorderStyle = bsSingle
193 | Caption = 'Panel1'
194 | Ctl3D = False
195 | ParentCtl3D = False
196 | ShowCaption = False
197 | TabOrder = 3
198 | object MemoSource: TMemo
199 | Left = 0
200 | Top = 0
201 | Width = 484
202 | Height = 288
203 | Align = alClient
204 | BevelInner = bvLowered
205 | BevelOuter = bvRaised
206 | BorderStyle = bsNone
207 | Color = 14737632
208 | Ctl3D = True
209 | Font.Charset = DEFAULT_CHARSET
210 | Font.Color = clWindowText
211 | Font.Height = 14
212 | Font.Name = 'Consolas'
213 | Font.Style = []
214 | ParentCtl3D = False
215 | ParentFont = False
216 | ScrollBars = ssBoth
217 | TabOrder = 0
218 | end
219 | end
220 | object Timer1: TTimer
221 | Enabled = False
222 | Interval = 300
223 | OnTimer = Timer1Timer
224 | Left = 208
225 | Top = 72
226 | end
227 | end
228 |
--------------------------------------------------------------------------------
/JSON/Wizard/WizardWin.pas:
--------------------------------------------------------------------------------
1 | unit WizardWin;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
8 |
9 | type
10 | TWizardForm = class(TForm)
11 | ButtonImport: TButton;
12 | ButtonCancel: TButton;
13 | EditURL: TEdit;
14 | ButtonGet: TButton;
15 | Timer1: TTimer;
16 | LabelInvalidJSON: TLabel;
17 | Shape1: TShape;
18 | EditName: TEdit;
19 | Label1: TLabel;
20 | PanelJSON: TPanel;
21 | MemoJSON: TMemo;
22 | PanelSource: TPanel;
23 | MemoSource: TMemo;
24 | Label2: TLabel;
25 | Label3: TLabel;
26 | procedure ButtonImportClick(Sender: TObject);
27 | procedure FormCreate(Sender: TObject);
28 | procedure FormDestroy(Sender: TObject);
29 | procedure ButtonCancelClick(Sender: TObject);
30 | procedure ButtonGetClick(Sender: TObject);
31 | procedure MemoJSONChange(Sender: TObject);
32 | procedure Timer1Timer(Sender: TObject);
33 | procedure EditURLKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
34 | procedure EditNameChange(Sender: TObject);
35 | procedure EditURLKeyPress(Sender: TObject; var Key: Char);
36 | procedure EditURLKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
37 | private
38 | FURL: String;
39 | FDTOSource: TStringList;
40 | Function IsValidJSON: Boolean;
41 | procedure CheckValidJSON;
42 | procedure NeedCheck;
43 | public
44 | Function Execute: String;
45 | end;
46 |
47 | var
48 | WizardForm: TWizardForm;
49 |
50 | implementation
51 |
52 | Uses
53 | JSON, JSON2DTO;
54 |
55 | {$R *.dfm}
56 |
57 | procedure TWizardForm.ButtonImportClick(Sender: TObject);
58 | begin
59 | Close;
60 | ModalResult := mrOk;
61 | end;
62 |
63 | procedure TWizardForm.ButtonGetClick(Sender: TObject);
64 | begin
65 | FURL := Trim( EditURL.Text );
66 | MemoJSON.Text := TJSON.Get( FURL ); //Will start timer
67 | Timer1.Enabled := False; //Cancel timer
68 | CheckValidJSON;
69 | end;
70 |
71 | procedure TWizardForm.ButtonCancelClick(Sender: TObject);
72 | begin
73 | Close;
74 | end;
75 |
76 | procedure TWizardForm.EditNameChange(Sender: TObject);
77 | Begin
78 | NeedCheck;
79 | End;
80 |
81 | procedure TWizardForm.NeedCheck;
82 | begin
83 | Timer1.Enabled := False;
84 | Timer1.Enabled := True;
85 | end;
86 |
87 | procedure TWizardForm.EditURLKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
88 | begin
89 | if Key = VK_RETURN then
90 | Begin
91 | Key := 0;
92 | ButtonGet.Click;
93 | End;
94 | end;
95 |
96 | procedure TWizardForm.EditURLKeyPress(Sender: TObject; var Key: Char);
97 | begin
98 | if Key = #13 then
99 | Key := #0;
100 | end;
101 |
102 | procedure TWizardForm.EditURLKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
103 | begin
104 | if Key = VK_RETURN then
105 | Key := 0;
106 | end;
107 |
108 | function TWizardForm.Execute: String;
109 | begin
110 | if (ShowModal = mrOk) and
111 | (FDTOSource.Count > 0) then
112 | Result := FDTOSource.Text
113 | else
114 | Result := '';
115 | end;
116 |
117 | procedure TWizardForm.FormCreate(Sender: TObject);
118 | begin
119 | FURL := '';
120 | FDTOSource := TStringList.Create;
121 | CheckValidJSON;
122 | end;
123 |
124 | procedure TWizardForm.FormDestroy(Sender: TObject);
125 | begin
126 | FDTOSource.Free;
127 | end;
128 |
129 | procedure TWizardForm.MemoJSONChange(Sender: TObject);
130 | begin
131 | NeedCheck;
132 | end;
133 |
134 | procedure TWizardForm.Timer1Timer(Sender: TObject);
135 | Begin
136 | Timer1.Enabled := False;
137 | CheckValidJSON;
138 | End;
139 |
140 | function TWizardForm.IsValidJSON: Boolean;
141 | var
142 | JSON: TJSON_Element;
143 | begin
144 | Result := False;
145 | JSON := nil;
146 | Try
147 | JSON := TJSON.ParseText( MemoJSON.Text );
148 | //Pretty print
149 | MemoJSON.OnChange := nil;
150 | MemoJSON.Text := JSON.ToJSON;
151 | MemoJSON.OnChange := MemoJSONChange;
152 | Result := True;
153 | Except
154 | on E: Exception do
155 | LabelInvalidJSON.Caption := 'Invalid JSON (' + E.Message + ')';
156 | End;
157 | JSON.Free;
158 | end;
159 |
160 | procedure TWizardForm.CheckValidJSON;
161 | begin
162 | FDTOSource.Clear;
163 | ButtonImport.Enabled := False;
164 | LabelInvalidJSON.Visible := True;
165 | if IsValidJSON then
166 | Try
167 | TDTOGenerator.Parse( MemoJSON.Text, EditName.Text, 'DTO.' + EditName.Text, FDTOSource, FURL );
168 | MemoSource.Lines.Assign( FDTOSource );
169 | ButtonImport.Enabled := True;
170 | LabelInvalidJSON.Visible := False;
171 | Except
172 | On E: Exception do
173 | MemoSource.Lines.Text := E.Message;
174 | End;
175 | end;
176 |
177 | end.
178 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # comotobo
2 | The "Code Monkeys ToolBox" (CoMoToBo) is a small collection of useful Delphi classes/APIs.
3 |
4 | ## EasyDelphiQ
5 | An easy-to-use Delphi AIP for RabbitMQ. Inspired by the .Net EasyNetQ client.
6 | Uses the AMQP protocol to send and receive messages.
7 | EasyDelphiQ uses JSON by default for serializing Data Transfer Objects (DTOs) in messages.
8 | DTOs are just simple Delphi classes with standard properties - but they must have a simple, parameterless constructor.
9 |
10 | ### DTOs
11 |
12 | A DTO could look like this:
13 | ```Delphi
14 | unit Some.namespace;
15 |
16 | interface
17 |
18 | Uses
19 | EasyDelphiQ.DTO;
20 |
21 | Type
22 | [AssemblyName('MyAssembly')]
23 | TestDTO = Class
24 | private
25 | FName: String;
26 | FID: Integer;
27 | Public
28 | Property ID : Integer read FID write FID;
29 | Property Name : String read FName write FName;
30 | Constructor Create;
31 | End;
32 |
33 | implementation
34 |
35 | constructor TestDTO.Create;
36 | begin
37 | FID := 0;
38 | FName := '';
39 | end;
40 | ```
41 |
42 | The `EasyDelphiQ.DTO` unit in the uses clause is not necessary, but it allows you to use the AssemblyName attribute which makes EasyDelphiQ compatible with EasyNetQ naming conventions.
43 |
44 | ### Publishing messages
45 |
46 | Simple example of how to publish a message:
47 | ```Delphi
48 | Bus := RabbitHutch.CreateBus( 'host=localhost;username=TestUser;password=password' );
49 | DTO := TestDTO.Create;
50 | Try
51 | DTO.ID := 42;
52 | DTO.Name := 'Zaphod';
53 | Bus.Publish( DTO );
54 | Finally
55 | DTO.Free;
56 | Bus.Free;
57 | End;
58 | ```
59 |
60 | The code above will connect to localhost and publish the DTO to an exchange named `Some.namespace.TestDTO:MyAssembly`.
61 | This exchange naming convention is used by EasyNetQ; [Namespace].[Classname]:[Assemblyname].
62 |
63 | ### Getting a single message from a queue
64 |
65 | ```Delphi
66 | DTO := Bus.Get( 'MySubscriberID' );
67 | if DTO = nil then
68 | Memo.Lines.Add( 'No messages in queue' )
69 | else
70 | Try
71 | Memo.Lines.Add( 'Received:' );
72 | Memo.Lines.Add( ' DTO.ID: ' + DTO.ID.ToString );
73 | Memo.Lines.Add( ' DTO.Name: ' + DTO.Name );
74 | Finally
75 | DTO.Free;
76 | End;
77 | ```
78 |
79 |
80 | ### Subscribing to a queue
81 |
82 | To subscribe to a RabbitMQ queue, simply do this:
83 | ```Delphi
84 | Subscription := Bus.Subscribe( 'MySubscription', Handler );
85 | ```
86 |
87 | The handler method could look like this:
88 | ```Delphi
89 | procedure TMainForm.Handler(var Msg: TestDTO);
90 | begin
91 | DoSomethingInteresting( Msg );
92 | end;
93 | ```
94 |
95 | If no exceptions are raised in the Handler method, then the message is acknowledged and removed from the queue.
96 | The `Msg` object in the example will be destroyed automatically by EasyDelphiQ.
97 | If you want to keep the object (put it in a list, for example) then set `Msg` to `nil` in the `Handler`.
98 | It is important to know, however, that the `Handler` method is **NOT** called in the main thread context, so the code here **MUST** be thread safe.
99 |
100 | Here is a simple example of how to use the DTO in the main thread context:
101 |
102 | ```Delphi
103 | procedure TMainForm.Handler(var Msg: TestDTO);
104 | var
105 | DTO: TestDTO;
106 | begin
107 | DTO := Msg; //Necessary to capture the object in the anonymous method below
108 | TThread.Queue( nil,
109 | Procedure
110 | begin
111 | Memo1.Lines.Add( 'Received:' );
112 | Memo1.Lines.Add( ' DTO.ID: ' + DTO.ID.ToString );
113 | Memo1.Lines.Add( ' DTO.Name: ' + DTO.Name );
114 | DTO.Free; //Free the object here - when we are done with it
115 | end );
116 | Msg := nil; //Don't free the object here
117 | end;
118 | ```
119 |
120 |
121 | ## AMQP
122 | The implementation of the AMQP protocol which RabbitMQ uses for communication.
123 | EasyDelphiQ is built on top of this library.
124 |
125 | ## DJSON
126 | The DJSON unit makes reading and writing JSON easy (using RTTI).
127 |
128 | For example; parsing JSON array of objects directly into a TObjectList<>:
129 | ```Delphi
130 | JSON := '[ {"ID":4, "Name":"Tom" }, {"ID":7, "Name":"Julia" } ]';
131 | TJSONParser.Parse( JSON, List );
132 | ```
133 |
134 | Serializing an object is equally easy;
135 | ```Delphi
136 | JSON := TJSONSerializer.Serialize( List );
137 | ```
138 |
139 | ## XPath
140 | This little unit makes parsing HTML files easy.
141 |
142 | Given this html:
143 | ```Html
144 |
145 | Not me!
146 |
147 |
Hello
148 |
Cruel
149 |
150 |
153 |
154 | ```
155 |
156 | ...is loaded into the Dom viariable (TDom) this line:
157 | ```Delphi
158 | TXPath.Eval( Dom, '/html/div//p' );
159 | ```
160 |
161 | Will return an array containing these 3 "p" nodes:
162 | ```Html
163 | Hello
164 | Cruel
165 | World
166 | ```
167 |
168 | ## Examples
169 | Simple examples are included in the source.
170 |
--------------------------------------------------------------------------------
/XPath/TestBench/HtmlTest.dpr:
--------------------------------------------------------------------------------
1 | program HtmlTest;
2 |
3 | uses
4 | Vcl.Forms,
5 | MainWin in 'MainWin.pas' {Form1},
6 | HtmlParser in '..\HtmlParser.pas',
7 | XPathLexer in '..\XPathLexer.pas',
8 | XPath in '..\XPath.pas';
9 |
10 | {$R *.res}
11 |
12 | begin
13 | Application.Initialize;
14 | Application.MainFormOnTaskbar := True;
15 | Application.CreateForm(TForm1, Form1);
16 | Application.Run;
17 | end.
18 |
--------------------------------------------------------------------------------
/XPath/TestBench/HtmlTest.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/XPath/TestBench/HtmlTest.res
--------------------------------------------------------------------------------
/XPath/TestBench/MainWin.dfm:
--------------------------------------------------------------------------------
1 | object Form1: TForm1
2 | Left = 0
3 | Top = 0
4 | Anchors = [akLeft, akTop, akRight, akBottom]
5 | Caption = 'Form1'
6 | ClientHeight = 604
7 | ClientWidth = 1087
8 | Color = clBtnFace
9 | DoubleBuffered = True
10 | Font.Charset = DEFAULT_CHARSET
11 | Font.Color = clWindowText
12 | Font.Height = -11
13 | Font.Name = 'Tahoma'
14 | Font.Style = []
15 | OldCreateOrder = False
16 | OnCreate = FormCreate
17 | OnDestroy = FormDestroy
18 | DesignSize = (
19 | 1087
20 | 604)
21 | PixelsPerInch = 96
22 | TextHeight = 13
23 | object ButtonDownload: TButton
24 | Left = 8
25 | Top = 8
26 | Width = 75
27 | Height = 25
28 | Caption = 'Download'
29 | TabOrder = 0
30 | OnClick = ButtonDownloadClick
31 | end
32 | object ButtonParseLastDownload: TButton
33 | Left = 950
34 | Top = 8
35 | Width = 129
36 | Height = 25
37 | Anchors = [akTop, akRight]
38 | Caption = 'Parse last download'
39 | TabOrder = 4
40 | OnClick = ButtonParseLastDownloadClick
41 | end
42 | object ButtonXPath: TButton
43 | Left = 8
44 | Top = 39
45 | Width = 75
46 | Height = 25
47 | Caption = 'XPath'
48 | Default = True
49 | TabOrder = 2
50 | OnClick = ButtonXPathClick
51 | end
52 | object EditXPath: TEdit
53 | Left = 89
54 | Top = 41
55 | Width = 720
56 | Height = 21
57 | Anchors = [akLeft, akTop, akRight]
58 | TabOrder = 3
59 | Text =
60 | '//div[@id='#39'tab_de'#39']/table[3]/tbody/tr[ not(td[ text()='#39'MWh'#39' ] ) ' +
61 | ']'
62 | end
63 | object EditURL: TEdit
64 | Left = 89
65 | Top = 9
66 | Width = 720
67 | Height = 21
68 | Anchors = [akLeft, akTop, akRight]
69 | TabOrder = 1
70 | Text =
71 | 'http://www.epexspot.com/en/market-data/dayaheadauction/auction-t' +
72 | 'able/2015-08-23/DE'
73 | end
74 | object PanelContent: TPanel
75 | Left = 8
76 | Top = 70
77 | Width = 1071
78 | Height = 509
79 | Anchors = [akLeft, akTop, akRight, akBottom]
80 | Caption = 'PanelContent'
81 | ShowCaption = False
82 | TabOrder = 7
83 | object Splitter1: TSplitter
84 | Left = 441
85 | Top = 1
86 | Width = 8
87 | Height = 507
88 | Beveled = True
89 | ResizeStyle = rsUpdate
90 | ExplicitLeft = 290
91 | ExplicitHeight = 383
92 | end
93 | object PageControlRight: TPageControl
94 | Left = 449
95 | Top = 1
96 | Width = 621
97 | Height = 507
98 | ActivePage = TabXPath
99 | Align = alClient
100 | Constraints.MinWidth = 200
101 | TabOrder = 0
102 | object TabDom: TTabSheet
103 | Caption = 'HTML input'
104 | Constraints.MinWidth = 200
105 | ExplicitLeft = 0
106 | ExplicitTop = 0
107 | ExplicitWidth = 0
108 | ExplicitHeight = 0
109 | DesignSize = (
110 | 613
111 | 479)
112 | object ButtonParseMemo: TButton
113 | Left = 3
114 | Top = 3
115 | Width = 94
116 | Height = 25
117 | Caption = 'Parse memo'
118 | TabOrder = 0
119 | OnClick = ButtonParseMemoClick
120 | end
121 | object MemoHtml: TMemo
122 | Left = 3
123 | Top = 34
124 | Width = 607
125 | Height = 442
126 | Anchors = [akLeft, akTop, akRight, akBottom]
127 | Lines.Strings = (
128 | ''
129 | ''
130 | ''
131 | ''
132 | ''
133 | ''
134 | ''
135 | ''
136 | ''
137 | ' Helloworld'
138 | '
'
139 | ' I am groot'
140 | ''
141 | ''
142 | '')
145 | TabOrder = 1
146 | end
147 | end
148 | object TabXPath: TTabSheet
149 | Caption = 'XPath Result'
150 | ImageIndex = 1
151 | DesignSize = (
152 | 613
153 | 479)
154 | object Grid: TStringGrid
155 | Left = 3
156 | Top = 34
157 | Width = 607
158 | Height = 442
159 | Anchors = [akLeft, akTop, akRight, akBottom]
160 | DefaultRowHeight = 18
161 | DrawingStyle = gdsClassic
162 | FixedCols = 0
163 | Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goEditing, goThumbTracking]
164 | TabOrder = 0
165 | end
166 | object Button1: TButton
167 | Left = 3
168 | Top = 3
169 | Width = 94
170 | Height = 25
171 | Caption = 'Copy'
172 | TabOrder = 1
173 | OnClick = Button1Click
174 | end
175 | object CheckBoxTrimTags: TCheckBox
176 | Left = 112
177 | Top = 8
178 | Width = 97
179 | Height = 17
180 | Caption = 'Trim HTML tags'
181 | Checked = True
182 | State = cbChecked
183 | TabOrder = 2
184 | end
185 | end
186 | end
187 | object PageControlLeft: TPageControl
188 | Left = 1
189 | Top = 1
190 | Width = 440
191 | Height = 507
192 | ActivePage = TabSheet1
193 | Align = alLeft
194 | Constraints.MinWidth = 200
195 | TabOrder = 1
196 | object TabSheet1: TTabSheet
197 | Caption = 'DOM'
198 | object TreeViewDOM: TTreeView
199 | Left = 0
200 | Top = 0
201 | Width = 432
202 | Height = 479
203 | Align = alClient
204 | Indent = 19
205 | TabOrder = 0
206 | end
207 | end
208 | object TabSheet2: TTabSheet
209 | Caption = 'XPath Result'
210 | ImageIndex = 1
211 | ExplicitLeft = 0
212 | ExplicitTop = 0
213 | ExplicitWidth = 0
214 | ExplicitHeight = 0
215 | object TreeViewXPath: TTreeView
216 | Left = 0
217 | Top = 0
218 | Width = 432
219 | Height = 479
220 | Align = alClient
221 | Constraints.MinWidth = 200
222 | Indent = 19
223 | TabOrder = 0
224 | end
225 | end
226 | end
227 | end
228 | object StatusBar: TStatusBar
229 | Left = 0
230 | Top = 585
231 | Width = 1087
232 | Height = 19
233 | Panels = <>
234 | SimplePanel = True
235 | end
236 | object ButtonEpexTest: TButton
237 | Left = 950
238 | Top = 39
239 | Width = 129
240 | Height = 25
241 | Anchors = [akTop, akRight]
242 | Caption = 'Epex test'
243 | TabOrder = 6
244 | OnClick = ButtonEpexTestClick
245 | end
246 | object ButtonExaaTest: TButton
247 | Left = 815
248 | Top = 39
249 | Width = 129
250 | Height = 25
251 | Anchors = [akTop, akRight]
252 | Caption = 'EXAA test'
253 | TabOrder = 5
254 | OnClick = ButtonExaaTestClick
255 | end
256 | end
257 |
--------------------------------------------------------------------------------
/XPath/TestBench/MainWin.pas:
--------------------------------------------------------------------------------
1 | unit MainWin;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.ExtCtrls, Vcl.Grids, HtmlParser, XPath;
8 |
9 | type
10 | TForm1 = class(TForm)
11 | ButtonDownload: TButton;
12 | ButtonParseLastDownload: TButton;
13 | ButtonXPath: TButton;
14 | EditXPath: TEdit;
15 | EditURL: TEdit;
16 | PanelContent: TPanel;
17 | PageControlRight: TPageControl;
18 | TabDom: TTabSheet;
19 | TabXPath: TTabSheet;
20 | Splitter1: TSplitter;
21 | PageControlLeft: TPageControl;
22 | TabSheet1: TTabSheet;
23 | TabSheet2: TTabSheet;
24 | ButtonParseMemo: TButton;
25 | MemoHtml: TMemo;
26 | TreeViewDOM: TTreeView;
27 | TreeViewXPath: TTreeView;
28 | StatusBar: TStatusBar;
29 | ButtonEpexTest: TButton;
30 | Grid: TStringGrid;
31 | Button1: TButton;
32 | ButtonExaaTest: TButton;
33 | CheckBoxTrimTags: TCheckBox;
34 | procedure ButtonDownloadClick(Sender: TObject);
35 | procedure ButtonParseLastDownloadClick(Sender: TObject);
36 | procedure ButtonParseMemoClick(Sender: TObject);
37 | procedure FormCreate(Sender: TObject);
38 | procedure FormDestroy(Sender: TObject);
39 | procedure ButtonXPathClick(Sender: TObject);
40 | procedure ButtonEpexTestClick(Sender: TObject);
41 | procedure Button1Click(Sender: TObject);
42 | procedure ButtonExaaTestClick(Sender: TObject);
43 | private
44 | FDom: TDom;
45 | FNodeList: TNodeList;
46 | FLastParse: Int64;
47 | FLastXPath: Int64;
48 | FXPathResult: TXValue;
49 | Procedure MakeTree( ATreeView: TTreeView; AParent: TTreeNode; ANode: TNode );
50 | procedure ShowDom( ATreeView: TTreeView; ANode: TNode );
51 | procedure ShowXPathTree;
52 | procedure ShowXPathTable;
53 | procedure DownloadURL( AURL: String );
54 | procedure RunXPath( AXPath: String );
55 | procedure UpdateStatusBar;
56 | procedure ParseDOM( Fil: TStrings; ARootName: String );
57 | procedure ParseLastDownloadClick;
58 | end;
59 |
60 | var
61 | Form1: TForm1;
62 |
63 | implementation
64 |
65 | Uses
66 | IdHttp, System.Math, System.Diagnostics, VCL.clipbrd;
67 |
68 | {$R *.dfm}
69 |
70 | procedure TForm1.Button1Click(Sender: TObject);
71 | var
72 | Text: String;
73 | Row: Integer;
74 | begin
75 | Text := '';
76 | for Row := 0 to Grid.RowCount-1 do
77 | Text := Text + Grid.Rows[Row].CommaText + #13#10;
78 | Clipboard.AsText := Text;
79 | end;
80 |
81 | procedure TForm1.ButtonExaaTestClick(Sender: TObject);
82 | begin
83 | EditURL.Text := 'http://www.exaa.at/de/marktdaten/handelsergebnisse';
84 | EditXPath.Text := '//div[@class=''pimcore_area_cismo_wysiwyg hourProducts'']/table//tr';
85 | DownloadURL( EditURL.Text );
86 | RunXPath( EditXPath.Text );
87 | end;
88 |
89 | procedure TForm1.ButtonDownloadClick(Sender: TObject);
90 | Begin
91 | DownloadURL( Trim(EditURL.Text) );
92 | End;
93 |
94 | procedure TForm1.DownloadURL( AURL: String );
95 | var
96 | Http : TIdHttp;
97 | Stream : TStringStream;
98 | Fil : TStringList;
99 | begin
100 | Http := TIdHttp.Create(nil);
101 | Stream := TStringStream.Create( '', TEncoding.UTF8 );
102 | Fil := TStringList.Create;
103 | Try
104 | Http.Get( AURL, Stream );
105 | if Http.ResponseCode = 200 then
106 | Begin
107 | Stream.Position := 0;
108 | Fil.Text := Stream.DataString; //UTF8 --> Unicode
109 | Fil.SaveToFile( 'Download.html' );
110 | ParseDOM( Fil, AURL );
111 | End;
112 | Finally
113 | Fil.Free;
114 | Stream.Free;
115 | Http.Free;
116 | End;
117 | end;
118 |
119 | procedure TForm1.ButtonEpexTestClick(Sender: TObject);
120 | begin
121 | EditURL.Text := 'http://www.epexspot.com/en/market-data/dayaheadauction/auction-table/2015-08-23/DE';
122 | EditXPath.Text := '//div[@id=''tab_de'']/table[3]/tbody/tr[ not(td[ text()=''MWh'' ] ) ]';
123 | DownloadURL( EditURL.Text );
124 | RunXPath( EditXPath.Text );
125 | end;
126 |
127 | procedure TForm1.ButtonParseLastDownloadClick(Sender: TObject);
128 | Begin
129 | ParseLastDownloadClick;
130 | End;
131 |
132 | procedure TForm1.ParseLastDownloadClick;
133 | var
134 | Fil: TStringList;
135 | begin
136 | if FileExists( 'Download.html' ) then
137 | Begin
138 | Fil := TStringList.Create;
139 | Try
140 | Fil.LoadFromFile( 'Download.html' );
141 | ParseDOM( Fil, 'Download.html' );
142 | Finally
143 | Fil.Free;
144 | End;
145 | End;
146 | end;
147 |
148 | procedure TForm1.ButtonParseMemoClick(Sender: TObject);
149 | begin
150 | ParseDOM( MemoHtml.Lines, 'Memo' );
151 | end;
152 |
153 | procedure TForm1.ButtonXPathClick(Sender: TObject);
154 | Begin
155 | RunXPath( Trim(EditXPath.Text) );
156 | End;
157 |
158 | procedure TForm1.ShowXPathTable;
159 |
160 | Function TrimHtmlTags( S: String ): String;
161 | var
162 | Start, EndTag: Integer;
163 | Begin
164 | Result := S;
165 | Start := Pos( '<', S );
166 | EndTag := Pos( '>', S );
167 | while (Start > 0) and (EndTag > 0) and (EndTag > Start) do
168 | Begin
169 | S := Copy( S, 1, Start-1 ) + Copy( S, EndTag+1, MaxInt );
170 | Start := Pos( '<', S );
171 | EndTag := Pos( '>', S );
172 | End;
173 | Result := S;
174 | End;
175 |
176 | Function TrimCellText( S: String ): String;
177 | Begin
178 | Result := S;
179 | if CheckBoxTrimTags.Checked then
180 | Result := TrimHtmlTags( Result );
181 | Result := Trim( Result );
182 | End;
183 |
184 | var
185 | ColCount, Col, Row: Integer;
186 | Node, Child: TNode;
187 | begin
188 | if FXPathResult.XType <> xNodelist then
189 | Begin
190 | Grid.ColCount := 1;
191 | Grid.RowCount := 2;
192 | Grid.Rows[0].Text := 'Value';
193 | case FXPathResult.XType of
194 | xBool : Grid.Rows[1].Text := BoolToStr( FXPathResult.AsBoolean, True );
195 | xInt : Grid.Rows[1].Text := IntToStr( FXPathResult.AsInt );
196 | xFloat : Grid.Rows[1].Text := FloatToStr( FXPathResult.AsFloat );
197 | xString : Grid.Rows[1].Text := FXPathResult.AsString;
198 | end;
199 | End
200 | else
201 | Begin
202 | Grid.RowCount := 1 + Max( 1, FNodeList.Count );
203 | ColCount := 0;
204 | For Node in FNodeList do
205 | ColCount := Max( ColCount, Node.Count );
206 | Grid.ColCount := Max( 1, ColCount );
207 | Grid.Rows[0].Text := '';
208 | Grid.Rows[1].Text := '';
209 |
210 | for Col := 0 to Grid.ColCount-1 do
211 | Grid.Cells[ Col, 0 ] := 'Col ' + Col.ToString;
212 | Row := 1;
213 | For Node in FNodeList do
214 | Begin
215 | Col := 0;
216 | if ColCount = 0 then
217 | Grid.Cells[ Col, Row ] := TrimCellText( Node.Text )
218 | Else
219 | Begin
220 | Grid.Rows[ Row ].Text := '';
221 | For Child in Node do
222 | Begin
223 | Grid.Cells[ Col, Row ] := TrimCellText( Child.Text );
224 | Inc( Col );
225 | End;
226 | End;
227 | Inc( Row );
228 | End;
229 | End;
230 | end;
231 |
232 | procedure TForm1.ShowXPathTree;
233 | var
234 | Node: TNode;
235 | begin
236 | TreeViewXPath.Items.BeginUpdate;
237 | Try
238 | TreeViewXPath.Items.Clear;
239 | For Node in FNodeList do
240 | MakeTree( TreeViewXPath, nil, Node );
241 | Finally
242 | TreeViewXPath.Items.EndUpdate;
243 | End;
244 | UpdateStatusBar;
245 | end;
246 |
247 | procedure TForm1.RunXPath( AXPath: String );
248 | var
249 | StopWatch : TStopWatch;
250 | begin
251 | FNodeList.Clear;
252 | StopWatch := TStopWatch.StartNew;
253 | if AXPath <> '' then
254 | Begin
255 | FXPathResult := TXPath.Eval( FDom, AXPath );
256 | if FXPathResult.XType = xNodelist then
257 | FNodeList.AddRange( FXPathResult.AsNodes );
258 | End;
259 | FLastXPath := StopWatch.ElapsedMilliseconds;
260 | ShowXPathTree;
261 | ShowXPathTable;
262 | PageControlLeft.ActivePageIndex := 1;
263 | PageControlRight.ActivePageIndex := 1;
264 | end;
265 |
266 | procedure TForm1.FormCreate(Sender: TObject);
267 | begin
268 | ReportMemoryLeaksOnShutdown := True;
269 | FDom := TDom.Create;
270 | FDom.StrictMode := False;
271 | FLastParse := 0;
272 | FLastXPath := 0;
273 | FNodeList := TNodeList.Create( False );
274 | PageControlLeft.ActivePageIndex := 0;
275 | PageControlRight.ActivePageIndex := 0;
276 | ParseLastDownloadClick;
277 | end;
278 |
279 | procedure TForm1.FormDestroy(Sender: TObject);
280 | begin
281 | FDom.Free;
282 | FNodeList.Free;
283 | end;
284 |
285 | Procedure TForm1.MakeTree( ATreeView: TTreeView; AParent: TTreeNode; ANode: TNode );
286 | var
287 | Item: TTreeNode;
288 | Child: TNode;
289 | Text, Value, AttributeText: String;
290 | Attribute: TAttribute;
291 | Begin
292 | AttributeText := '';
293 | if ANode.Attributes.Count > 0 then
294 | Begin
295 | for Attribute in ANode.Attributes do
296 | begin
297 | if AttributeText <> '' then
298 | AttributeText := AttributeText + ', ';
299 | AttributeText := AttributeText + ' @' + Attribute.Name + ' = "' + Attribute.Value + '"';
300 | end;
301 | AttributeText := ' [' + AttributeText + ' ]';
302 | End;
303 | Text := Trim( ANode.Name ) + AttributeText;
304 | Value := Trim( ANode.Text );
305 | if (Value <> '') and (Value.Length < 50) then
306 | Text := Text + ' :: ' + Value;
307 |
308 | Item := ATreeView.Items.AddChild( AParent, Text );
309 | for Child in ANode do
310 | MakeTree( ATreeView, Item, Child );
311 | Item.Expanded := True;
312 | End;
313 |
314 | procedure TForm1.ParseDOM(Fil: TStrings; ARootName: String);
315 | var
316 | StopWatch : TStopWatch;
317 | begin
318 | StopWatch := TStopWatch.StartNew;
319 | FDom.LoadFromStrings( Fil );
320 | FLastParse := StopWatch.ElapsedMilliseconds;
321 |
322 | FDom.Root.Name := ARootName;
323 | ShowDom( TreeViewDOM, FDom.Root );
324 | PageControlLeft.ActivePageIndex := 0;
325 | UpdateStatusBar;
326 | end;
327 |
328 | procedure TForm1.ShowDom(ATreeView: TTreeView; ANode: TNode);
329 | begin
330 | ATreeView.Items.BeginUpdate;
331 | Try
332 | ATreeView.Items.Clear;
333 | MakeTree( TreeViewDOM, nil, ANode );
334 | Finally
335 | ATreeView.Items.EndUpdate;
336 | End;
337 | end;
338 |
339 | procedure TForm1.UpdateStatusBar;
340 | begin
341 | StatusBar.SimpleText := 'Last parse: ' + FLastParse.ToString + ' ms' +
342 | ' ' +
343 | 'Last XPath: ' + FLastXPath.ToString + ' ms';
344 | end;
345 |
346 | end.
347 |
348 |
--------------------------------------------------------------------------------
/XPath/TestBench/Win32/Debug/Download.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/XPath/TestBench/Win32/Debug/Download.html
--------------------------------------------------------------------------------
/XPath/UnitTest/TestHtmlParser.pas:
--------------------------------------------------------------------------------
1 | unit TestHtmlParser;
2 |
3 | interface
4 |
5 | uses
6 | TestFramework, HtmlParser;
7 |
8 | type
9 | TestTDom = class(TTestCase)
10 | strict private
11 | FDom: TDom;
12 | public
13 | procedure SetUp; override;
14 | procedure TearDown; override;
15 | published
16 | procedure TestLoadFromString;
17 | end;
18 |
19 | implementation
20 |
21 | procedure TestTDom.SetUp;
22 | begin
23 | FDom := TDom.Create;
24 | end;
25 |
26 | procedure TestTDom.TearDown;
27 | begin
28 | FDom.Free;
29 | FDom := nil;
30 | end;
31 |
32 | procedure TestTDom.TestLoadFromString;
33 | var
34 | Node: TNode;
35 | Name: String;
36 | begin
37 | FDom.LoadFromString( ''+
38 | 'Hello
World
' );
39 | CheckEquals( 2, FDom.Root.Count );
40 | Node := FDom.Root[0];
41 | Name := 'FDom.Root[0]';
42 | CheckEquals( '', Node.Source, Name + ': Source' );
43 | CheckEquals( ' a="12"', Node.Text, Name + ': Text' );
44 | CheckEquals( 0, Node.Attributes.Count, Name + ': Attributes.Count' );
45 | CheckEquals( 0, Node.Count, Name + ': Count' );
46 | Node := FDom.Root[1];
47 | Name := 'FDom.Root[1]';
48 | CheckEquals( 'Hello
World
', Node.Source, Name + ': Source' );
49 | CheckEquals( 'Hello
World
', Node.Text, Name + ': Text' );
50 | CheckEquals( 1, Node.Attributes.Count, Name + ': Attributes.Count' );
51 | CheckEquals( 'b', Node.Attributes[0].Name, Name + ': Attributes[0].Name' );
52 | CheckEquals( '12', Node.Attributes[0].Value, Name + ': Attributes[0].Value' );
53 | CheckEquals( 1, Node.Count, Name + ': Count' );
54 | Node := FDom.Root[1].Children[0];
55 | Name := 'FDom.Root[1].Children[0]';
56 | CheckEquals( 'Hello
World
', Node.Source, Name + ': Source' );
57 | CheckEquals( 'Hello
World
', Node.Text, Name + ': Text' );
58 | CheckEquals( 0, Node.Attributes.Count, Name + ': Attributes.Count' );
59 | CheckEquals( 1, Node.Count, Name + ': Count' );
60 | Node := FDom.Root[1].Children[0].Children[0];
61 | Name := 'FDom.Root[1].Children[0].Children[0]';
62 | CheckEquals( 'Hello
World
', Node.Source, Name + ': Source' );
63 | CheckEquals( 'Hello
World', Node.Text, Name + ': Text' );
64 | CheckEquals( 0, Node.Attributes.Count, Name + ': Attributes.Count' );
65 | CheckEquals( 0, Node.Count, Name + ': Count' );
66 | end;
67 |
68 | initialization
69 | RegisterTest(TestTDom.Suite);
70 | end.
71 |
72 |
--------------------------------------------------------------------------------
/XPath/UnitTest/TestLexer.pas:
--------------------------------------------------------------------------------
1 | unit TestLexer;
2 |
3 | interface
4 |
5 | uses
6 | TestFramework, XPathLexer;
7 |
8 | type
9 | TestTLexer = class(TTestCase)
10 | strict private
11 | FLexer: TLexer;
12 | Procedure CheckToken( ATokenType: TTokenType; AStr: String ); Overload;
13 | Procedure CheckToken( ATokenType: TTokenType ); Overload;
14 | public
15 | procedure SetUp; override;
16 | procedure TearDown; override;
17 | published
18 | procedure TestLexer;
19 | procedure TestLexer_Uppercase;
20 | procedure TestLexer_Identifier_After_Slash;
21 | procedure TestLexer_Identifier_After_DoubleSlash;
22 | procedure TestLexer_Identifier_After_DoubleColon;
23 | procedure TestLexer_Text_After_DoubleColon;
24 | end;
25 |
26 | implementation
27 |
28 | procedure TestTLexer.CheckToken(ATokenType: TTokenType; AStr: String);
29 | begin
30 | CheckTrue( FLexer.Token.TokenType = ATokenType, 'Expected token ' + FLexer.Token.TokenType.AsString +
31 | ', found ' + ATokenType.AsString );
32 | CheckEquals( AStr, FLexer.Token.Text, 'Text' );
33 | FLexer.Next;
34 | end;
35 |
36 | procedure TestTLexer.CheckToken(ATokenType: TTokenType);
37 | begin
38 | CheckToken( ATokenType, ATokenType.AsString );
39 | end;
40 |
41 | procedure TestTLexer.SetUp;
42 | begin
43 | FLexer := nil;
44 | end;
45 |
46 | procedure TestTLexer.TearDown;
47 | begin
48 | FLexer.Free;
49 | end;
50 |
51 | procedure TestTLexer.TestLexer;
52 | begin
53 | FLexer := TLexer.Create( 'Identifier 25 0.25 ''Hello World'' ' +
54 | '()[]' +
55 | '@.::/..//$,' +
56 | '+-*' +
57 | '=!=<><=>=' +
58 | 'or and div idiv mod ' +
59 | 'child.descendant.descendant-or-self.parent.self.' +
60 | 'following-sibling.following.namespace.ancestor.' +
61 | 'preceding-sibling.preceding.ancestor-or-self ' +
62 | 'document-node element attribute schema-element schema-attribute ' +
63 | 'processing-instruction comment text node' );
64 | CheckToken( ttIdentifier, 'Identifier' );
65 | CheckToken( ttInteger, '25' );
66 | CheckToken( ttFloat, '0.25' );
67 | CheckToken( ttString, 'Hello World' );
68 | CheckToken( ttParenStart );
69 | CheckToken( ttParenEnd );
70 | CheckToken( ttBracketStart );
71 | CheckToken( ttBracketEnd );
72 | CheckToken( ttAt );
73 | CheckToken( ttDot );
74 | CheckToken( ttColonColon );
75 | CheckToken( ttSlash );
76 | CheckToken( ttDotDot );
77 | CheckToken( ttDoubleSlash );
78 | CheckToken( ttDollar );
79 | CheckToken( ttComma );
80 | CheckToken( ttPlus );
81 | CheckToken( ttMinus );
82 | CheckToken( ttMultiply );
83 | CheckToken( ttEquals );
84 | CheckToken( ttNotEquals );
85 | CheckToken( ttLess );
86 | CheckToken( ttGreater );
87 | CheckToken( ttLessEqual );
88 | CheckToken( ttGreaterEqual );
89 | CheckToken( ttOr );
90 | CheckToken( ttAnd );
91 | CheckToken( ttDiv );
92 | CheckToken( ttIDiv );
93 | CheckToken( ttMod );
94 | CheckToken( ttChild );
95 | CheckToken( ttDot );
96 | CheckToken( ttDescendant );
97 | CheckToken( ttDot );
98 | CheckToken( ttDescendantOrSelf );
99 | CheckToken( ttDot );
100 | CheckToken( ttParent );
101 | CheckToken( ttDot );
102 | CheckToken( ttSelf );
103 | CheckToken( ttDot );
104 | CheckToken( ttFollowingSibling );
105 | CheckToken( ttDot );
106 | CheckToken( ttFollowing );
107 | CheckToken( ttDot );
108 | CheckToken( ttNamespace );
109 | CheckToken( ttDot );
110 | CheckToken( ttAncestor );
111 | CheckToken( ttDot );
112 | CheckToken( ttPrecedingSibling );
113 | CheckToken( ttDot );
114 | CheckToken( ttPreceding );
115 | CheckToken( ttDot );
116 | CheckToken( ttAncestorOrSelf );
117 | CheckToken( ttDocumentNode );
118 | CheckToken( ttElement );
119 | CheckToken( ttAttribute );
120 | CheckToken( ttSchemaElement );
121 | CheckToken( ttSchemaAttribute );
122 | CheckToken( ttProcessingInstruction );
123 | CheckToken( ttComment );
124 | CheckToken( ttText );
125 | CheckToken( ttNode );
126 | CheckToken( ttEOF );
127 | end;
128 |
129 | procedure TestTLexer.TestLexer_Identifier_After_DoubleColon;
130 | begin
131 | FLexer := TLexer.Create( '::text/' );
132 | CheckToken( ttColonColon );
133 | CheckToken( ttIdentifier, 'text' );
134 | CheckToken( ttSlash );
135 | end;
136 |
137 | procedure TestTLexer.TestLexer_Identifier_After_DoubleSlash;
138 | begin
139 | FLexer := TLexer.Create( '//div div' );
140 | CheckToken( ttDoubleSlash );
141 | CheckToken( ttIdentifier, 'div' );
142 | CheckToken( ttDiv );
143 | end;
144 |
145 | procedure TestTLexer.TestLexer_Identifier_After_Slash;
146 | begin
147 | FLexer := TLexer.Create( '/div div' );
148 | CheckToken( ttSlash );
149 | CheckToken( ttIdentifier, 'div' );
150 | CheckToken( ttDiv );
151 | end;
152 |
153 | procedure TestTLexer.TestLexer_Text_After_DoubleColon;
154 | begin
155 | FLexer := TLexer.Create( '::text()' );
156 | CheckToken( ttColonColon );
157 | CheckToken( ttText );
158 | end;
159 |
160 | procedure TestTLexer.TestLexer_Uppercase;
161 | begin
162 | FLexer := TLexer.Create( 'IDENTIFIER 25 0.25 ''HELLO WORLD'' ' +
163 | '()[]' +
164 | '@.::/..//$,' +
165 | '+-*' +
166 | '=!=<><=>=' +
167 | 'OR AND DIV IDIV MOD ' +
168 | 'CHILD.DESCENDANT.DESCENDANT-OR-SELF.PARENT.SELF.' +
169 | 'FOLLOWING-SIBLING.FOLLOWING.NAMESPACE.ANCESTOR.' +
170 | 'PRECEDING-SIBLING.PRECEDING.ANCESTOR-OR-SELF ' +
171 | 'DOCUMENT-NODE ELEMENT ATTRIBUTE SCHEMA-ELEMENT SCHEMA-ATTRIBUTE ' +
172 | 'PROCESSING-INSTRUCTION COMMENT TEXT NODE' );
173 | CheckToken( ttIdentifier, 'IDENTIFIER' );
174 | CheckToken( ttInteger, '25' );
175 | CheckToken( ttFloat, '0.25' );
176 | CheckToken( ttString, 'HELLO WORLD' );
177 | CheckToken( ttParenStart );
178 | CheckToken( ttParenEnd );
179 | CheckToken( ttBracketStart );
180 | CheckToken( ttBracketEnd );
181 | CheckToken( ttAt );
182 | CheckToken( ttDot );
183 | CheckToken( ttColonColon );
184 | CheckToken( ttSlash );
185 | CheckToken( ttDotDot );
186 | CheckToken( ttDoubleSlash );
187 | CheckToken( ttDollar );
188 | CheckToken( ttComma );
189 | CheckToken( ttPlus );
190 | CheckToken( ttMinus );
191 | CheckToken( ttMultiply );
192 | CheckToken( ttEquals );
193 | CheckToken( ttNotEquals );
194 | CheckToken( ttLess );
195 | CheckToken( ttGreater );
196 | CheckToken( ttLessEqual );
197 | CheckToken( ttGreaterEqual );
198 | CheckToken( ttOr );
199 | CheckToken( ttAnd );
200 | CheckToken( ttDiv );
201 | CheckToken( ttIDiv );
202 | CheckToken( ttMod );
203 | CheckToken( ttChild );
204 | CheckToken( ttDot );
205 | CheckToken( ttDescendant );
206 | CheckToken( ttDot );
207 | CheckToken( ttDescendantOrSelf );
208 | CheckToken( ttDot );
209 | CheckToken( ttParent );
210 | CheckToken( ttDot );
211 | CheckToken( ttSelf );
212 | CheckToken( ttDot );
213 | CheckToken( ttFollowingSibling );
214 | CheckToken( ttDot );
215 | CheckToken( ttFollowing );
216 | CheckToken( ttDot );
217 | CheckToken( ttNamespace );
218 | CheckToken( ttDot );
219 | CheckToken( ttAncestor );
220 | CheckToken( ttDot );
221 | CheckToken( ttPrecedingSibling );
222 | CheckToken( ttDot );
223 | CheckToken( ttPreceding );
224 | CheckToken( ttDot );
225 | CheckToken( ttAncestorOrSelf );
226 | CheckToken( ttDocumentNode );
227 | CheckToken( ttElement );
228 | CheckToken( ttAttribute );
229 | CheckToken( ttSchemaElement );
230 | CheckToken( ttSchemaAttribute );
231 | CheckToken( ttProcessingInstruction );
232 | CheckToken( ttComment );
233 | CheckToken( ttText );
234 | CheckToken( ttNode );
235 | CheckToken( ttEOF );
236 | end;
237 |
238 | initialization
239 | RegisterTest(TestTLexer.Suite);
240 | end.
241 |
242 |
--------------------------------------------------------------------------------
/XPath/UnitTest/XPathTests.dpr:
--------------------------------------------------------------------------------
1 | program XPathTests;
2 |
3 | {$IFDEF CONSOLE_TESTRUNNER}
4 | {$APPTYPE CONSOLE}
5 | {$ENDIF}
6 |
7 | uses
8 | DUnitTestRunner,
9 | TestLexer in 'TestLexer.pas',
10 | TestHtmlParser in 'TestHtmlParser.pas',
11 | TestXPath in 'TestXPath.pas',
12 | HtmlParser in '..\HtmlParser.pas',
13 | XPathLexer in '..\XPathLexer.pas',
14 | XPath in '..\XPath.pas';
15 |
16 | {$R *.RES}
17 |
18 | begin
19 | DUnitTestRunner.RunRegisteredTests;
20 | end.
21 |
22 |
--------------------------------------------------------------------------------
/XPath/UnitTest/XPathTests.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delphiripper/comotobo/22a39d8425f07c7a6ddfc0758db309785b67b4d9/XPath/UnitTest/XPathTests.res
--------------------------------------------------------------------------------
/XPath/XPath EBNF.txt:
--------------------------------------------------------------------------------
1 | XPath ::= Expr
2 |
3 | Expr ::= AndExpr { "or" AndExpr }
4 | AndExpr ::= ComparisonExpr { "and" ComparisonExpr }
5 | ComparisonExpr ::= AdditiveExpr { ("=" | "!=" | "<" | "<=" | ">" | ">=") AdditiveExpr }
6 | AdditiveExpr ::= MultiplicativeExpr { ("+" | "-") MultiplicativeExpr }
7 | MultiplicativeExpr ::= UnaryExpr { ("*" | "div" | "idiv" | "mod") UnaryExpr }
8 |
9 | UnaryExpr ::= { "-" | "+" } PathExpr
10 | PathExpr ::= [ "/" | "//" ] RelativePathExpr
11 | RelativePathExpr ::= StepExpr { ("/" | "//") StepExpr }
12 | StepExpr ::= ( PrimaryExpr | Step ) { Predicate }
13 | Step ::= (Axis "::" NodeTest) | ([ "@" ] NodeTest) | ".."
14 | NodeTest ::= KindTest | IDENTIFIER | "*"
15 | PrimaryExpr ::= INTEGER | FLOAT | STRING | ( "$" IDENTIFIER ) | ( "(" Expr ")" ) | "." | IDENTIFIER "(" [ ParameterList ] ")"
16 | ParameterList ::= ExprSingle { "," ExprSingle }
17 | KindTest ::= "document-node" DocumentTest
18 | | ElementTest
19 | | "attribute" AttributeTest
20 | | "schema-element" "(" IDENTIFIER ")"
21 | | "schema-attribute" "(" IDENTIFIER ")"
22 | | "processing-instruction" "(" [ NCName | StringLiteral ] ")"
23 | | "comment" "(" ")"
24 | | "text" "(" ")"
25 | | "node" "(" ")"
26 | DocumentTest ::= "(" [ ElementTest ] ")"
27 | AttributeTest ::= "(" [ ( IDENTIFIER | "*" ) [ "," TypeName ] ] ")"
28 | ElementTest ::= "element" "(" [ ( IDENTIFIER | "*" ) [ "," TypeName [ "?" ] ] ] ")"
29 |
30 | TypeName ::= IDENTIFIER
31 | Axis ::= "child" | "descendant" | "attribute" | "self" | "descendant-or-self" | "following-sibling" | "following" | "namespace" |
32 | "parent" | "ancestor" | "preceding-sibling" | "preceding" | "ancestor-or-self"
33 |
34 |
35 |
36 |
37 | ///////////////////////////////////////////////////////////////////
38 |
39 |
40 |
41 |
42 |
43 |
44 | XPath ::= Expr
45 | Expr ::= ExprSingle ("," ExprSingle)*
46 | ExprSingle ::= ForExpr
47 | | QuantifiedExpr
48 | | IfExpr
49 | | OrExpr
50 | ForExpr ::= SimpleForClause "return" ExprSingle
51 | SimpleForClause ::= "for" "$" VarName "in" ExprSingle ("," "$" VarName "in" ExprSingle)*
52 | QuantifiedExpr ::= ("some" | "every") "$" VarName "in" ExprSingle ("," "$" VarName "in" ExprSingle)* "satisfies" ExprSingle
53 | IfExpr ::= "if" "(" Expr ")" "then" ExprSingle "else" ExprSingle
54 | OrExpr ::= AndExpr ( "or" AndExpr )*
55 | AndExpr ::= ComparisonExpr ( "and" ComparisonExpr )*
56 | ComparisonExpr ::= RangeExpr ( (ValueComp
57 | | GeneralComp
58 | | NodeComp) RangeExpr )?
59 | RangeExpr ::= AdditiveExpr ( "to" AdditiveExpr )?
60 | AdditiveExpr ::= MultiplicativeExpr ( ("+" | "-") MultiplicativeExpr )*
61 | MultiplicativeExpr ::= UnionExpr ( ("*" | "div" | "idiv" | "mod") UnionExpr )*
62 | UnionExpr ::= IntersectExceptExpr ( ("union" | "|") IntersectExceptExpr )*
63 | IntersectExceptExpr ::= InstanceofExpr ( ("intersect" | "except") InstanceofExpr )*
64 | InstanceofExpr ::= TreatExpr ( "instance" "of" SequenceType )?
65 | TreatExpr ::= CastableExpr ( "treat" "as" SequenceType )?
66 | CastableExpr ::= CastExpr ( "castable" "as" SingleType )?
67 | CastExpr ::= UnaryExpr ( "cast" "as" SingleType )?
68 | UnaryExpr ::= ("-" | "+")* ValueExpr
69 | ValueExpr ::= PathExpr
70 | GeneralComp ::= "=" | "!=" | "<" | "<=" | ">" | ">="
71 | ValueComp ::= "eq" | "ne" | "lt" | "le" | "gt" | "ge"
72 | NodeComp ::= "is" | "<<" | ">>"
73 | PathExpr ::= ("/" RelativePathExpr?)
74 | | ("//" RelativePathExpr)
75 | | RelativePathExpr/* xgs: leading-lone-slash */
76 | RelativePathExpr ::= StepExpr (("/" | "//") StepExpr)*
77 | StepExpr ::= FilterExpr | AxisStep
78 | AxisStep ::= (ReverseStep | ForwardStep) PredicateList
79 | ForwardStep ::= (ForwardAxis NodeTest) | AbbrevForwardStep
80 | ForwardAxis ::= ("child" "::")
81 | | ("descendant" "::")
82 | | ("attribute" "::")
83 | | ("self" "::")
84 | | ("descendant-or-self" "::")
85 | | ("following-sibling" "::")
86 | | ("following" "::")
87 | | ("namespace" "::")
88 | AbbrevForwardStep ::= "@"? NodeTest
89 | ReverseStep ::= (ReverseAxis NodeTest) | AbbrevReverseStep
90 | ReverseAxis ::= ("parent" "::")
91 | | ("ancestor" "::")
92 | | ("preceding-sibling" "::")
93 | | ("preceding" "::")
94 | | ("ancestor-or-self" "::")
95 | AbbrevReverseStep ::= ".."
96 | NodeTest ::= KindTest | NameTest
97 | NameTest ::= QName | Wildcard
98 | Wildcard ::= "*"
99 | | (NCName ":" "*")
100 | | ("*" ":" NCName) /* ws: explicit */
101 | FilterExpr ::= PrimaryExpr PredicateList
102 | PredicateList ::= Predicate*
103 | Predicate ::= "[" Expr "]"
104 | PrimaryExpr ::= Literal | VarRef | ParenthesizedExpr | ContextItemExpr | FunctionCall
105 | Literal ::= NumericLiteral | StringLiteral
106 | NumericLiteral ::= IntegerLiteral | DecimalLiteral | DoubleLiteral
107 | VarRef ::= "$" VarName
108 | VarName ::= QName
109 | ParenthesizedExpr ::= "(" Expr? ")"
110 | ContextItemExpr ::= "."
111 | FunctionCall ::= QName "(" (ExprSingle ("," ExprSingle)*)? ")"/* xgs: reserved-function-names */
112 | /* gn: parens */
113 | SingleType ::= AtomicType "?"?
114 | SequenceType ::= ("empty-sequence" "(" ")")
115 | | (ItemType OccurrenceIndicator?)
116 | OccurrenceIndicator ::= "?" | "*" | "+" /* xgs: occurrence-indicators */
117 | ItemType ::= KindTest | ("item" "(" ")") | AtomicType
118 | AtomicType ::= QName
119 | KindTest ::= DocumentTest
120 | | ElementTest
121 | | AttributeTest
122 | | SchemaElementTest
123 | | SchemaAttributeTest
124 | | PITest
125 | | CommentTest
126 | | TextTest
127 | | AnyKindTest
128 | AnyKindTest ::= "node" "(" ")"
129 | DocumentTest ::= "document-node" "(" (ElementTest | SchemaElementTest)? ")"
130 | TextTest ::= "text" "(" ")"
131 | CommentTest ::= "comment" "(" ")"
132 | PITest ::= "processing-instruction" "(" (NCName | StringLiteral)? ")"
133 | AttributeTest ::= "attribute" "(" (AttribNameOrWildcard ("," TypeName)?)? ")"
134 | AttribNameOrWildcard ::= AttributeName | "*"
135 | SchemaAttributeTest ::= "schema-attribute" "(" AttributeDeclaration ")"
136 | AttributeDeclaration ::= AttributeName
137 | ElementTest ::= "element" "(" (ElementNameOrWildcard ("," TypeName "?"?)?)? ")"
138 | ElementNameOrWildcard ::= ElementName | "*"
139 | SchemaElementTest ::= "schema-element" "(" ElementDeclaration ")"
140 | ElementDeclaration ::= ElementName
141 | AttributeName ::= QName
142 | ElementName ::= QName
143 | TypeName ::= QName
144 |
--------------------------------------------------------------------------------
/XPath/XPathGroup.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {5A0E92E0-2FBC-4546-9210-04C8BD0294CC}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Default.Personality.12
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------