/* * @project: TERA * @version: Development (beta) * @license: MIT (not for evil) * @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com] * Web: https://terafoundation.org * Twitter: https://twitter.com/terafoundation * Telegram: https://t.me/terafoundation */ function Write(buf, data, StringFormat?, ParamValue?, WorkStruct?) { if (buf.len >= buf.length) { return; } if (typeof StringFormat === "number") { global.ToLogTrace("ERRR StringFormat "); throw "ERR!!"; } var format = StringFormat; if (format.substr(0, 6) === "buffer" && format.length > 6) { ParamValue = parseInt(format.substr(6)); format = "buffer"; } else if (format.substr(0, 3) === "arr" && format.length > 3) { ParamValue = parseInt(format.substr(3)); format = "arr"; } else if (format.substr(0, 3) === "str" && format.length > 3) { var length = parseInt(format.substr(3)); if (data) buf.write(data, buf.len, length); buf.len += length; return; } switch (format) { case "str": { var arr = global.toUTF8Array(data); let length = arr.length; if (length > 65535) length = 0; buf[buf.len] = length & 255; buf[buf.len + 1] = (length >>> 8) & 255; buf.len += 2; for (var i = 0; i < length; i++) { buf[buf.len + i] = arr[i]; } buf.len += length; break; } case "byte": { if (data < 0) data = 0; buf[buf.len] = data; buf.len += 1; break; } case "double": { buf.writeDoubleLE(data, buf.len, 8); buf.len += 8; break; } case "uint": { if (data < 0) data = 0; if (data >= 281474976710655) data = 0; buf.writeUIntLE(data, buf.len, 6); buf.len += 6; break; } case "uint16": { if (data < 0) data = 0; buf[buf.len] = data & 255; buf[buf.len + 1] = (data >>> 8) & 255; buf.len += 2; break; } case "uint32": { if (data < 0) data = 0; buf.writeUInt32LE(data, buf.len, 4); buf.len += 4; break; } case "time": { var Time = data.valueOf(); buf.writeUIntLE(Time, buf.len, 6); buf.len += 6; break; } case "addres": case "hash": { let length; if (data) length = Math.min(32, data.length); else length = 0; for (var i = 0; i < length; i++) { buf[buf.len + i] = data[i]; } buf.len += 32; break; } case "buffer": { let length; if (ParamValue === undefined) length = data.length; else length = Math.min(ParamValue, data.length); for (var i = 0; i < length; i++) { buf[buf.len + i] = data[i]; } buf.len += ParamValue; break; } case "arr": { let length; if (data) length = Math.min(ParamValue, data.length); else length = 0; for (var i = 0; i < length; i++) { buf[buf.len + i] = data[i]; } buf.len += ParamValue; break; } case "tr": { let length = data.length; if (global.MAX_TRANSACTION_SIZE > global.MAX_TRANSACTION_SIZE) length = global.MAX_TRANSACTION_SIZE; buf[buf.len] = length & 255; buf[buf.len + 1] = (length >>> 8) & 255; buf.len += 2; for (var i = 0; i < length; i++) { buf[buf.len + i] = data[i]; } buf.len += length; break; } case "data": { let length = data.length; buf.writeUInt32LE(length, buf.len, 4); buf.len += 4; for (var i = 0; i < length; i++) { buf[buf.len + i] = data[i]; } buf.len += length; break; } case "hashSTR": { var Str = global.GetHexFromAddres(data); buf.write(Str, buf.len, 64); buf.len += 64; break; } case "uintSTR": { var Str = data.toString(); buf.write(Str, buf.len, 10); buf.len += 10; break; } default: { WorkStruct = WorkStruct || {}; var CurFormat = StringFormat.substr(0, 1); if (CurFormat === "[") { let length; if (data) length = data.length; var formatNext = GetMiddleString(format); Write(buf, length, "uint32"); for (var i = 0; i < length; i++) { Write(buf, data[i], formatNext, undefined, WorkStruct); } } else if (CurFormat === "<") { let length; if (data) length = data.length; var formatNext = GetMiddleString(format); var IndexCount = 0; var len = buf.len; buf.len += 4; for (var i = 0; i < length; i++) { if (data[i]) { IndexCount++; Write(buf, i, "uint32"); Write(buf, data[i], formatNext, undefined, WorkStruct); } } buf.writeUInt32LE(IndexCount, len, 4); } else if (CurFormat === "{") { var attrs = WorkStruct[format]; if (!attrs) { attrs = GetAttributes(GetMiddleString(format)); WorkStruct[format] = attrs; } for (var i = 0; i < attrs.length; i++) { var type = attrs[i]; Write(buf, data[type.Key], type.Value, undefined, WorkStruct); } } else { throw "Bad write type params: " + format; } } } }; function Read(buf, StringFormat, ParamValue?, WorkStruct?, bDisableTime?) { var ret; if (typeof StringFormat === "number") { global.ToLogTrace("ERR StringFormat"); throw "ERRR!"; } var format = StringFormat; if (format.substr(0, 6) === "buffer") { if (format.length > 6) { ParamValue = parseInt(format.substr(6)); format = "buffer"; } else { ParamValue = 0; } } else if (format.substr(0, 3) === "arr") { if (format.length > 3) { ParamValue = parseInt(format.substr(3)); format = "arr"; } else { ParamValue = 0; } } else if (format.substr(0, 3) === "str") { if (format.length > 3) { var length = parseInt(format.substr(3)); ret = buf.toString('utf8', buf.len, buf.len + length); buf.len += length; var nEnd = - 1; for (var i = ret.length - 1; i >= 0; i--) { if (ret.charCodeAt(i) !== 0) { nEnd = i; break; } } return nEnd >= 0 ? ret.substr(0, i + 1) : ""; } else { ParamValue = 0; } } switch (format) { case "str": { let length; if (buf.len + 2 <= buf.length) length = buf[buf.len] + buf[buf.len + 1] * 256; else length = 0; buf.len += 2; var arr = buf.slice(buf.len, buf.len + length); ret = global.Utf8ArrayToStr(arr); buf.len += length; break; } case "byte": { if (buf.len + 1 <= buf.length) ret = buf[buf.len]; else ret = 0; buf.len += 1; break; } case "double": { if (buf.len + 8 <= buf.length) ret = buf.readDoubleLE(buf.len, 8); else ret = 0; buf.len += 8; break; } case "uint": { if (buf.len + 6 <= buf.length) ret = buf.readUIntLE(buf.len, 6); else ret = 0; buf.len += 6; break; } case "uint16": { if (buf.len + 2 <= buf.length) ret = buf[buf.len] + buf[buf.len + 1] * 256; else ret = 0; buf.len += 2; break; } case "uint32": { if (buf.len + 4 <= buf.length) ret = buf.readUInt32LE(buf.len, 4); else ret = 0; buf.len += 4; break; } case "time": { if (bDisableTime) throw "Bad read type params: time - DisableTime ON"; if (buf.len + 6 <= buf.length) ret = buf.readUIntLE(buf.len, 6); else ret = 0; ret = new Date(ret); buf.len += 6; break; } case "addres": case "hash": { ret = []; for (var i = 0; i < 32; i++) { if (buf.len + i <= buf.length) ret[i] = buf[buf.len + i]; else ret[i] = 0; } buf.len += 32; break; } case "buffer": case "arr": { if (buf.len + ParamValue <= buf.length) ret = buf.slice(buf.len, buf.len + ParamValue); else ret = Buffer.alloc(ParamValue); buf.len += ParamValue; break; } case "tr": { if (buf.len + 1 >= buf.length) { ret = undefined; break; } let length = buf[buf.len] + buf[buf.len + 1] * 256; buf.len += 2; ret = buf.slice(buf.len, buf.len + length); buf.len += length; break; } case "data": { let length; if (buf.len + 4 <= buf.length) length = buf.readUInt32LE(buf.len, 4); else length = 0; if (length > buf.length - buf.len - 4) length = 0; buf.len += 4; ret = buf.slice(buf.len, buf.len + length); buf.len += length; break; } case "hashSTR": { var Str = buf.toString('utf8', buf.len, buf.len + 64); ret = global.GetAddresFromHex(Str); buf.len += 64; break; } case "uintSTR": { var Str = buf.toString('utf8', buf.len, buf.len + 10); ret = parseInt(Str); buf.len += 10; break; } default: { WorkStruct = WorkStruct || {}; var LStr = format.substr(0, 1); if (LStr === "[" || LStr === "<") { var bIndexArr = (LStr === "<"); ret = []; var formatNext = GetMiddleString(format); let length = Read(buf, "uint32"); for (var i = 0; i < length; i++) { if (buf.len > buf.length) { break; } if (bIndexArr) { var index = Read(buf, "uint32"); ret[index] = Read(buf, formatNext, undefined, WorkStruct, bDisableTime); } else { ret[i] = Read(buf, formatNext, undefined, WorkStruct, bDisableTime); } } } else if (LStr === "{") { var attrs = WorkStruct[format]; if (!attrs) { attrs = GetAttributes(GetMiddleString(format)); WorkStruct[format] = attrs; } ret = {}; for (var i = 0; i < attrs.length; i++) { var type = attrs[i]; ret[type.Key] = Read(buf, type.Value, undefined, WorkStruct, bDisableTime); } } else { throw "Bad read type params: " + format; } } } return ret; }; function BufWriteByte(value) { this[this.len] = value; this.len += 1; }; function BufWrite(data, StringFormat, ParamValue) { Write(this, data, StringFormat, ParamValue); }; function BufRead(StringFormat, ParamValue) { return Read(this, StringFormat, ParamValue); }; function GetNewBuffer(size) { var buf = Buffer.alloc(size); buf.Read = BufRead.bind(buf); buf.Write = BufWrite.bind(buf); buf.len = 0; return buf; }; function GetReadBuffer(buffer) { var buf = Buffer.from(buffer); buf.Read = BufRead.bind(buf); buf.Write = BufWrite.bind(buf); buf.len = 0; return buf; }; function GetObjectFromBuffer(buffer, format, WorkStruct, bDisableTime?) { var buf = Buffer.from(buffer); buf.len = 0; return Read(buf, format, undefined, WorkStruct, bDisableTime); }; function GetBufferFromObject(data, format, size, WorkStruct, bNotSlice?) { var buf = Buffer.alloc(size); buf.len = 0; Write(buf, data, format, undefined, WorkStruct); if (!bNotSlice) { buf = buf.slice(0, buf.len); } return buf; }; function GetMiddleString(Str) { return Str.substr(1, Str.length - 2); }; function GetMiddleString2(Str, FromStr, ToStr) { var Count = 0; var Result = ""; for (var i = 0; i < Str.length; i++) { var FStr = Str.substr(i, 1); if (FStr === " " || FStr === "\n") { continue; } if (FStr === FromStr) { Count++; if (Count === 1) continue; } if (FStr === ToStr) { Count--; if (Count === 0) break; } if (Count) Result = Result + FStr; } return Result; }; function GetAttributeStrings(Str) { var Count = 0; var Result = []; var Element = ""; for (var i = 0; i < Str.length; i++) { var FStr = Str.substr(i, 1); if (FStr === "{") { Count++; } else if (FStr === "}") { Count--; } else if (FStr === "," && Count === 0) { if (Element.length > 0) Result.push(Element); Element = ""; continue; } else if (FStr === " " || FStr === "\n") continue; Element = Element + FStr; } if (Element.length > 0) Result.push(Element); return Result; }; function GetKeyValueStrings(Str) { var Key = ""; for (var i = 0; i < Str.length; i++) { var FStr = Str.substr(i, 1); if (FStr === " " || FStr === "\n") { continue; } if (FStr === ":") { var Value = Str.substr(i + 1); return { Key: Key, Value: Value }; } Key = Key + FStr; } throw "Error format Key:Value = " + Str; }; function GetAttributes(Str) { var arr = []; var attrstr = GetAttributeStrings(Str); for (var i = 0; i < attrstr.length; i++) { var type = GetKeyValueStrings(attrstr[i]); arr.push(type); } return arr; }; let alloc = GetNewBuffer; let from = GetReadBuffer; export { GetNewBuffer, GetReadBuffer, alloc, from, Write, Read, GetObjectFromBuffer, GetBufferFromObject, }