dynarr.inc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. { decr. ref. count }
  65. { should we remove the array? }
  66. if declocked(realp^.refcount) then
  67. dynarray_clear(realp,ti);
  68. p:=nil;
  69. end;
  70. procedure dynarray_incr_ref(var p : pointer);[Public,Alias:'FPC_DYNARRAY_INCR_REF'];
  71. var
  72. realp : pdynarray;
  73. begin
  74. if p=nil then
  75. exit;
  76. realp:=pdynarray(p-sizeof(tdynarray));
  77. if realp^.refcount=0 then
  78. HandleErrorFrame(204,get_frame);
  79. inclocked(realp^.refcount);
  80. end;
  81. procedure dynarray_setlength(var p : pointer;pti : pdynarraytypeinfo;
  82. dimcount : dword;dims : pdynarrayindex);[Public,Alias:'FPC_DYNARR_SETLENGTH'];
  83. var
  84. i : tdynarrayindex;
  85. size : t_size;
  86. { contains the "fixed" pointers where the refcount }
  87. { and high are at positive offsets }
  88. realp,newp : pdynarray;
  89. ti : pdynarraytypeinfo;
  90. begin
  91. ti:=pti;
  92. { skip kind and name }
  93. inc(pointer(ti),ord(ti^.namelen));
  94. { determine new memory size }
  95. size:=ti^.elesize*dims[0]+sizeof(tdynarray);
  96. { not assigned yet? }
  97. if not(assigned(p)) then
  98. begin
  99. getmem(newp,size);
  100. fillchar(newp^,size,0);
  101. end
  102. else
  103. begin
  104. realp:=pdynarray(p-sizeof(tdynarray));
  105. if dims[0]<0 then
  106. HandleErrorFrame(201,get_frame);
  107. { if the new dimension is 0, we've to release all data }
  108. if dims[0]=0 then
  109. begin
  110. dynarray_clear(realp,pti);
  111. p:=nil;
  112. exit;
  113. end;
  114. if realp^.refcount<>1 then
  115. begin
  116. { make an unique copy }
  117. getmem(newp,size);
  118. move(p^,(pointer(newp)+sizeof(tdynarray))^,ti^.elesize*dims[0]);
  119. { increment ref. count of members }
  120. for i:=0 to dims[0]-1 do
  121. addref(pointer(newp)+sizeof(tdynarray)+ti^.elesize*i,ti^.eletype);
  122. { a declock(ref. count) isn't enough here }
  123. { it could be that the in MT enviroments }
  124. { in the mean time the refcount was }
  125. { decremented }
  126. { it is, because it doesn't really matter }
  127. { if the array is now removed }
  128. dynarray_decr_ref(p,ti);
  129. end
  130. else if dims[0]<>realp^.high+1 then
  131. begin
  132. { range checking is quite difficult ... }
  133. { if size overflows then it is less than }
  134. { the values it was calculated from }
  135. if (size<sizeof(tdynarray)) or
  136. ((ti^.elesize>0) and (size<ti^.elesize)) then
  137. HandleErrorFrame(201,get_frame);
  138. { resize? }
  139. if realp^.refcount=1 then
  140. begin
  141. { shrink the array? }
  142. if dims[0]<realp^.high+1 then
  143. begin
  144. finalizearray(pointer(realp)+sizeof(tdynarray)+ti^.elesize*dims[0],
  145. ti^.eletype,realp^.high-dims[0]+1,ti^.elesize);
  146. reallocmem(realp,size);
  147. end
  148. else if dims[0]>realp^.high+1 then
  149. begin
  150. reallocmem(realp,size);
  151. fillchar((pointer(realp)+sizeof(tdynarray)+ti^.elesize*(realp^.high+1))^,
  152. (dims[0]-realp^.high-1)*ti^.elesize,0);
  153. end;
  154. end;
  155. end
  156. else
  157. newp:=realp;
  158. { handle nested arrays }
  159. if dimcount>1 then
  160. begin
  161. for i:=0 to dims[0]-1 do
  162. dynarray_setlength(pointer(plongint(pointer(newp)+sizeof(tdynarray))[i*ti^.elesize]),
  163. ti^.eletype,dimcount-1,@dims[1]);
  164. end;
  165. end;
  166. p:=pointer(newp)+sizeof(tdynarray);
  167. newp^.refcount:=1;
  168. newp^.high:=dims[0]-1;
  169. end;
  170. function dynarray_copy(var p : pointer;ti : pdynarraytypeinfo;
  171. dimcount : dword;dims : pdynarrayindex) : pointer;[Public,Alias:'FPC_DYNARRAY_COPY'];
  172. begin
  173. {!!!!!!!!!!}
  174. end;
  175. {
  176. $Log$
  177. Revision 1.7 2001-05-27 14:28:44 florian
  178. + made the ref. couting MT safe
  179. Revision 1.6 2001/04/13 23:49:48 peter
  180. * fixes for the stricter compiler
  181. Revision 1.5 2000/12/01 23:30:00 florian
  182. * fixed some bugs in setlength
  183. Revision 1.4 2000/11/12 23:23:34 florian
  184. * interfaces basically running
  185. Revision 1.3 2000/11/07 23:42:21 florian
  186. + AfterConstruction and BeforeDestruction implemented
  187. + TInterfacedObject implemented
  188. Revision 1.2 2000/11/06 21:35:59 peter
  189. * removed some warnings
  190. Revision 1.1 2000/11/04 17:52:46 florian
  191. * fixed linker errors
  192. }