Skip to content

Commit 6198d77

Browse files
committed
Adapted to recent changes in SWAG collection data structure
1 parent e46411f commit 6198d77

File tree

4 files changed

+74
-40
lines changed

4 files changed

+74
-40
lines changed

Src/FmSWAGImportDlg.pas

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ TSWAGImportDlg = class(TWizardDlg, INoPublicConstruct)
133133
/// user database.</summary>
134134
fImporter: TSWAGImporter;
135135
/// <summary>ID of currently selected category.</summary>
136-
/// <remarks>Set to empty string if no category is selected.</remarks>
137-
fCurrentCatID: string;
136+
/// <remarks>Set to zero if no category is selected.</remarks>
137+
fCurrentCatID: Cardinal;
138138
/// <summary>Retrieves import directory name from edit control where it is
139139
/// entered.</summary>
140140
function GetDirNameFromEditCtrl: string;
@@ -503,7 +503,7 @@ procedure TSWAGImportDlg.DisplayPacketsForCategory;
503503
CatIdx := lbCategories.ItemIndex;
504504
if CatIdx = -1 then
505505
begin
506-
fCurrentCatID := '';
506+
fCurrentCatID := 0;
507507
Exit;
508508
end;
509509
if fCurrentCatID = fSortedCategories[CatIdx].ID then

Src/SWAG.UCommon.pas

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ interface
1818
type
1919
/// <summary>Record that encapsulates the data of a SWAG category.</summary>
2020
TSWAGCategory = record
21-
/// <summary>String that uniquely identifies a SWAG category.</summary>
22-
ID: string;
21+
/// <summary>Number that uniquely identifies a SWAG category.</summary>
22+
ID: Cardinal;
2323
/// <summary>SWAG category title.</summary>
2424
Title: string;
2525
end;
@@ -31,7 +31,7 @@ TSWAGPacket = record
3131
/// <summary>Number that uniquely identifies a SWAG packet.</summary>
3232
ID: Cardinal;
3333
/// <summary>ID of SWAG category that packet belongs to.</summary>
34-
Category: string;
34+
Category: Cardinal;
3535
/// <summary>File name of packet in original SWAG archive.</summary>
3636
FileName: string;
3737
/// <summary>Date and time packet was added to or updated in the SWAG

Src/SWAG.UReader.pas

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ interface
1818
uses
1919
// Delphi
2020
SysUtils,
21+
Generics.Defaults,
2122
Generics.Collections,
2223
// Project
2324
SWAG.UCommon,
@@ -58,7 +59,7 @@ TSWAGReader = class(TObject)
5859
/// <para>Only partial information that summarises each packet is
5960
/// stored.</para>
6061
/// </remarks>
61-
fPacketsByCategory: TDictionary<string,TList<TSWAGPacket>>;
62+
fPacketsByCategory: TDictionary<Cardinal,TList<TSWAGPacket>>;
6263
/// <summary>Object used to interogate SWAG XML file.</summary>
6364
fXMLProcessor: TSWAGXMLProcessor;
6465
/// <summary>Default wrapper for calls to the local SWAG database.
@@ -85,15 +86,15 @@ TSWAGReader = class(TObject)
8586
procedure FetchCategories(CallWrapper: TSWAGCallbackWrapper);
8687
/// <summary>Fetches summaries of all the packets contained in a given
8788
/// SWAG category from the SWAG database.</summary>
88-
/// <param name="CatID">string [in] ID of category for which packet
89+
/// <param name="CatID">Cardinal [in] ID of category for which packet
8990
/// summaries are required.</param>
9091
/// <param name="CallWrapper">TSWAGCallbackWrapper [in] Callback that is
9192
/// called and passed a closure which can retrive the required category
9293
/// information from the database. If nil then the default callback passed
9394
/// to the constructor is used.</param>
9495
/// <remarks>The fetched packet summaries are cached in
9596
/// fPacketsByCategory.</remarks>
96-
procedure FetchPartialPackets(const CatID: string;
97+
procedure FetchPartialPackets(const CatID: Cardinal;
9798
CallWrapper: TSWAGCallbackWrapper);
9899
/// <summary>Fetches full details a packet from the SWAG database.
99100
/// </summary>
@@ -147,7 +148,7 @@ TSWAGReader = class(TObject)
147148
CallWrapper: TSWAGCallbackWrapper = nil);
148149
/// <summary>Gets summaries of all the packets contained in a given SWAG
149150
/// category.</summary>
150-
/// <param name="CatID">string [in] ID of the required category.</param>
151+
/// <param name="CatID">Cardinal [in] ID of the required category.</param>
151152
/// <param name="Packets">TList&lt;TSWAGPacket&gt; [in] Receives the
152153
/// required list of packet summaries.</param>
153154
/// <param name="CallWrapper">TSWAGCallbackWrapper [in] Callback that is
@@ -158,7 +159,7 @@ TSWAGReader = class(TObject)
158159
/// CallWrapper is called to retrieve the required packets. On subsequent
159160
/// calls for that category the packets summaries are read from a cache
160161
/// and CallWrapper is not called.</remarks>
161-
procedure GetPartialPackets(const CatID: string;
162+
procedure GetPartialPackets(const CatID: Cardinal;
162163
const Packets: TList<TSWAGPacket>;
163164
CallWrapper: TSWAGCallbackWrapper = nil);
164165
/// <summary>Gets full details a packet from the SWAG database.</summary>
@@ -222,9 +223,18 @@ constructor TSWAGReader.Create(const SWAGDBDir: string;
222223
inherited Create;
223224
fDefaultCallWrapper := DefaultSWAGCallbackWrapper;
224225
fCategories := TList<TSWAGCategory>.Create;
225-
fPacketsByCategory := TObjectDictionary<string,TList<TSWAGPacket>>.Create(
226+
fPacketsByCategory := TObjectDictionary<Cardinal,TList<TSWAGPacket>>.Create(
226227
[doOwnsValues],
227-
TStringEqualityComparer.Create
228+
TDelegatedEqualityComparer<Cardinal>.Create(
229+
function (const Left, Right: Cardinal): Boolean
230+
begin
231+
Result := Left = Right;
232+
end,
233+
function (const Value: Cardinal): Integer
234+
begin
235+
Result := Integer(Value);
236+
end
237+
)
228238
);
229239
fPacketCache := TSWAGPacketCache.Create(MaxPacketCacheSize);
230240
fXMLProcessor := TSWAGXMLProcessor.Create;
@@ -301,7 +311,7 @@ procedure TSWAGReader.FetchCompletePackets(const PacketIDs: TList<Cardinal>;
301311
);
302312
end;
303313

304-
procedure TSWAGReader.FetchPartialPackets(const CatID: string;
314+
procedure TSWAGReader.FetchPartialPackets(const CatID: Cardinal;
305315
CallWrapper: TSWAGCallbackWrapper);
306316
begin
307317
if not Assigned(CallWrapper) then
@@ -382,7 +392,7 @@ procedure TSWAGReader.GetCompletePackets(PacketIDs: TList<Cardinal>;
382392
end;
383393
end;
384394

385-
procedure TSWAGReader.GetPartialPackets(const CatID: string;
395+
procedure TSWAGReader.GetPartialPackets(const CatID: Cardinal;
386396
const Packets: TList<TSWAGPacket>; CallWrapper: TSWAGCallbackWrapper);
387397
begin
388398
if not fPacketsByCategory.ContainsKey(CatID) then

Src/SWAG.UXMLProcessor.pas

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ interface
1818

1919
uses
2020
// VCL
21+
XMLIntf,
2122
Generics.Collections,
2223
// Project
2324
SWAG.UCommon,
@@ -47,8 +48,8 @@ TSWAGXMLProcessor = class(TObject)
4748
cCategoryNode = 'category';
4849
cCategoryIDAttr = 'id';
4950
cCategoryTitleNode = 'title';
50-
cPacketsNode = 'snippets';
51-
cPacketNode = 'snippet';
51+
cPacketsNode = 'packets';
52+
cPacketNode = 'packet';
5253
cPacketIDAttr = 'id';
5354
cPacketCatIdNode = 'category-id';
5455
cPacketFileNameNode = 'file-name';
@@ -91,6 +92,18 @@ TSWAGXMLProcessor = class(TObject)
9192
/// <exception>ESWAGXMLProcessor raised if packet source code can&#39;t be
9293
/// loaded.</exception>
9394
procedure GetPacketSourceCode(var Packet: TSWAGPacket);
95+
/// <summary>Read and validate a positive integer value from a node
96+
/// attribute</summary>
97+
/// <param name="Node">IXMLNode [in] Node whose attribute is to be read.
98+
/// </param>
99+
/// <param name="Attr">string [in] Name of attribute.</param>
100+
/// <param name="ErrMsg">string [in] Exception error messsage to be used on
101+
/// error.</param>
102+
/// <returns>Required postive integer value.</returns>
103+
/// <exception>ESWAGXMLProcessor raised if attribute value is missing or
104+
/// is not a positive integer.</exception>
105+
function GetPositiveIntAttribute(Node: IXMLNode; const Attr: string;
106+
const ErrMsg: string): Cardinal;
94107
public
95108
/// <summary>Constructor that sets up object ready to to process XML.
96109
/// </summary>
@@ -110,13 +123,13 @@ TSWAGXMLProcessor = class(TObject)
110123
procedure GetCategories(CatList: TList<TSWAGCategory>);
111124
/// <summary>Gets partial information about all packets belonging to a
112125
/// category from the SWAG XML file.</summary>
113-
/// <param name="CatID">string [in] ID of category for which packets are
126+
/// <param name="CatID">Cardinal [in] ID of category for which packets are
114127
/// required.</param>
115128
/// <param name="PacketList">TList&lt;TSWAGPacket&gt; [in] Receives list
116129
/// of packets read.</param>
117130
/// <exception>ESWAGXMLProcessor raised if partial packets can't be read
118131
/// or are invalid.</exception>
119-
procedure GetPartialPackets(const CatID: string;
132+
procedure GetPartialPackets(const CatID: Cardinal;
120133
PacketList: TList<TSWAGPacket>);
121134
/// <summary>Gets a single packet from the SWAG XML file.</summary>
122135
/// <param name="PacketID">Cardinal [in] Unique ID of the required packet.
@@ -142,7 +155,6 @@ implementation
142155
Classes,
143156
IOUtils,
144157
ActiveX,
145-
XMLIntf,
146158
Math,
147159
DateUtils,
148160
// Project
@@ -179,6 +191,7 @@ procedure TSWAGXMLProcessor.GetCategories(CatList: TList<TSWAGCategory>);
179191
sMissingNode = 'Invalid SWAG XML file: no categories information found';
180192
sMissingID = 'Invalid SWAG XML file: missing category ID';
181193
sMissingTitle = 'Invalid SWAG XML file: missing title for category "%s"';
194+
sBadSourceID = 'Invalid SWAG XML file: invalid or missing category ID';
182195
begin
183196
CategoriesNode := fXMLDoc.FindNode(
184197
NodePath([cSWAGRootNode, cCategoriesNode])
@@ -188,9 +201,9 @@ procedure TSWAGXMLProcessor.GetCategories(CatList: TList<TSWAGCategory>);
188201
CategoryNodes := fXMLDoc.FindChildNodes(CategoriesNode, cCategoryNode);
189202
for CategoryNode in CategoryNodes do
190203
begin
191-
Category.ID := CategoryNode.Attributes[cCategoryIDAttr];
192-
if StrIsEmpty(Category.ID, True) then
193-
raise ESWAGXMLProcessor.Create(sMissingID);
204+
Category.ID := GetPositiveIntAttribute(
205+
CategoryNode, cCategoryIDAttr, sBadSourceID
206+
);
194207
Category.Title := TXMLDocHelper.GetSubTagText(
195208
fXMLDoc, CategoryNode, cCategoryTitleNode
196209
);
@@ -205,9 +218,12 @@ function TSWAGXMLProcessor.GetPacket(const PacketID: Cardinal): TSWAGPacket;
205218
AllPacketsNode: IXMLNode;
206219
PacketNode: IXMLNode;
207220
DateStr: string;
221+
PacketCatID: Cardinal;
208222
resourcestring
209223
sPacketsNodeMissing = 'Invalid SWAG XML file: no packet information found';
210224
sPacketNotFound = 'Invalid SWAG XML file: packet with ID %d not found';
225+
sBadPacketCategory = 'Invalid SWAG XML file: packet has invalid or missing '
226+
+ 'category ID';
211227
begin
212228
// Find required Packet node
213229
AllPacketsNode := fXMLDoc.FindNode(NodePath([cSWAGRootNode, cPacketsNode]));
@@ -220,9 +236,12 @@ function TSWAGXMLProcessor.GetPacket(const PacketID: Cardinal): TSWAGPacket;
220236
raise ESWAGXMLProcessor.CreateFmt(sPacketNotFound, [PacketID]);
221237
// Get Packet info from Packet node
222238
Result.ID := PacketID;
223-
Result.Category := TXMLDocHelper.GetSubTagText(
224-
fXMLDoc, PacketNode, cPacketCatIdNode
225-
);
239+
if not TryStrToCardinal(
240+
TXMLDocHelper.GetSubTagText(fXMLDoc, PacketNode, cPacketCatIdNode),
241+
PacketCatID
242+
) then
243+
raise ESWAGXMLProcessor.Create(sBadPacketCategory);
244+
Result.Category := PacketCatID;
226245
Result.FileName := TXMLDocHelper.GetSubTagText(
227246
fXMLDoc, PacketNode, cPacketFileNameNode
228247
);
@@ -255,12 +274,10 @@ procedure TSWAGXMLProcessor.GetPacketSourceCode(var Packet: TSWAGPacket);
255274
begin
256275
Assert(Packet.ID > 0, ClassName + '.GetPacketSourceCode: '
257276
+ 'Packet.ID not set');
258-
Assert(not StrIsEmpty(Packet.Category),
259-
ClassName + '.GetPacketSourceCode: Packet.Category not set');
260277
Assert(not StrIsEmpty(Packet.FileName),
261278
ClassName + '.GetPacketSourceCode: Packet.FileName not set');
262279
FilePath := StrJoin(
263-
[fSWAGRootDir, Packet.Category, Packet.FileName], PathDelim
280+
[fSWAGRootDir, Packet.FileName], PathDelim
264281
);
265282
if not TFile.Exists(FilePath, False) then
266283
raise ESWAGXMLProcessor.CreateFmt(sSourceCodeNotFound, [Packet.ID]);
@@ -271,17 +288,17 @@ procedure TSWAGXMLProcessor.GetPacketSourceCode(var Packet: TSWAGPacket);
271288
Packet.SourceCode := Code;
272289
end;
273290

274-
procedure TSWAGXMLProcessor.GetPartialPackets(const CatID: string;
291+
procedure TSWAGXMLProcessor.GetPartialPackets(const CatID: Cardinal;
275292
PacketList: TList<TSWAGPacket>);
276293
var
277294
AllPacketsNode: IXMLNode;
278295
PacketNodes: IXMLSimpleNodeList;
279296
PacketNode: IXMLNode;
280297
Packet: TSWAGPacket;
281-
PacketID: Integer;
298+
CatIDFromNode: Cardinal;
282299
resourcestring
283300
sPacketsNodeMissing = 'Invalid SWAG XML file: no packet information found';
284-
sBadSourceID = 'Invalid SWAG XML file: invalid packet ID encountered';
301+
sBadSourceID = 'Invalid SWAG XML file: missing or invalid packet ID';
285302
begin
286303
AllPacketsNode := fXMLDoc.FindNode(NodePath([cSWAGRootNode, cPacketsNode]));
287304
if not Assigned(AllPacketsNode) then
@@ -291,14 +308,14 @@ procedure TSWAGXMLProcessor.GetPartialPackets(const CatID: string;
291308
Exit;
292309
for PacketNode in PacketNodes do
293310
begin
294-
if StrSameText(
311+
if TryStrToCardinal(
295312
TXMLDocHelper.GetSubTagText(fXMLDoc, PacketNode, cPacketCatIdNode),
296-
CatID
297-
) then
313+
CatIDFromNode
314+
) and (CatIDFromNode > 0) and (CatIDFromNode = CatID) then
298315
begin
299-
if not TryStrToInt(PacketNode.Attributes[cPacketIDAttr], PacketID) then
300-
raise ESWAGXMLProcessor.Create(sBadSourceID);
301-
Packet.ID := PacketID;
316+
Packet.ID := GetPositiveIntAttribute(
317+
PacketNode, cPacketIDAttr, sBadSourceID
318+
);
302319
Packet.Title := TXMLDocHelper.GetSubTagText(
303320
fXMLDoc, PacketNode, cPacketTitleNode
304321
);
@@ -308,6 +325,13 @@ procedure TSWAGXMLProcessor.GetPartialPackets(const CatID: string;
308325
end;
309326
end;
310327

328+
function TSWAGXMLProcessor.GetPositiveIntAttribute(Node: IXMLNode; const Attr,
329+
ErrMsg: string): Cardinal;
330+
begin
331+
if not TryStrToCardinal(Node.Attributes[Attr], Result) or (Result = 0) then
332+
raise ESWAGXMLProcessor.Create(ErrMsg);
333+
end;
334+
311335
procedure TSWAGXMLProcessor.Initialise(const SWAGDirName: string);
312336
resourcestring
313337
sFileReadError = 'Can''t read SWAG database file "%0:s"' + EOL2
@@ -352,14 +376,14 @@ class function TSWAGXMLProcessor.NodePath(const Tags: array of string): string;
352376

353377
procedure TSWAGXMLProcessor.ValidatePacket(const Packet: TSWAGPacket);
354378
resourcestring
355-
sBadCatID = 'Invalid SWAG XML file: packet %d has no category';
379+
sBadCatID = 'Invalid SWAG XML file: packet %d has invalid category';
356380
sBadFileName = 'Invalid SWAG XML file: packet %d has no file name';
357381
sBadDateStamp = 'Invalid SWAG XML file: packet %d has no date stamp';
358382
sBadAuthor = 'Invalid SWAG XML file: packet %d has no author';
359383
sBadSourceCode = 'Invalid SWAG XML file: packet %d has no source code';
360384
begin
361385
ValidatePartialPacket(Packet);
362-
if StrIsEmpty(Packet.Category, True) then
386+
if Packet.Category = 0 then
363387
raise ESWAGXMLProcessor.CreateFmt(sBadCatID, [Packet.ID]);
364388
if StrIsEmpty(Packet.FileName, True) then
365389
raise ESWAGXMLProcessor.CreateFmt(sBadFileName, [Packet.ID]);

0 commit comments

Comments
 (0)