dynarr.inc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2000 by Florian Klaempfl
  5. member of the Free Pascal development team.
  6. This file implements the helper routines for dyn. Arrays in FPC
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************
  13. }
  14. procedure FinalizeArray(data,typeinfo : pointer;count,size : longint);forward;
  15. Procedure Addref (Data,TypeInfo : Pointer);forward;
  16. Procedure int_finalize (Data,TypeInfo: Pointer);forward;
  17. type
  18. tdynarrayindex = longint;
  19. pdynarrayindex = ^tdynarrayindex;
  20. t_size = dword;
  21. { don't add new fields, the size is used }
  22. { to calculate memory requirements }
  23. pdynarray = ^tdynarray;
  24. tdynarray = packed record
  25. refcount : longint;
  26. high : tdynarrayindex;
  27. end;
  28. pdynarraytypeinfo = ^tdynarraytypeinfo;
  29. tdynarraytypeinfo = packed record
  30. kind : byte;
  31. namelen : byte;
  32. { here the chars follow, we've to skip them }
  33. elesize : t_size;
  34. eletype : pdynarraytypeinfo;
  35. end;
  36. function dynarray_length(p : pointer) : tdynarrayindex;[Public,Alias:'FPC_DYNARRAY_LENGTH'];
  37. begin
  38. dynarray_length:=pdynarray(p-sizeof(tdynarray))^.high+1;
  39. end;
  40. function dynarray_high(p : pointer) : tdynarrayindex;[Public,Alias:'FPC_DYNARRAY_HIGH'];
  41. begin
  42. dynarray_high:=pdynarray(p-sizeof(tdynarray))^.high;
  43. end;
  44. { releases and finalizes the data of a dyn. array and sets p to nil }
  45. procedure dynarray_clear(var p : pdynarray;ti : pdynarraytypeinfo);
  46. begin
  47. { skip kind and name }
  48. inc(pointer(ti),ord(ti^.namelen));
  49. { finalize all data }
  50. finalizearray(p,ti^.eletype,p^.high+1,ti^.elesize);
  51. { release the data }
  52. freemem(p,sizeof(tdynarray)+(p^.high+1)*ti^.elesize);
  53. p:=nil;
  54. end;
  55. procedure dynarray_decr_ref(var p : pointer;ti : pdynarraytypeinfo);[Public,Alias:'FPC_DYNARRAY_DECR_REF'];
  56. var
  57. realp : pdynarray;
  58. begin
  59. if p=nil then
  60. exit;
  61. realp:=pdynarray(p-sizeof(tdynarray));
  62. if realp^.refcount=0 then
  63. HandleErrorFrame(204,get_frame);
  64. { this isn't MT safe! }
  65. { decr. ref. count }
  66. declocked(realp^.refcount);
  67. { should we remove the array? }
  68. if realp^.refcount=0 then
  69. dynarray_clear(realp,ti);
  70. p:=nil;
  71. end;
  72. procedure dynarray_setlength(var p : pointer;pti : pdynarraytypeinfo;
  73. dimcount : dword;dims : pdynarrayindex);[Public,Alias:'FPC_DYNARR_SETLENGTH'];
  74. var
  75. i : tdynarrayindex;
  76. size : t_size;
  77. { contains the "fixed" pointers where the refcount }
  78. { and high are at positive offsets }
  79. realp,newp : pdynarray;
  80. ti : pdynarraytypeinfo;
  81. begin
  82. ti:=pti;
  83. { skip kind and name }
  84. inc(pointer(ti),ord(ti^.namelen));
  85. { determine new memory size }
  86. size:=ti^.elesize*dims[0]+sizeof(tdynarray);
  87. { not assigned yet? }
  88. if not(assigned(p)) then
  89. begin
  90. getmem(newp,size);
  91. fillchar(newp^,size,0);
  92. end
  93. else
  94. begin
  95. realp:=pdynarray(p-sizeof(tdynarray));
  96. if dims[0]<0 then
  97. HandleErrorFrame(201,get_frame);
  98. { if the new dimension is 0, we've to release all data }
  99. if dims[0]=0 then
  100. begin
  101. dynarray_clear(realp,pti);
  102. p:=nil;
  103. exit;
  104. end;
  105. if realp^.refcount<>1 then
  106. begin
  107. { make an unique copy }
  108. getmem(newp,size);
  109. move(p^,(pointer(newp)+sizeof(tdynarray))^,ti^.elesize*dims[0]);
  110. { increment ref. count of members }
  111. for i:=0 to dims[0]-1 do
  112. addref(pointer(newp)+sizeof(tdynarray)+ti^.elesize*i,ti^.eletype);
  113. { a declock(ref. count) isn't enough here }
  114. { it could be that the in MT enviroments }
  115. { in the mean time the refcount was }
  116. { decremented }
  117. dynarray_decr_ref(p,ti);
  118. end
  119. else if dims[0]<>realp^.high+1 then
  120. begin
  121. { range checking is quite difficult ... }
  122. { if size overflows then it is less than }
  123. { the values it was calculated from }
  124. if (size<sizeof(tdynarray)) or
  125. ((ti^.elesize>0) and (size<ti^.elesize)) then
  126. HandleErrorFrame(201,get_frame);
  127. { resize? }
  128. if realp^.refcount=1 then
  129. begin
  130. { shrink the array? }
  131. if dims[0]<realp^.high+1 then
  132. begin
  133. finalizearray(pointer(realp)+sizeof(tdynarray)+ti^.elesize*dims[0],
  134. ti^.eletype,realp^.high-dims[0]+1,ti^.elesize);
  135. reallocmem(realp,size);
  136. end
  137. else if dims[0]>realp^.high+1 then
  138. begin
  139. reallocmem(realp,size);
  140. fillchar((pointer(realp)+sizeof(tdynarray)+ti^.elesize*(realp^.high+1))^,
  141. (dims[0]-realp^.high-1)*ti^.elesize,0);
  142. end;
  143. end;
  144. end
  145. else
  146. newp:=realp;
  147. { handle nested arrays }
  148. if dimcount>1 then
  149. begin
  150. for i:=0 to dims[0]-1 do
  151. dynarray_setlength(pointer(plongint(pointer(newp)+sizeof(tdynarray))[i*ti^.elesize]),
  152. ti^.eletype,dimcount-1,@dims[1]);
  153. end;
  154. end;
  155. p:=pointer(newp)+sizeof(tdynarray);
  156. newp^.refcount:=1;
  157. newp^.high:=dims[0]-1;
  158. end;
  159. function dynarray_copy(var p : pointer;ti : pdynarraytypeinfo;
  160. dimcount : dword;dims : pdynarrayindex) : pointer;[Public,Alias:'FPC_DYNARRAY_COPY'];
  161. begin
  162. {!!!!!!!!!!}
  163. end;
  164. {
  165. $Log$
  166. Revision 1.6 2001-04-13 23:49:48 peter
  167. * fixes for the stricter compiler
  168. Revision 1.5 2000/12/01 23:30:00 florian
  169. * fixed some bugs in setlength
  170. Revision 1.4 2000/11/12 23:23:34 florian
  171. * interfaces basically running
  172. Revision 1.3 2000/11/07 23:42:21 florian
  173. + AfterConstruction and BeforeDestruction implemented
  174. + TInterfacedObject implemented
  175. Revision 1.2 2000/11/06 21:35:59 peter
  176. * removed some warnings
  177. Revision 1.1 2000/11/04 17:52:46 florian
  178. * fixed linker errors
  179. }