Menu

[r1786]: / trunk / Src / UCodeImportExport.pas  Maximize  Restore  History

Download this file

747 lines (685 with data), 24.7 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 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
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
{
* UCodeImportExport.pas
*
* Implements classes that can import and export user defined snippets and user
* information from and to XML.
*
* $Rev$
* $Date$
*
* ***** BEGIN LICENSE BLOCK *****
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is UCodeImportExport.pas
*
* The Initial Developer of the Original Code is Peter Johnson
* (http://www.delphidabbler.com/).
*
* Portions created by the Initial Developer are Copyright (C) 2008-2011 Peter
* Johnson. All Rights Reserved.
*
* Contributor(s)
* NONE
*
* ***** END LICENSE BLOCK *****
}
unit UCodeImportExport;
interface
uses
// Delphi
SysUtils, Classes, XMLIntf,
// Project
DB.USnippet, UBaseObjects, UEncodings, UExceptions, UIStringList,
UUserDetails, UXMLDocHelper, UXMLDocumentEx;
type
{
TSnippetInfo:
Record that encapsulates data read from an import file that describes a
snippet.
}
TSnippetInfo = record
Name: string; // Snippet name
Data: TSnippetEditData; // Describes a snippet
procedure Assign(const Src: TSnippetInfo);
{Sets this record's fields to be same as another TSnippetInfo record.
Object fields are copied appropriately.
@param Src [in] Record containing fields to be copied.
}
procedure Init;
{Initialises record to nul values.
}
end;
{
TSnippetInfoList:
Dynamic array of TSnippetInfo records.
}
TSnippetInfoList = array of TSnippetInfo;
{
TUserInfo:
Record that encapsulates user info optionally stored in export files.
}
TUserInfo = record
Details: TUserDetails; // User's personal details
Comments: string; // User's comments
constructor Create(const UserDetails: TUserDetails;
const UserComments: string);
{Initialises all a fields of a record.
@param UserDetails [in] Information about user.
@param UserComments [in] User's comments.
}
class function CreateNul: TUserInfo; static;
{Create a new nul record.
@return Required initialised record.
}
procedure Assign(const Src: TUserInfo);
{Sets this record's fields to be same as another TUserInfo record.
@param Src [in] Record containing fields to be copied.
}
procedure Init;
{Initialises record to nul values.
}
function IsNul: Boolean;
{Checks if record is nul (empty).
@return True if record is nul, False if not.
}
end;
{
TCodeImporter:
Class that imports code snippets and user info from XML.
}
TCodeImporter = class(TNoPublicConstructObject)
strict private
fVersion: Integer; // Version of file being imported
fUserInfo: TUserInfo; // Information about user who created export
fSnippetInfp: TSnippetInfoList; // List of snippets read from XML
fXMLDoc: IXMLDocumentEx; // Extended XML document object
function GetAllSnippetNodes: IXMLSimpleNodeList;
{Retrieves a list of all snippet nodes in XML document.
@return Required node list.
}
procedure Execute(const Data: TBytes);
{Performs the import.
@param Data [in] Byte array containing XML data.
}
function ValidateDoc: Integer;
{Validates XML document read from stream and gets file version.
@return XML file version number.
@except ECodeImporter raised if XML is not valid.
}
constructor InternalCreate;
{Private class constructor. Sets up object to import data.
}
public
destructor Destroy; override;
{Class destructor. Tidies up object.
}
class procedure ImportData(out UserInfo: TUserInfo;
out SnippetInfo: TSnippetInfoList; const Data: TBytes);
{Imports snippets and optional user data from XML.
@param UserInfo [out] Receives user info. Set to nul if no user info was
available.
@param SnippetInfo [out] Receives information about each snippet read.
@param Data [in] Byte array containing XML data.
}
end;
{
ECodeImporter:
Class of exception raised when TCodeImporter encounters invalid XML.
}
ECodeImporter = class(ECodeSnipXML);
{
TCodeExporter:
Class that exports code snippets and user info to XML.
}
TCodeExporter = class(TNoPublicConstructObject)
strict private
var fUserInfo: TUserInfo; // User information to be written to XML
var fSnippets: TSnippetList; // List of snippets to be exported
var fXMLDoc: IXMLDocumentEx; // Extended XML document object
procedure HandleException(const EObj: TObject);
{Handles exceptions by converting expected exceptions into ECodeExporter.
Unexpected exceptions are re-raised.
@param EObj [in] Reference to exception to be handled.
@except Always raise an exception.
}
function SnippetNames(const SnipList: TSnippetList): IStringList;
{Builds a list of snippet names from a snippet list.
@param SnipList [in] List of snippets.
@return List containing names of all snippets names.
}
procedure WriteReferenceList(const ParentNode: IXMLNode;
const ListNodeName: string; PasNames: IStringList);
{Writes a XML node that contains a list of pascal names.
@param ParentNode [in] Node under which this list node is to be created.
@param ListNodeName [in] Tag name of list node.
@param PasNames [in] List of pascal names to be written as child nodes
of list.
}
procedure WriteProgInfo(const ParentNode: IXMLNode);
{Writes XML node containing CodeSnip version information.
@param ParentNode [in] Node under which this node is to be created.
}
procedure WriteUserInfo(const ParentNode: IXMLNode);
{Writes a node and sub-nodes containing any information about user who
created export file.
@param ParentNode [in] Node under which user info node to be written.
}
procedure WriteSnippets(const ParentNode: IXMLNode);
{Writes a snippets node and sub-nodes containing details of all exported
snippets.
@param ParentNode [in] Node under which snippet list node to be
created.
}
procedure WriteSnippet(const ParentNode: IXMLNode; const Snippet: TSnippet);
{Writes an XML snippet node and child nodes that describe a snippet.
@param ParentNode [in] Node under which snippet node is to be created.
@param Snippet [in] Reference to snippet to be described in XML.
}
function Execute: TEncodedData;
{Performs the export.
@return Encoded data containing exported XML.
@except ECodeExporter raised if a known error is encountered.
}
constructor InternalCreate(const UserInfo: TUserInfo;
const SnipList: TSnippetList);
{Private object constructor. Sets up object to export data.
@param UserInfo [in] User information to be exported.
@param SnipList [in] List of snippets to be exported.
}
public
destructor Destroy; override;
{Object destructor: tidies up object.
}
class function ExportSnippets(const UserInfo: TUserInfo;
const SnipList: TSnippetList): TEncodedData;
{Exports user information and snippets as XML.
@param UserInfo [in] User information to be exported. Ignored if nul.
@param SnipList [in] List of snippets to be exported.
@return Encoding data containing exported XML.
}
end;
{
ECodeExporter:
Class of exception raised when TCodeExporter detects an expected error.
}
ECodeExporter = class(ECodeSnipXML);
implementation
uses
// Delphi
ActiveX, XMLDom,
// Project
DB.UMain, DB.USnippetKind, UAppInfo, UREMLDataIO, UReservedCategories,
USnippetExtraHelper, USnippetIDs, UStructs, UXMLDocConsts;
const
// XML file markers: attributes of root node
// watermark (never changes for all versions)
cWatermark = 'B46969D4-D367-4F5F-833E-F165FBA78631';
// file version numbers
cEarliestVersion = 1; // earliest file version supported by importer
cLatestVersion = 5; // current file version written by exporter
{ TUserInfo }
procedure TUserInfo.Assign(const Src: TUserInfo);
{Sets this record's fields to be same as another TUserInfo record.
@param Src [in] Record containing fields to be copied.
}
begin
Details.Assign(Src.Details);
Comments := Src.Comments;
end;
constructor TUserInfo.Create(const UserDetails: TUserDetails;
const UserComments: string);
{Initialises all a fields of a record.
@param UserDetails [in] Information about user.
@param UserComments [in] User's comments.
}
begin
Details := UserDetails;
Comments := UserComments;
end;
class function TUserInfo.CreateNul: TUserInfo;
{Create a new nul record.
@return Required initialised record.
}
begin
Result.Init;
end;
procedure TUserInfo.Init;
{Initialises record to nul values.
}
begin
Details.Init;
Comments := '';
end;
function TUserInfo.IsNul: Boolean;
{Checks if record is nul (empty).
@return True if record is nul, False if not.
}
begin
Result := Details.IsNul and (Comments = '');
end;
{ TCodeExporter }
destructor TCodeExporter.Destroy;
{Object destructor: tidies up object.
}
begin
fXMLDoc := nil;
inherited;
end;
function TCodeExporter.Execute: TEncodedData;
{Performs the export.
@return Encoded data containing exported XML.
@except ECodeExporter raised if a known error is encountered.
}
var
RootNode: IXMLNode; // document root node
resourcestring
// Comment written to XML file
sFileComment = 'This file was generated by CodeSnip. Do not edit.';
begin
// Create and configure XML document
fXMLDoc := TXMLDocHelper.CreateXMLDoc;
try
fXMLDoc.Active := True;
// Add XML root nodes
TXMLDocHelper.CreateXMLProcInst(fXMLDoc);
TXMLDocHelper.CreateComment(fXMLDoc, sFileComment);
RootNode := TXMLDocHelper.CreateRootNode(
fXMLDoc, cExportRootNode, cWatermark, cLatestVersion
);
// Write document content
WriteProgInfo(RootNode);
if not fUserInfo.IsNul then
WriteUserInfo(RootNode);
WriteSnippets(RootNode);
// Save XML as UTF-8 with no BOM
fXMLDoc.Encoding := 'UTF-8';
Result := TEncodedData.Create(fXMLDoc.SaveToBytes, etUTF8);
except
HandleException(ExceptObject);
end;
end;
class function TCodeExporter.ExportSnippets(const UserInfo: TUserInfo;
const SnipList: TSnippetList): TEncodedData;
{Exports user information and snippets as XML.
@param UserInfo [in] User information to be exported. Ignored if nul.
@param SnipList [in] List of snippets to be exported.
@return Encoding data containing exported XML.
}
begin
with InternalCreate(UserInfo, SnipList) do
try
Result := Execute;
finally
Free;
end;
end;
procedure TCodeExporter.HandleException(const EObj: TObject);
{Handles exceptions by converting expected exceptions into ECodeExporter.
Unexpected exceptions are re-raised.
@param EObj [in] Reference to exception to be handled.
@except Always raise an exception.
}
begin
if (EObj is EFileStreamError) or (EObj is ECodeSnipXML) then
raise ECodeExporter.Create(EObj as Exception);
raise EObj;
end;
constructor TCodeExporter.InternalCreate(const UserInfo: TUserInfo;
const SnipList: TSnippetList);
{Private object constructor. Sets up object to export data.
@param UserInfo [in] User information to be exported.
@param SnipList [in] List of snippets to be exported.
}
begin
inherited InternalCreate;
fSnippets := SnipList;
fUserInfo := UserInfo;
end;
function TCodeExporter.SnippetNames(
const SnipList: TSnippetList): IStringList;
{Builds a list of snippet names from a snippet list.
@param SnipList [in] List of snippets.
@return List containing names of all snippet names.
}
var
Snippet: TSnippet; // references each snippet in list
begin
Result := TIStringList.Create;
for Snippet in SnipList do
Result.Add(Snippet.Name);
end;
procedure TCodeExporter.WriteProgInfo(const ParentNode: IXMLNode);
{Writes XML node containing CodeSnip version information.
@param ParentNode [in] Node under which this node is to be created.
}
begin
fXMLDoc.CreateElement(
ParentNode, cProgVersionNode, TAppInfo.ProgramReleaseVersion
);
end;
procedure TCodeExporter.WriteReferenceList(const ParentNode: IXMLNode;
const ListNodeName: string; PasNames: IStringList);
{Writes a XML node that contains a list of pascal names.
@param ParentNode [in] Node under which this list node is to be created.
@param ListNodeName [in] Tag name of list node.
@param PasNames [in] List of pascal names to be written as child nodes of
list.
}
begin
// Don't write list tags if no items
if PasNames.Count = 0 then
Exit;
// Write the list
TXMLDocHelper.WritePascalNameList(
fXMLDoc, ParentNode, ListNodeName, PasNames
);
end;
procedure TCodeExporter.WriteSnippet(const ParentNode: IXMLNode;
const Snippet: TSnippet);
{Writes an XML snippet node and child nodes that describe a snippet.
@param ParentNode [in] Node under which snippet node is to be created.
@param Snippet [in] Reference to snippet to be described in XML.
}
var
SnippetNode: IXMLNode; // new snippet node
begin
// Create snippet node with attribute that specifies snippet name
SnippetNode := fXMLDoc.CreateElement(ParentNode, cSnippetNode);
SnippetNode.Attributes[cSnippetNameAttr] := Snippet.Name;
// Add nodes for properties: (ignore category and xrefs)
fXMLDoc.CreateElement(SnippetNode, cDescriptionNode, Snippet.Description);
// source code is stored directly in XML, not in external file
fXMLDoc.CreateElement(SnippetNode, cSourceCodeTextNode, Snippet.SourceCode);
// extra info is written only if present
if not Snippet.Extra.IsEmpty then
fXMLDoc.CreateElement(
SnippetNode,
cExtraNode,
TSnippetExtraHelper.BuildREMLMarkup(Snippet.Extra)
);
// write kind
TXMLDocHelper.WriteSnippetKind(fXMLDoc, SnippetNode, Snippet.Kind);
// compiler results value: only write known results
TXMLDocHelper.WriteCompilerResults(
fXMLDoc, SnippetNode, Snippet.Compatibility
);
// depends and units lists
WriteReferenceList(
SnippetNode, cDependsNode, SnippetNames(Snippet.Depends)
);
WriteReferenceList(
SnippetNode, cUnitsNode, TIStringList.Create(Snippet.Units)
);
end;
procedure TCodeExporter.WriteSnippets(const ParentNode: IXMLNode);
{Writes a snippet node and sub-nodes containing details of all exported
snippets.
@param ParentNode [in] Node under which snippet list node to be created.
}
var
Node: IXMLNode; // new snippets list node
Snippet: TSnippet; // refers to each exported snippet
begin
// Add snippets list node
Node := fXMLDoc.CreateElement(ParentNode, cSnippetsNode);
// Add child node for each exported snippet
for Snippet in fSnippets do
WriteSnippet(Node, Snippet);
end;
procedure TCodeExporter.WriteUserInfo(const ParentNode: IXMLNode);
{Writes a node and sub-nodes containing any information about user who
created export file.
@param ParentNode [in] Node under which user info node to be written.
}
var
UserInfoNode: IXMLNode; // new user info parent node
begin
// Add user info node
UserInfoNode := fXMLDoc.CreateElement(ParentNode, cUserInfoNode);
// Add separate child node for each piece of user info
fXMLDoc.CreateElement(UserInfoNode, cUserNameNode, fUserInfo.Details.Name);
fXMLDoc.CreateElement(UserInfoNode, cUserEmailNode, fUserInfo.Details.Email);
fXMLDoc.CreateElement(UserInfoNode, cUserCommentsNode, fUserInfo.Comments);
end;
{ TCodeImporter }
destructor TCodeImporter.Destroy;
{Class destructor. Tidies up object.
}
begin
fXMLDoc := nil;
OleUninitialize;
inherited;
end;
procedure TCodeImporter.Execute(const Data: TBytes);
{Performs the import.
@param Data [in] Byte array containing XML data.
}
// ---------------------------------------------------------------------------
procedure GetUnits(const SnippetNode: IXMLNode; Units: IStringList);
{Gets a list of units required by a snippet.
@param SnippetNode [in] Node of snippet for which units are required.
@param Units [in] Receives list of unit names. Cleared if there are no
unit names.
}
var
UnitNode: IXMLNode; // unit list node: nil if no list
begin
UnitNode := fXMLDoc.FindFirstChildNode(SnippetNode, cUnitsNode);
Units.Clear;
TXMLDocHelper.GetPascalNameList(fXMLDoc, UnitNode, Units);
end;
procedure GetDepends(const SnippetNode: IXMLNode;
const Depends: ISnippetIDList);
{Gets a list of snippets on which a snippet depends.
@param SnippetNode [in] Node of snippet for which dependencies are
required.
@param Depends [in] Receives list of required snippets. Cleared if the are
no required snippets.
}
var
DependsNode: IXMLNode; // depends node list: nil if no list
SnippetNames: IStringList; // list of names of snippets in depends list
SnippetName: string; // each snippet name in SnippetNames
begin
DependsNode := fXMLDoc.FindFirstChildNode(SnippetNode, cDependsNode);
SnippetNames := TIStringList.Create;
TXMLDocHelper.GetPascalNameList(fXMLDoc, DependsNode, SnippetNames);
Depends.Clear;
for SnippetName in SnippetNames do
// Note: in building snippet ID list we assume each snippet is user-
// defined. It may not be, but there is no way of telling from XML.
Depends.Add(TSnippetID.Create(SnippetName, True));
end;
// ---------------------------------------------------------------------------
resourcestring
// Error message
sParseError = 'Import file has an invalid format';
var
UserNode: IXMLNode; // node containing any user info
SnippetNodes: IXMLSimpleNodeList; // list of snippet nodes
SnippetNode: IXMLNode; // each snippet node in list
Idx: Integer; // loops thru snippet node list
begin
// Load XML document
try
fXMLDoc.LoadFromBytes(Data);
fXMLDoc.Active := True;
// Validate loaded document and get version number
fVersion := ValidateDoc;
// Get user info
UserNode := fXMLDoc.FindNode(cExportRootNode + '\' + cUserInfoNode);
if Assigned(UserNode) then
begin
fUserInfo.Details.Name := TXMLDocHelper.GetSubTagText(
fXMLDoc, UserNode, cUserNameNode
);
fUserInfo.Details.Email := TXMLDocHelper.GetSubTagText(
fXMLDoc, UserNode, cUserEmailNode
);
fUserInfo.Comments := TXMLDocHelper.GetSubTagText(
fXMLDoc, UserNode, cUserCommentsNode
);
end;
// Read in all snippets
SnippetNodes := GetAllSnippetNodes;
SetLength(fSnippetInfp, SnippetNodes.Count);
for Idx := 0 to Pred(SnippetNodes.Count) do
begin
// Read a snippet node
SnippetNode := SnippetNodes[Idx];
fSnippetInfp[Idx].Name := SnippetNode.Attributes[cSnippetNameAttr];
fSnippetInfp[Idx].Data :=
(Database as IDatabaseEdit).GetEditableSnippetInfo;
with fSnippetInfp[Idx].Data do
begin
Props.Cat := TReservedCategories.ImportsCatID;
Props.Desc :=
TXMLDocHelper.GetSubTagText(fXMLDoc, SnippetNode, cDescriptionNode);
Props.SourceCode :=
TXMLDocHelper.GetSubTagText(
fXMLDoc, SnippetNode, cSourceCodeTextNode
);
// how we read extra property depends on version of file
case fVersion of
1:
Props.Extra := TSnippetExtraHelper.BuildActiveText(
TXMLDocHelper.GetSubTagText(fXMLDoc, SnippetNode, cCommentsNode),
TXMLDocHelper.GetSubTagText(fXMLDoc, SnippetNode, cCreditsNode),
TXMLDocHelper.GetSubTagText(fXMLDoc, SnippetNode, cCreditsUrlNode)
);
else // later versions
Props.Extra := TSnippetExtraHelper.BuildActiveText(
TXMLDocHelper.GetSubTagText(fXMLDoc, SnippetNode, cExtraNode)
);
end;
// how we read kind property depends on version of file
case fVersion of
1, 2:
// for version 1 and 2, we have StandardFormat instead of Kind:
// map standard format value onto a kind
if TXMLDocHelper.GetStandardFormat(fXMLDoc, SnippetNode, False) then
Props.Kind := skRoutine
else
Props.Kind := skFreeform;
else // later versions
// for later versions we have Kind value: use Freeform if missing
Props.Kind := TXMLDocHelper.GetSnippetKind(
fXMLDoc, SnippetNode, skFreeForm
);
end;
Props.CompilerResults := TXMLDocHelper.GetCompilerResults(
fXMLDoc, SnippetNode
);
GetUnits(SnippetNode, Refs.Units);
GetDepends(SnippetNode, Refs.Depends);
Refs.XRef.Clear;
end;
end;
except
on E: EDOMParseError do
raise ECodeImporter.Create(sParseError);
on E: ECodeSnipXML do
raise ECodeImporter.Create(E);
else
raise;
end;
end;
function TCodeImporter.GetAllSnippetNodes: IXMLSimpleNodeList;
{Retrieves a list of all snippet nodes in XML document.
@return Required node list.
}
var
SnippetsNode: IXMLNode; // node under which all snippets are stored
begin
SnippetsNode := fXMLDoc.FindNode(cExportRootNode + '\' + cSnippetsNode);
Result := fXMLDoc.FindChildNodes(SnippetsNode, cSnippetNode);
end;
class procedure TCodeImporter.ImportData(out UserInfo: TUserInfo;
out SnippetInfo: TSnippetInfoList; const Data: TBytes);
{Imports snippets and optional user data from XML.
@param UserInfo [out] Receives user info. Set to nul if no user info was
available.
@param SnippetInfo [out] Receives information about each snippet read.
@param Data [in] Byte array containing XML data.
}
var
Idx: Integer; // loops through all imported snippets
begin
with InternalCreate do
try
Execute(Data);
UserInfo.Assign(fUserInfo);
SetLength(SnippetInfo, Length(fSnippetInfp));
for Idx := Low(fSnippetInfp) to High(fSnippetInfp) do
SnippetInfo[Idx].Assign(fSnippetInfp[Idx]);
finally
Free;
end;
end;
constructor TCodeImporter.InternalCreate;
{Private class constructor. Sets up object to import data.
}
begin
inherited InternalCreate;
// Set up XML document that will read data
OleInitialize(nil);
fXMLDoc := TXMLDocHelper.CreateXMLDoc;
// Initialise fields that receive imported data
SetLength(fSnippetInfp, 0);
fUserInfo.Init;
end;
function TCodeImporter.ValidateDoc: Integer;
{Validates XML document read from stream and gets file version.
@return XML file version number.
@except ECodeImporter raised if XML is not valid.
}
var
SnippetsNode: IXMLNode; // node where snippets are recorded
SnippetNodes: IXMLSimpleNodeList; // list of nodes describing snippets
resourcestring
// Error message
sMissingNode = 'Invalid document: no <%s> node present';
begin
TXMLDocHelper.ValidateProcessingInstr(fXMLDoc);
Result := TXMLDocHelper.ValidateRootNode(
fXMLDoc,
cExportRootNode,
cWatermark,
TRange.Create(cEarliestVersion, cLatestVersion)
);
// Must be a snippets node
SnippetsNode := fXMLDoc.FindNode(cExportRootNode + '\' + cSnippetsNode);
if not Assigned(SnippetsNode) then
raise ECodeImporter.CreateFmt(sMissingNode, [cSnippetsNode]);
// Must be at least one snippet node
SnippetNodes := fXMLDoc.FindChildNodes(SnippetsNode, cSnippetNode);
if SnippetNodes.Count = 0 then
raise ECodeImporter.CreateFmt(sMissingNode, [cSnippetNode]);
end;
{ TSnippetInfo }
procedure TSnippetInfo.Assign(const Src: TSnippetInfo);
{Sets this record's fields to be same as another TSnippetInfo record.
Object fields are copied appropriately.
@param Src [in] Record containing fields to be copied.
}
begin
Name := Src.Name;
Data.Assign(Src.Data);
end;
procedure TSnippetInfo.Init;
{Initialises record to nul values.
}
begin
Name := '';
Data.Init;
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.