2
0

PSStackHelper.pas 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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. TArrayOfObject = array of TObject;
  22. TArrayOfString = array of String;
  23. TArrayBuilder = record
  24. Arr: TPSVariantIFC;
  25. I: Integer;
  26. procedure Add(const Data: String);
  27. end;
  28. TArrayEnumerator = record
  29. Arr: TPSVariantIFC;
  30. N, I: Integer;
  31. function HasNext: Boolean;
  32. function Next: String;
  33. end;
  34. function GetChar(const ItemNo: Longint): Char;
  35. function GetClassArray(const ItemNo: Longint; const FieldNo: Longint = -1): TArrayOfObject;
  36. function GetIntArray(const ItemNo: Longint; const FieldNo: Longint = -1): TArrayOfInteger;
  37. function GetNativeInt(const ItemNo: Longint): NativeInt;
  38. function GetNativeUInt(const ItemNo: Longint): NativeUInt;
  39. function GetProc(const ItemNo: Longint; const Exec: TPSExec): TMethod;
  40. function GetStringArray(const ItemNo: Longint; const FieldNo: Longint = -1): TArrayOfString;
  41. function InitArrayBuilder(const ItemNo: LongInt; const FieldNo: Longint = -1): TArrayBuilder;
  42. function InitArrayEnumerator(const ItemNo: LongInt; const FieldNo: Longint = -1): TArrayEnumerator;
  43. procedure SetArray(const ItemNo: Longint; const Data: TArray<String>; const FieldNo: Longint = -1); overload;
  44. procedure SetArray(const ItemNo: Longint; const Data: TStrings; const FieldNo: Longint = -1); overload;
  45. procedure SetInt(const ItemNo: Longint; const Data: Integer; const FieldNo: Longint = -1);
  46. procedure SetInt64(const ItemNo: Longint; const Data: Int64; const FieldNo: Longint = -1);
  47. procedure SetNativeInt(const ItemNo: Longint; const Data: NativeInt; const FieldNo: Longint = -1);
  48. procedure SetNativeUInt(const ItemNo: Longint; const Data: NativeUInt; const FieldNo: Longint = -1);
  49. procedure SetUInt(const ItemNo: Longint; const Data: Cardinal; const FieldNo: Longint = -1);
  50. procedure SetUInt64(const ItemNo: Longint; const Data: UInt64; const FieldNo: Longint = -1);
  51. end;
  52. implementation
  53. function TPSStackHelper.GetArray(const ItemNo, FieldNo: Longint;
  54. out 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. N := PSDynArrayGetLength(Pointer(Result.Dta^), Result.aType);
  61. end;
  62. function TPSStackHelper.SetArray(const ItemNo, FieldNo: Longint;
  63. const N: Integer): TPSVariantIFC;
  64. begin
  65. if FieldNo >= 0 then
  66. Result := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo)
  67. else
  68. Result := NewTPSVariantIFC(Items[ItemNo], True);
  69. PSDynArraySetLength(Pointer(Result.Dta^), Result.aType, N);
  70. end;
  71. function TPSStackHelper.GetChar(const ItemNo: Longint): Char;
  72. begin
  73. var S := GetString(ItemNo);
  74. if S <> '' then
  75. Result := S[1]
  76. else
  77. Result := #0;
  78. end;
  79. function TPSStackHelper.GetClassArray(const ItemNo, FieldNo: Longint): TArrayOfObject;
  80. begin
  81. var N: Integer;
  82. var Arr := GetArray(ItemNo, FieldNo, N);
  83. SetLength(Result, N);
  84. for var I := 0 to N-1 do
  85. Result[I] := VNGetObject(PSGetArrayField(Arr, I));
  86. end;
  87. function TPSStackHelper.GetIntArray(const ItemNo, FieldNo: Longint): TArrayOfInteger;
  88. begin
  89. var N: Integer;
  90. var Arr := GetArray(ItemNo, FieldNo, N);
  91. SetLength(Result, N);
  92. for var I := 0 to N-1 do
  93. Result[I] := VNGetInt(PSGetArrayField(Arr, I));
  94. end;
  95. function TPSStackHelper.GetNativeInt(const ItemNo: Longint): NativeInt;
  96. begin
  97. {$IFNDEF WIN64}
  98. Result := GetInt(ItemNo);
  99. {$ELSE}
  100. Result := GetInt64(ItemNo);
  101. {$ENDIF}
  102. end;
  103. function TPSStackHelper.GetNativeUInt(const ItemNo: Longint): NativeUInt;
  104. begin
  105. {$IFNDEF WIN64}
  106. Result := GetUInt(ItemNo);
  107. {$ELSE}
  108. Result := GetUInt64(ItemNo);
  109. {$ENDIF}
  110. end;
  111. function TPSStackHelper.GetProc(const ItemNo: Longint; const Exec: TPSExec): TMethod;
  112. begin
  113. var P := PPSVariantProcPtr(Items[ItemNo]);
  114. { ProcNo 0 means nil was passed by the script and GetProcAsMethod will then return a (nil, nil) TMethod }
  115. Result := Exec.GetProcAsMethod(P.ProcNo);
  116. end;
  117. function TPSStackHelper.GetStringArray(const ItemNo, FieldNo: Longint): TArrayOfString;
  118. begin
  119. var N: Integer;
  120. var Arr := GetArray(ItemNo, FieldNo, N);
  121. SetLength(Result, N);
  122. for var I := 0 to N-1 do
  123. Result[I] := VNGetString(PSGetArrayField(Arr, I));
  124. end;
  125. function TPSStackHelper.InitArrayBuilder(const ItemNo, FieldNo: Longint): TArrayBuilder;
  126. begin
  127. Result.Arr := SetArray(ItemNo, FieldNo, 0);
  128. Result.I := 0;
  129. end;
  130. procedure TPSStackHelper.TArrayBuilder.Add(const Data: String);
  131. begin
  132. PSDynArraySetLength(Pointer(Arr.Dta^), Arr.aType, I+1);
  133. VNSetString(PSGetArrayField(Arr, I), Data);
  134. Inc(I);
  135. end;
  136. function TPSStackHelper.InitArrayEnumerator(const ItemNo, FieldNo: Longint): TArrayEnumerator;
  137. begin
  138. Result.Arr := GetArray(ItemNo, FieldNo, Result.N);
  139. Result.I := 0;
  140. end;
  141. function TPSStackHelper.TArrayEnumerator.HasNext: Boolean;
  142. begin
  143. Result := I < N;
  144. end;
  145. function TPSStackHelper.TArrayEnumerator.Next: String;
  146. begin
  147. Result := VNGetString(PSGetArrayField(Arr, I));
  148. Inc(I);
  149. end;
  150. procedure TPSStackHelper.SetArray(const ItemNo: Longint; const Data: TArray<String>; const FieldNo: Longint);
  151. begin
  152. var N := Integer(System.Length(Data));
  153. var Arr := SetArray(ItemNo, FieldNo, N);
  154. for var I := 0 to N-1 do
  155. VNSetString(PSGetArrayField(Arr, I), Data[I]);
  156. end;
  157. procedure TPSStackHelper.SetArray(const ItemNo: Longint; const Data: TStrings; const FieldNo: Longint);
  158. begin
  159. var N := Data.Count;
  160. var Arr := SetArray(ItemNo, FieldNo, N);
  161. for var I := 0 to N-1 do
  162. VNSetString(PSGetArrayField(Arr, I), Data[I]);
  163. end;
  164. procedure TPSStackHelper.SetInt(const ItemNo: Longint; const Data: Integer;
  165. const FieldNo: Longint);
  166. begin
  167. if FieldNo >= 0 then begin
  168. var PSVariantIFC := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo);
  169. VNSetInt(PSVariantIFC, Data);
  170. end else
  171. inherited SetInt(ItemNo, Data)
  172. end;
  173. procedure TPSStackHelper.SetUInt(const ItemNo: Longint; const Data: Cardinal;
  174. const FieldNo: Longint);
  175. begin
  176. if FieldNo >= 0 then begin
  177. var PSVariantIFC := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo);
  178. VNSetUInt(PSVariantIFC, Data);
  179. end else
  180. inherited SetUInt(ItemNo, Data)
  181. end;
  182. procedure TPSStackHelper.SetInt64(const ItemNo: Longint; const Data: Int64;
  183. const FieldNo: Longint);
  184. begin
  185. if FieldNo >= 0 then begin
  186. var PSVariantIFC := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo);
  187. VNSetInt64(PSVariantIFC, Data);
  188. end else
  189. inherited SetInt64(ItemNo, Data)
  190. end;
  191. procedure TPSStackHelper.SetUInt64(const ItemNo: Longint; const Data: UInt64;
  192. const FieldNo: Longint);
  193. begin
  194. if FieldNo >= 0 then begin
  195. var PSVariantIFC := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo);
  196. VNSetUInt64(PSVariantIFC, Data);
  197. end else
  198. inherited SetUInt64(ItemNo, Data)
  199. end;
  200. procedure TPSStackHelper.SetNativeInt(const ItemNo: Longint; const Data: NativeInt;
  201. const FieldNo: Longint);
  202. begin
  203. {$IFNDEF WIN64}
  204. SetInt(ItemNo, Data, FieldNo);
  205. {$ELSE}
  206. SetInt64(ItemNo, Data, FieldNo);
  207. {$ENDIF}
  208. end;
  209. procedure TPSStackHelper.SetNativeUInt(const ItemNo: Longint; const Data: NativeUInt;
  210. const FieldNo: Longint);
  211. begin
  212. {$IFNDEF WIN64}
  213. SetUInt(ItemNo, Data, FieldNo);
  214. {$ELSE}
  215. SetUInt64(ItemNo, Data, FieldNo);
  216. {$ENDIF}
  217. end;
  218. end.