PSStackHelper.pas 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. unit PSStackHelper;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2024 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. ROPS TPSStack helper class
  8. }
  9. interface
  10. uses
  11. Classes,
  12. uPSRuntime;
  13. type
  14. TPSStackHelper = class helper for TPSStack
  15. private
  16. function GetArray(const ItemNo, FieldNo: Longint; out N: Integer): TPSVariantIFC;
  17. function SetArray(const ItemNo, FieldNo: Longint; const N: Integer): TPSVariantIFC; overload;
  18. public
  19. type
  20. TArrayOfInteger = array of Integer;
  21. TArrayOfString = array of String;
  22. TArrayBuilder = record
  23. Arr: TPSVariantIFC;
  24. I: Integer;
  25. procedure Add(const Data: String);
  26. end;
  27. TArrayEnumerator = record
  28. Arr: TPSVariantIFC;
  29. N, I: Integer;
  30. function HasNext: Boolean;
  31. function Next: String;
  32. end;
  33. function GetChar(const ItemNo: Longint): Char;
  34. function GetIntArray(const ItemNo: Longint; const FieldNo: Longint = -1): TArrayOfInteger;
  35. function GetProc(const ItemNo: Longint; const Exec: TPSExec): TMethod;
  36. function GetStringArray(const ItemNo: Longint; const FieldNo: Longint = -1): TArrayOfString;
  37. function InitArrayBuilder(const ItemNo: LongInt; const FieldNo: Longint = -1): TArrayBuilder;
  38. function InitArrayEnumerator(const ItemNo: LongInt; const FieldNo: Longint = -1): TArrayEnumerator;
  39. procedure SetArray(const ItemNo: Longint; const Data: TArray<String>; const FieldNo: Longint = -1); overload;
  40. procedure SetArray(const ItemNo: Longint; const Data: TStrings; const FieldNo: Longint = -1); overload;
  41. procedure SetInt(const ItemNo: Longint; const Data: Integer; const FieldNo: Longint = -1);
  42. end;
  43. implementation
  44. function TPSStackHelper.GetArray(const ItemNo, FieldNo: Longint;
  45. out N: Integer): TPSVariantIFC;
  46. begin
  47. if FieldNo >= 0 then
  48. Result := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo)
  49. else
  50. Result := NewTPSVariantIFC(Items[ItemNo], True);
  51. N := PSDynArrayGetLength(Pointer(Result.Dta^), Result.aType);
  52. end;
  53. function TPSStackHelper.SetArray(const ItemNo, FieldNo: Longint;
  54. const N: Integer): TPSVariantIFC;
  55. begin
  56. if FieldNo >= 0 then
  57. Result := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo)
  58. else
  59. Result := NewTPSVariantIFC(Items[ItemNo], True);
  60. PSDynArraySetLength(Pointer(Result.Dta^), Result.aType, N);
  61. end;
  62. function TPSStackHelper.GetChar(const ItemNo: Longint): Char;
  63. begin
  64. var S := GetString(ItemNo);
  65. if S <> '' then
  66. Result := S[1]
  67. else
  68. Result := #0;
  69. end;
  70. function TPSStackHelper.GetIntArray(const ItemNo, FieldNo: Longint): TArrayOfInteger;
  71. begin
  72. var N: Integer;
  73. var Arr := GetArray(ItemNo, FieldNo, N);
  74. SetLength(Result, N);
  75. for var I := 0 to N-1 do
  76. Result[I] := VNGetInt(PSGetArrayField(Arr, I));
  77. end;
  78. function TPSStackHelper.GetProc(const ItemNo: Longint; const Exec: TPSExec): TMethod;
  79. begin
  80. var P := PPSVariantProcPtr(Items[ItemNo]);
  81. { ProcNo 0 means nil was passed by the script and GetProcAsMethod will then return a (nil, nil) TMethod }
  82. Result := Exec.GetProcAsMethod(P.ProcNo);
  83. end;
  84. function TPSStackHelper.GetStringArray(const ItemNo, FieldNo: Longint): TArrayOfString;
  85. begin
  86. var N: Integer;
  87. var Arr := GetArray(ItemNo, FieldNo, N);
  88. SetLength(Result, N);
  89. for var I := 0 to N-1 do
  90. Result[I] := VNGetString(PSGetArrayField(Arr, I));
  91. end;
  92. function TPSStackHelper.InitArrayBuilder(const ItemNo, FieldNo: Longint): TArrayBuilder;
  93. begin
  94. Result.Arr := SetArray(ItemNo, FieldNo, 0);
  95. Result.I := 0;
  96. end;
  97. procedure TPSStackHelper.TArrayBuilder.Add(const Data: String);
  98. begin
  99. PSDynArraySetLength(Pointer(Arr.Dta^), Arr.aType, I+1);
  100. VNSetString(PSGetArrayField(Arr, I), Data);
  101. Inc(I);
  102. end;
  103. function TPSStackHelper.InitArrayEnumerator(const ItemNo, FieldNo: Longint): TArrayEnumerator;
  104. begin
  105. Result.Arr := GetArray(ItemNo, FieldNo, Result.N);
  106. Result.I := 0;
  107. end;
  108. function TPSStackHelper.TArrayEnumerator.HasNext: Boolean;
  109. begin
  110. Result := I < N;
  111. end;
  112. function TPSStackHelper.TArrayEnumerator.Next: String;
  113. begin
  114. Result := VNGetString(PSGetArrayField(Arr, I));
  115. Inc(I);
  116. end;
  117. procedure TPSStackHelper.SetArray(const ItemNo: Longint; const Data: TArray<String>; const FieldNo: Longint);
  118. begin
  119. var N := System.Length(Data);
  120. var Arr := SetArray(ItemNo, FieldNo, N);
  121. for var I := 0 to N-1 do
  122. VNSetString(PSGetArrayField(Arr, I), Data[I]);
  123. end;
  124. procedure TPSStackHelper.SetArray(const ItemNo: Longint; const Data: TStrings; const FieldNo: Longint);
  125. begin
  126. var N := Data.Count;
  127. var Arr := SetArray(ItemNo, FieldNo, N);
  128. for var I := 0 to N-1 do
  129. VNSetString(PSGetArrayField(Arr, I), Data[I]);
  130. end;
  131. procedure TPSStackHelper.SetInt(const ItemNo: Longint; const Data: Integer;
  132. const FieldNo: Longint);
  133. begin
  134. if FieldNo >= 0 then begin
  135. var PSVariantIFC := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo);
  136. VNSetInt(PSVariantIFC, Data);
  137. end else
  138. inherited SetInt(ItemNo, Data)
  139. end;
  140. end.