X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fshared%2Futils.pas;h=59a49f251dbb3b927cfea195b442f38ab3656ae8;hb=94de7eeb85f9ccafbb301c063de3d2b820af193b;hp=f61035e5c4ac6a6fbf736df86b64e53901c4550e;hpb=a4f25c41dfd783a925aa2dab4b9b84753d5c3f18;p=d2df-sdl.git diff --git a/src/shared/utils.pas b/src/shared/utils.pas index f61035e..59a49f2 100644 --- a/src/shared/utils.pas +++ b/src/shared/utils.pas @@ -22,6 +22,11 @@ uses SysUtils, Classes; +// ////////////////////////////////////////////////////////////////////////// // +type + SSArray = array of ShortString; + + // ////////////////////////////////////////////////////////////////////////// // type TUtf8DecoderFast = packed record @@ -76,15 +81,15 @@ function isWadPath (const fn: AnsiString): Boolean; function addWadExtension (const fn: AnsiString): AnsiString; // convert number to strig with nice commas -function Int64ToStrComma (i: Int64): AnsiString; +function int64ToStrComma (i: Int64): AnsiString; -function UpCase1251 (ch: Char): Char; -function LoCase1251 (ch: Char): Char; +function upcase1251 (ch: AnsiChar): AnsiChar; inline; +function locase1251 (ch: AnsiChar): AnsiChar; inline; function toLowerCase1251 (const s: AnsiString): AnsiString; // `true` if strings are equal; ignoring case for cp1251 -function StrEquCI1251 (const s0, s1: AnsiString): Boolean; +function strEquCI1251 (const s0, s1: AnsiString): Boolean; function utf8Valid (const s: AnsiString): Boolean; @@ -100,6 +105,15 @@ function openDiskFileRO (pathname: AnsiString): TStream; function createDiskFile (pathname: AnsiString): TStream; // little endian +procedure writeSign (st: TStream; const sign: AnsiString); +function checkSign (st: TStream; const sign: AnsiString): Boolean; + +procedure writeBool (st: TStream; b: Boolean); +function readBool (st: TStream): Boolean; + +procedure writeStr (st: TStream; const str: AnsiString; maxlen: LongWord=65535); +function readStr (st: TStream; maxlen: LongWord=65535): AnsiString; + procedure writeInt (st: TStream; v: Byte); overload; procedure writeInt (st: TStream; v: ShortInt); overload; procedure writeInt (st: TStream; v: Word); overload; @@ -179,7 +193,7 @@ type TFormatStrFCallback = procedure (constref buf; len: SizeUInt); // returns formatted string if `writerCB` is `nil`, empty string otherwise -function formatstrf (const fmt: AnsiString; args: array of const; writerCB: TFormatStrFCallback=nil): AnsiString; +function formatstrf (const fmt: AnsiString; const args: array of const; writerCB: TFormatStrFCallback=nil): AnsiString; function wchar2win (wc: WideChar): AnsiChar; inline; function utf2win (const s: AnsiString): AnsiString; @@ -235,6 +249,8 @@ type procedure clear (); inline; procedure append (constref it: ItemT); inline; + procedure delete (idx: Integer); inline; + function remove (idx: Integer): ItemT; inline; public property count: Integer read mCount; @@ -243,8 +259,33 @@ type end; +procedure FillMemory (Dest: Pointer; Len: LongWord; Ch: Byte); inline; +procedure CopyMemory (Dest: Pointer; Src: Pointer; Len: LongWord); inline; +procedure ZeroMemory (Dest: Pointer; Len: LongWord); inline; + + implementation +uses + xstreams; + + +// ////////////////////////////////////////////////////////////////////////// // +procedure CopyMemory (Dest: Pointer; Src: Pointer; Len: LongWord); inline; +begin + Move(Src^, Dest^, Len); +end; + +procedure FillMemory (Dest: Pointer; Len: LongWord; Ch: Byte); inline; +begin + FillChar(Dest^, Len, Ch); +end; + +procedure ZeroMemory (Dest: Pointer; Len: LongWord); inline; +begin + FillChar(Dest^, Len, 0); +end; + // ////////////////////////////////////////////////////////////////////////// // constructor TSimpleList.TEnumerator.Create (const aitems: TItemArr; acount: Integer); @@ -328,16 +369,46 @@ end; procedure TSimpleList.append (constref it: ItemT); inline; +var + newsz: Integer; begin - if (mCount = Length(mItems)) then + if (mCount >= Length(mItems)) then begin - if (mCount = 0) then SetLength(mItems, 128) else SetLength(mItems, mCount*2); + newsz := mCount+(mCount div 3)+128; + SetLength(mItems, newsz); end; mItems[mCount] := it; Inc(mCount); end; +procedure TSimpleList.delete (idx: Integer); inline; +var + f: Integer; +begin + if (idx >= 0) and (idx < mCount) then + begin + for f := idx+1 to mCount-1 do mItems[f-1] := mItems[f]; + end; +end; + + +function TSimpleList.remove (idx: Integer): ItemT; inline; +var + f: Integer; +begin + if (idx >= 0) and (idx < mCount) then + begin + result := mItems[idx]; + for f := idx+1 to mCount-1 do mItems[f-1] := mItems[f]; + end + else + begin + result := Default(ItemT); + end; +end; + + // ////////////////////////////////////////////////////////////////////////// // var wc2shitmap: array[0..65535] of AnsiChar; @@ -466,25 +537,25 @@ var if (code < 0) or (code > $10FFFF) then begin result := '?'; exit; end; if (code <= $7f) then begin - result := Char(code and $ff); + result := AnsiChar(code and $ff); end else if (code <= $7FF) then begin - result := Char($C0 or (code shr 6)); - result += Char($80 or (code and $3F)); + result := AnsiChar($C0 or (code shr 6)); + result += AnsiChar($80 or (code and $3F)); end else if (code <= $FFFF) then begin - result := Char($E0 or (code shr 12)); - result += Char($80 or ((code shr 6) and $3F)); - result += Char($80 or (code and $3F)); + result := AnsiChar($E0 or (code shr 12)); + result += AnsiChar($80 or ((code shr 6) and $3F)); + result += AnsiChar($80 or (code and $3F)); end else if (code <= $10FFFF) then begin - result := Char($F0 or (code shr 18)); - result += Char($80 or ((code shr 12) and $3F)); - result += Char($80 or ((code shr 6) and $3F)); - result += Char($80 or (code and $3F)); + result := AnsiChar($F0 or (code shr 18)); + result += AnsiChar($80 or ((code shr 12) and $3F)); + result += AnsiChar($80 or ((code shr 6) and $3F)); + result += AnsiChar($80 or (code and $3F)); end else begin @@ -773,7 +844,7 @@ begin end; -function Int64ToStrComma (i: Int64): AnsiString; +function int64ToStrComma (i: Int64): AnsiString; var f: Integer; begin @@ -786,7 +857,7 @@ begin end; -function UpCase1251 (ch: Char): Char; +function upcase1251 (ch: AnsiChar): AnsiChar; inline; begin if ch < #128 then begin @@ -810,7 +881,7 @@ begin end; -function LoCase1251 (ch: Char): Char; +function locase1251 (ch: AnsiChar): AnsiChar; inline; begin if ch < #128 then begin @@ -834,7 +905,7 @@ begin end; -function StrEquCI1251 (const s0, s1: AnsiString): Boolean; +function strEquCI1251 (const s0, s1: AnsiString): Boolean; var i: Integer; begin @@ -920,7 +991,7 @@ const ); -function decodeUtf8Char (s: AnsiString; var pos: Integer): char; +function decodeUtf8Char (s: AnsiString; var pos: Integer): AnsiChar; var b, c: Integer; begin @@ -938,7 +1009,7 @@ begin b := Byte(s[pos]); Inc(pos); - if b < $80 then begin result := char(b); exit; end; + if b < $80 then begin result := AnsiChar(b); exit; end; // mask out unused bits if (b and $FE) = $FC then b := b and $01 @@ -959,7 +1030,7 @@ begin end; // done, try 1251 - for c := 128 to 255 do if uni2wint[c] = b then begin result := char(c and $FF); exit; end; + for c := 128 to 255 do if uni2wint[c] = b then begin result := AnsiChar(c and $FF); exit; end; // alas end; @@ -1108,6 +1179,36 @@ begin end; {$ENDIF} +procedure writeSign (st: TStream; const sign: AnsiString); +begin + if (Length(sign) > 0) then st.WriteBuffer(sign[1], Length(sign)); +end; + +function checkSign (st: TStream; const sign: AnsiString): Boolean; +var + buf: packed array[0..7] of AnsiChar; + f: Integer; +begin + result := false; + if (Length(sign) > 0) then + begin + if (Length(sign) <= 8) then + begin + st.ReadBuffer(buf[0], Length(sign)); + for f := 1 to Length(sign) do if (buf[f-1] <> sign[f]) then exit; + end + else + begin + for f := 1 to Length(sign) do + begin + st.ReadBuffer(buf[0], 1); + if (buf[0] <> sign[f]) then exit; + end; + end; + end; + result := true; +end; + procedure writeInt (st: TStream; v: Byte); overload; begin writeIntegerLE(st, @v, 1); end; procedure writeInt (st: TStream; v: ShortInt); overload; begin writeIntegerLE(st, @v, 1); end; procedure writeInt (st: TStream; v: Word); overload; begin writeIntegerLE(st, @v, 2); end; @@ -1126,6 +1227,31 @@ procedure writeIntBE (st: TStream; v: LongInt); overload; begin writeIntegerBE(s procedure writeIntBE (st: TStream; v: Int64); overload; begin writeIntegerBE(st, @v, 8); end; procedure writeIntBE (st: TStream; v: UInt64); overload; begin writeIntegerBE(st, @v, 8); end; +procedure writeBool (st: TStream; b: Boolean); begin writeInt(st, Byte(b)); end; +function readBool (st: TStream): Boolean; begin result := (readByte(st) <> 0); end; + + +procedure writeStr (st: TStream; const str: AnsiString; maxlen: LongWord=65535); +begin + if (Length(str) > maxlen) then raise XStreamError.Create('string too long'); + if (maxlen <= 65535) then writeInt(st, Word(Length(str))) else writeInt(st, LongWord(Length(str))); + if (Length(str) > 0) then st.WriteBuffer(str[1], Length(str)); +end; + +function readStr (st: TStream; maxlen: LongWord=65535): AnsiString; +var + len: Integer; +begin + result := ''; + if (maxlen <= 65535) then len := readWord(st) else len := Integer(readLongWord(st)); + if (len < 0) or (len > maxlen) then raise XStreamError.Create('string too long'); + if (len > 0) then + begin + SetLength(result, len); + st.ReadBuffer(result[1], len); + end; +end; + procedure readIntegerLE (st: TStream; vp: Pointer; size: Integer); {$IFDEF ENDIAN_LITTLE} @@ -1252,7 +1378,7 @@ end; *) -function formatstrf (const fmt: AnsiString; args: array of const; writerCB: TFormatStrFCallback=nil): AnsiString; +function formatstrf (const fmt: AnsiString; const args: array of const; writerCB: TFormatStrFCallback=nil): AnsiString; const PadSpaces: AnsiString = ' '; PadZeroes: AnsiString = '00000000000000000000000000000000000000000000000000000000000000000000000';