mod_stream.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. unit mod_stream;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, libsee;
  6. Procedure RegisterStreamModule;
  7. Procedure RegisterWriteModule;
  8. implementation
  9. { ---------------------------------------------------------------------
  10. General auxiliary functions
  11. ---------------------------------------------------------------------}
  12. Function ValueToString(V : TSee_Value) : AnsiString;
  13. Var
  14. PS : Ptcuint;
  15. PD : PAnsiChar;
  16. I : Integer;
  17. begin
  18. SetLength(Result,v.u._string^.length);
  19. If Length(Result)<>0 then
  20. begin
  21. PD:=PAnsiChar(Result);
  22. PS:=v.u._string^.data;
  23. For I:=0 to length(Result)-1 do
  24. begin
  25. PD^:=AnsiChar(PS^ and $ff);
  26. Inc(PD);
  27. Inc(PS);
  28. end;
  29. end;
  30. end;
  31. Procedure CreateJSObject(Interp : PSEE_Interpreter; Parent : PSEE_Object;AName : PSEE_String; Obj : PSee_Object);
  32. var
  33. V : PSEE_Value;
  34. begin
  35. v:=new_see_value;
  36. see_set_object(V,Obj);
  37. see_object_put(interp,parent,AName,V,SEE_ATTR_DEFAULT);
  38. end;
  39. Procedure CreateJSNumber(Interp : PSEE_Interpreter; Obj : PSee_Object; AName : PSEE_String; AValue : TSEE_number_t);
  40. var
  41. V : PSEE_Value;
  42. begin
  43. v:=new_SEE_value;
  44. see_set_number(V,AValue);
  45. see_object_put(Interp,Obj,AName,v,SEE_ATTR_DEFAULT);
  46. end;
  47. Procedure CreateJSFunction(Interp : PSEE_Interpreter; Obj : PSee_Object; Func : TSEE_call_fn_t; AName : PSEE_String; Len : Integer);
  48. var
  49. V : PSEE_Value;
  50. begin
  51. v:=new_SEE_value;
  52. see_set_object(V,see_cfunction_make(interp,Func,AName,len));
  53. see_object_put(Interp,Obj,AName,v,SEE_ATTR_DEFAULT);
  54. end;
  55. { ---------------------------------------------------------------------
  56. Stream module support
  57. ---------------------------------------------------------------------}
  58. Var
  59. StreamModule : TSEE_module;
  60. StreamObjectDef,
  61. StreamPrototypeDef : PSEE_objectclass;
  62. WriteModule : TSEE_module;
  63. Type
  64. TStreamModuleData = record
  65. Stream : PSEE_object;
  66. Prototype : PSEE_object;
  67. Error : PSEE_object;
  68. end;
  69. PStreamModuleData = ^TStreamModuleData;
  70. TStreamObject = record
  71. native : TSEE_native;
  72. Stream : TStream;
  73. end;
  74. PSTreamObject = ^TStreamObject;
  75. Var
  76. GStreamRead,
  77. GStreamWrite,
  78. GStreamSeek,
  79. GStreamSize,
  80. GStreamPosition,
  81. GStreamFree,
  82. GStreamfmCreate,
  83. GStreamfmOpenRead,
  84. GStreamfmOpenWrite,
  85. GStreamfmOpenReadWrite,
  86. GStreamStream,
  87. GStreamError,
  88. GStreamPrototype : PSEE_String;
  89. Procedure StreamAlloc(Interp : PSEE_Interpreter); cdecl;
  90. begin
  91. PPointer(see_module_private(Interp,@StreamModule))^:=new(PStreamModuleData);
  92. end;
  93. Function PrivateData(Interp : PSEE_Interpreter) : PStreamModuleData;
  94. begin
  95. Result:=PStreamModuleData((see_module_private(Interp,@StreamModule))^)
  96. end;
  97. Function AsFile(i:PTSEE_interpreter; obj:PTSEE_object) : PStreamObject;
  98. begin
  99. If (Not Assigned(obj)) or (Obj^.objectclass<>StreamPrototypeDef) then
  100. SEE_error__throw0(i,I^.TypeError,Nil);
  101. Result:=PStreamObject(Obj)
  102. end;
  103. procedure StreamSize (i:PTSEE_interpreter; obj:PTSEE_object; thisobj:PTSEE_object; argc:Tcint; argv:PPTSEE_value;
  104. res:PTSEE_value);cdecl;
  105. Var
  106. S : PStreamObject;
  107. begin
  108. S:=AsFile(I,ThisObj);
  109. If (S^.Stream=Nil) then
  110. SEE_error__throw0(i,PrivateData(I)^.Error,Nil);
  111. SEE_SET_NUMBER(res,S^.Stream.Size);
  112. end;
  113. procedure StreamWrite (i:PTSEE_interpreter; obj:PTSEE_object; thisobj:PTSEE_object; argc:Tcint; argv:PPTSEE_value;
  114. res:PTSEE_value);cdecl;
  115. Var
  116. S : PStreamObject;
  117. v : TSEE_Value;
  118. t : AnsiString;
  119. begin
  120. S:=AsFile(I,ThisObj);
  121. If (S^.Stream=Nil) then
  122. SEE_error__throw0(i,PrivateData(I)^.Error,'File is closed');
  123. if (ArgC=0) then
  124. SEE_error__throw0(i,I^.RangeError,'Missing argument');
  125. SEE_ToString(i,argv[0], @v);
  126. T:=ValueToString(V);
  127. If Length(T)>0 then
  128. S^.Stream.Write(T[1],Length(T));
  129. end;
  130. procedure StreamPosition (i:PTSEE_interpreter; obj:PTSEE_object; thisobj:PTSEE_object; argc:Tcint; argv:PPTSEE_value;
  131. res:PTSEE_value);cdecl;
  132. Var
  133. S : PStreamObject;
  134. v : TSEE_Value;
  135. t : AnsiString;
  136. begin
  137. S:=AsFile(I,ThisObj);
  138. If (S^.Stream=Nil) then
  139. SEE_error__throw0(i,PrivateData(I)^.Error,'File is closed');
  140. SEE_SET_NUMBER(res,S^.Stream.Position);
  141. end;
  142. procedure StreamSeek (i:PTSEE_interpreter; obj:PTSEE_object; thisobj:PTSEE_object; argc:Tcint; argv:PPTSEE_value;
  143. res:PTSEE_value);cdecl;
  144. Var
  145. S : PStreamObject;
  146. v : TSEE_Value;
  147. newpos : integer;
  148. begin
  149. S:=AsFile(I,ThisObj);
  150. If (S^.Stream=Nil) then
  151. SEE_error__throw0(i,PrivateData(I)^.Error,'File is closed');
  152. if (ArgC=0) then
  153. SEE_error__throw0(i,I^.RangeError,'Missing argument');
  154. newpos:=SEE_ToUint32(i,argv[0]);
  155. SEE_SET_NUMBER(res,S^.Stream.Seek(soFromBeginning,newpos));
  156. end;
  157. procedure StreamRead (i:PTSEE_interpreter; obj:PTSEE_object; thisobj:PTSEE_object; argc:Tcint; argv:PPTSEE_value;
  158. res:PTSEE_value);cdecl;
  159. Var
  160. S : PStreamObject;
  161. r : PSEE_String;
  162. j,maxlen : integer;
  163. c : AnsiChar;
  164. begin
  165. S:=AsFile(I,ThisObj);
  166. If (S^.Stream=Nil) then
  167. SEE_error__throw0(i,PrivateData(I)^.Error,'File is closed');
  168. if (ArgC=0) then
  169. maxlen:=1024
  170. else
  171. maxlen:=see_touint32(I,argv[0]);
  172. r:=see_string_new(I,maxlen);
  173. For j:=0 to maxLen-1 do
  174. begin
  175. S^.stream.Read(c,sizeOf(c));
  176. SEE_string_addch(R,ord(c));
  177. end;
  178. SEE_SET_STRING(Res,r);
  179. end;
  180. procedure StreamFree (i:PTSEE_interpreter; obj:PTSEE_object; thisobj:PTSEE_object; argc:Tcint; argv:PPTSEE_value;
  181. res:PTSEE_value);cdecl;
  182. Var
  183. S : PStreamObject;
  184. v : TSEE_Value;
  185. t : AnsiString;
  186. begin
  187. S:=AsFile(I,ThisObj);
  188. If (S^.Stream=Nil) then
  189. SEE_error__throw0(i,PrivateData(I)^.Error,'File is closed');
  190. FreeAndNil(S^.Stream);
  191. SEE_SET_UNDEFINED(Res);
  192. end;
  193. procedure StreamFinalize ( i:PTSEE_interpreter; p:pointer; closure:pointer);cdecl;
  194. begin
  195. FreeAndNil(PStreamObject(P)^.Stream);
  196. end;
  197. procedure StreamConstruct (i:PTSEE_interpreter; obj:PTSEE_object; thisobj:PTSEE_object; argc:Tcint; argv:PPTSEE_value;
  198. res:PTSEE_value);cdecl;
  199. Var
  200. P : PAnsiChar;
  201. fm : Integer;
  202. S : TStream;
  203. Err : AnsiString;
  204. R : PTSEE_Object;
  205. begin
  206. SEE_parse_args(i,argc,argv,'Z|i',@p,@fm);
  207. If (P=Nil) then
  208. SEE_error__throw0(i,I^.RangeError,'Missing argument');
  209. Err:='';
  210. try
  211. S:=TFileStream.Create(strpas(p),fm);
  212. except
  213. On E : Exception do
  214. Err:=E.Message;
  215. end;
  216. If (Err<>'') then
  217. SEE_error__throw0(i,PrivateData(I)^.Error,PAnsiChar(Err));
  218. R:=PTSEE_Object(SEE_malloc_finalize(I,SizeOf(TStreamObject),@StreamFinalize,Nil));
  219. SEE_Native_init(PSEE_Native(R),I,StreamPrototypeDef,PrivateData(I)^.Prototype);
  220. PStreamObject(r)^.Stream:=S;
  221. SEE_SET_OBJECT(Res,R);
  222. end;
  223. Procedure StreamInit(Interp : PSEE_Interpreter); cdecl;
  224. Var
  225. Stream,
  226. StreamPrototype,
  227. StreamError : PSee_object;
  228. begin
  229. // writeln('Initializing stream');
  230. // Construct Stream.prototype object
  231. // writeln('Creating Stream Prototype ');
  232. StreamPrototype:=PSEE_object(SEE_malloc(Interp,SizeOf(TSTreamObject)));
  233. See_native_init(PSEE_native(StreamProtoType),Interp,StreamPrototypeDef,interp^.Object_prototype);
  234. PSTreamObject(StreamPrototype)^.stream:=Nil;
  235. createJSFUnction(Interp,StreamPrototype,@StreamRead,GStreamRead,0);
  236. createJSFUnction(Interp,StreamPrototype,@StreamWrite,GStreamWrite,0);
  237. createJSFUnction(Interp,StreamPrototype,@StreamSize,GStreamSize,0);
  238. createJSFUnction(Interp,StreamPrototype,@StreamPosition,GStreamPosition,0);
  239. createJSFUnction(Interp,StreamPrototype,@StreamSeek,GStreamSeek,0);
  240. createJSFUnction(Interp,StreamPrototype,@StreamFree,GStreamFree,0);
  241. // writeln('Creating Stream');
  242. // Construct Stream object
  243. Stream:=PSEE_object(new_see_native);
  244. See_native_init(PSEE_native(Stream),Interp,StreamObjectDef,interp^.Object_prototype);
  245. CreateJSObject(Interp,Interp^.Global,GStreamStream,Stream);
  246. CreateJSObject(Interp,Stream,GStreamprototype,StreamPrototype);
  247. CreateJSNumber(Interp,Stream,GStreamfmCreate,fmCreate);
  248. CreateJSNumber(Interp,Stream,GStreamfmOpenRead,fmOpenRead);
  249. CreateJSNumber(Interp,Stream,GStreamfmOpenWrite,fmOpenWrite);
  250. CreateJSNumber(Interp,Stream,GStreamfmOpenReadWrite,fmOpenReadWrite);
  251. StreamError:=SEE_Error_make(interp, GSTreamError);
  252. PrivateData(Interp)^.Stream:=STream;
  253. PrivateData(Interp)^.Prototype:=StreamPrototype;
  254. PrivateData(Interp)^.Error:=StreamError;
  255. // writeln('Done initializing stream');
  256. end;
  257. Procedure AllocateStreamStrings;
  258. begin
  259. GStreamRead:=SEE_intern_global('Read');
  260. GStreamWrite:=SEE_intern_global('Write');
  261. GStreamSeek:=SEE_intern_global('Seek');
  262. GStreamSize:=SEE_intern_global('Size');
  263. GStreamPosition:=SEE_intern_global('Position');
  264. GStreamFree:=SEE_intern_global('Free');
  265. GStreamfmCreate:=SEE_intern_global('fmCreate');
  266. GStreamfmOpenRead:=SEE_intern_global('fmOpenRead');
  267. GStreamfmOpenWrite:=SEE_intern_global('fmOpenWrite');
  268. GStreamfmOpenReadWrite:=SEE_intern_global('fmOpenReadWrite');
  269. GStreamStream:=SEE_intern_global('Stream');
  270. GStreamError:=SEE_intern_global('Error');
  271. GStreamPrototype:=SEE_intern_global('prototype');
  272. end;
  273. Function StreamInitModule : Integer; cdecl;
  274. begin
  275. // writeln('Initializing module');
  276. StreamPrototypeDef:=new_SEE_objectclass;
  277. With StreamPrototypeDef^ do
  278. begin
  279. _Class:='Stream';
  280. get:=SEE_native_get;
  281. put:=SEE_native_put;
  282. canput:=SEE_native_canput;
  283. hasproperty:=SEE_native_hasproperty;
  284. Delete:=SEE_native_delete;
  285. DefaultValue:=SEE_native_defaultvalue;
  286. ENumerator:=SEE_native_enumerator;
  287. Construct:=Nil;
  288. Call:=Nil;
  289. HasInstance:=Nil;
  290. end;
  291. StreamObjectDef:=new_SEE_objectclass;
  292. With StreamObjectDef^ do
  293. begin
  294. _Class:='Stream';
  295. get:=SEE_native_get;
  296. put:=SEE_native_put;
  297. get:=SEE_native_get;
  298. put:=SEE_native_put;
  299. canput:=SEE_native_canput;
  300. hasproperty:=SEE_native_hasproperty;
  301. Delete:=SEE_native_delete;
  302. DefaultValue:=SEE_native_defaultvalue;
  303. ENumerator:=SEE_native_enumerator;
  304. Construct:=@StreamConstruct;
  305. Call:=Nil;
  306. HasInstance:=Nil;
  307. end;
  308. AllocateStreamStrings;
  309. // writeln('Done Initializing module');
  310. Result:=0;
  311. end;
  312. Procedure RegisterStreamModule;
  313. begin
  314. // writeln('Registering stream module');
  315. // StreamModule:=new_SEE_module;
  316. With StreamModule do
  317. begin
  318. magic:=SEE_MODULE_MAGIC;
  319. name:='Stream';
  320. version:='1.0';
  321. Index:=0;
  322. Mod_init:=@StreamInitModule;
  323. alloc:=@StreamAlloc;
  324. init:=@StreamInit
  325. end;
  326. SEE_module_add(@StreamModule);
  327. end;
  328. { ---------------------------------------------------------------------
  329. Write(ln) module support
  330. ---------------------------------------------------------------------}
  331. procedure WriteWrite (i:PTSEE_interpreter; obj:PTSEE_object; thisobj:PTSEE_object; argc:Tcint; argv:PPTSEE_value;
  332. res:PTSEE_value);cdecl;
  333. Var
  334. a,C : Integer;
  335. t : AnsiString;
  336. v : TSEE_Value;
  337. begin
  338. if (ArgC=0) then
  339. SEE_error__throw0(i,I^.RangeError,'Missing argument');
  340. C:=0;
  341. For A:=0 to Argc-1 do
  342. begin
  343. SEE_ToString(i,argv[a], @v);
  344. T:=ValueToString(V);
  345. If Length(T)>0 then
  346. begin
  347. Write(T);
  348. C:=C+Length(T);
  349. end;
  350. end;
  351. SEE_SET_NUMBER(Res,C);
  352. end;
  353. procedure WriteWriteln (i:PTSEE_interpreter; obj:PTSEE_object; thisobj:PTSEE_object; argc:Tcint; argv:PPTSEE_value;
  354. res:PTSEE_value);cdecl;
  355. begin
  356. if (Argc>0) then
  357. WriteWrite(i,obj,thisobj,argc,argv,res)
  358. else
  359. SEE_SET_NUMBER(Res,0);
  360. Writeln;
  361. end;
  362. Var
  363. GWriteWrite : PSEE_STRING;
  364. GWriteWriteln : PSEE_STRING;
  365. Procedure WriteInit(Interp : PSEE_Interpreter); cdecl;
  366. begin
  367. // writeln('Initializing write');
  368. createJSFUnction(Interp,Interp^.Global,@WriteWrite,GWriteWrite,1);
  369. createJSFUnction(Interp,Interp^.Global,@WriteWriteln,GWriteWriteln,1);
  370. // writeln('Done initializing write');
  371. end;
  372. Procedure AllocateWriteStrings;
  373. begin
  374. GWriteWrite:=SEE_intern_global('write');
  375. GWriteWriteln:=SEE_intern_global('writeln');
  376. end;
  377. Function WriteInitModule : Integer; cdecl;
  378. begin
  379. Result:=0;
  380. end;
  381. Procedure RegisterWriteModule;
  382. begin
  383. // writeln('Registering write module');
  384. // StreamModule:=new_SEE_module;
  385. With WriteModule do
  386. begin
  387. magic:=SEE_MODULE_MAGIC;
  388. name:='Write';
  389. version:='1.0';
  390. Index:=0;
  391. Mod_init:=@WriteInitModule;
  392. alloc:=Nil;
  393. init:=@WriteInit
  394. end;
  395. AllocateWriteStrings;
  396. SEE_module_add(@WriteModule);
  397. end;
  398. end.