unit SyNodeReadWrite; interface uses SpiderMonkey, Classes, SynCommons; // TODO - replace this implemenattion by buffers whed buffers become fully compartible with nodeJS /// Used for create JS method for writing data to internal class buffer // JS syntax: write(data: ArrayBuffer|String|Object, [encoding: "utf-8"|"ucs2"|"bin"|"base64"]' // inmplementation must provide TTextWriter to write data to function SMWrite_impl(cx: PJSContext; argc: uintN; vals: PjsvalVector; dest: TTextWriter): jsval; cdecl; /// Used for create JS method for reading data from internal class buffer (aStr) // JS syntax: read([encoding=utf-8: "utf-8"|"ucs2"|"bin"|"base64"]) // implementation must provide TTextWriter to write data to function SMRead_impl(cx: PJSContext; argc: uintN; vals: PjsvalVector; const aStr: RawByteString): jsval; cdecl; implementation {$ifdef MSWINDOWS} uses Windows; // CP_UTF8 {$endif} function SMRead_impl(cx: PJSContext; argc: uintN; vals: PjsvalVector; const aStr: RawByteString): jsval; cdecl; var encoding: RawUTF8; len: Integer; bufObj: PJSObject; bufData: pointer; decodedStr: RawByteString; begin if (argc = 0) or ((argc=1) and vals[0].isVoid) then encoding := 'utf-8' else encoding := LowerCase(vals[0].asJSString.ToUTF8(cx)); if encoding = 'utf-8' then begin Result := cx.NewJSString(Pointer(aStr), length(aStr), CP_UTF8).ToJSVal end else if encoding = 'Windows-1251' then begin Result := cx.NewJSString(Pointer(aStr), length(aStr), 1251).ToJSVal end else if encoding = 'ucs2' then begin Result := cx.NewJSString(aStr).ToJSVal end else if encoding = 'bin2base64' then begin decodedStr := BinToBase64(aStr); Result := cx.NewJSString(decodedStr).ToJSVal; end else if (encoding = 'bin') or (encoding = 'base64') then begin if encoding = 'base64' then decodedStr := Base64ToBin(aStr) else decodedStr := aStr; len := length(decodedStr); bufObj := cx.NewArrayBuffer(len); bufData := bufObj.GetArrayBufferData; Move(pointer(decodedStr)^, bufData^, len); Result := bufObj.ToJSValue; end else raise ESMException.Create('Invalid encoding'); end; function SMWrite_impl(cx: PJSContext; argc: uintN; vals: PjsvalVector; dest: TTextWriter): jsval; cdecl; var encoding: RawUTF8; len: uint32; isShared: boolean; bufObj: PJSObject; bufData: Puint8Vector; tmp1: RawByteString; tmp2: SynUnicode; begin if (argc < 1) or (argc>2) then raise ESMException.Create('Usage: write(data: ArrayBuffer|String|Object, [encoding: "utf-8"|"ucs2"|"bin"|"base64"]'); encoding := ''; if argc=2 then begin if (argc = 2) and (vals[1].isString) then encoding := LowerCase(vals[1].asJSString.ToUTF8(cx)); end; case cx.TypeOfValue(vals[0]) of JSTYPE_STRING: begin if (encoding = '') or (encoding = 'utf-8') or (encoding = 'utf8') then // default is utf-8 vals[0].asJSString.ToUTF8(cx, dest) else if (encoding = 'ucs2') then begin tmp2 := vals[0].asJSString.ToSynUnicode(cx); dest.AddNoJSONEscapeW(pointer(tmp2), length(tmp2)); end else raise ESMException.Create('invalid encoding'); end; JSTYPE_NUMBER: if vals[0].isInteger then dest.Add(vals[0].asInteger) else dest.AddDouble(vals[0].asDouble); JSTYPE_OBJECT: begin bufObj := vals[0].asObject; if bufObj=nil then begin Result.asBoolean := true; Exit; end; if bufObj.GetBufferDataAndLength(bufData, len) then begin if encoding = 'base64' then begin tmp1 := BinToBase64(PAnsiChar(bufData), len); bufData := Puint8Vector(tmp1); len := Length(tmp1); encoding := 'bin'; end; if (encoding = '') or (encoding = 'bin') then begin // default is bin if len>0 then dest.AddNoJSONEscape(pointer(bufData), len) end else raise ESMException.Create('invalid encoding'); end else begin if (encoding = '') or (encoding = 'utf-8') or (encoding = 'utf8') then // default is utf-8 vals[0].AddJSON(cx, dest) else raise ESMException.Create('invalid encoding'); end; end; JSTYPE_VOID: begin end; // do nothing else raise ESMException.Create('invalid parameter type for Writer'); end; result.asBoolean := True; end; end.