Combine two Bytes to WideChar - delphi

Is it possible to combine two Bytes to WideChar and if yes, then how?
For example, letter "ē" in binary is 00010011 = 19 and 00000001 = 1, or 275 together.
var
WChar: WideChar;
begin
WChar := WideChar(275); // Result is "ē"
var
B1, B2: Byte;
WChar: WideChar;
begin
B1 := 19;
B2 := 1;
WChar := CombineBytesToWideChar(B1, B2); // ???
How do I get WideChar from two bytes in Delphi?

WChar := WideChar(MakeWord(B1, B2));

You should just be able to create a type and cast:
type
DoubleByte = packed record
B1: Byte;
B2: Byte;
end;
var
DB: DoubleByte;
WC: WideChar;
begin
DB.B1 := 19;
DB.B2 := 1;
WC = WideChar(DB);
end;
Failing a cast you can use Move() instead and simply copy the memory.

Related

Fast find a DWORD position in array of byte delphi

finding fastest way to find dword in array of byte
I have this dword for example. I implemented a method but its slow because I convert byte array to hex string and search the dword as string, the conversion takes up most of the time!!
need to find pos of this dword --> 01 49 08 EF 48 C0 C6 91
var
myarray:array of byte;
p:integer;
begin
p:= pos('014908EF48C0C691',array2hex(myarray));
end;
i need to find the position of the dword fast search in byte array with out converting !
A DWORD is 4 bytes, so 01 49 08 EF 48 C0 C6 91 is too large to be a single DWORD. It is either 2 DWORD values, or it is a (U)Int64.
But either way, converting the array to a string is definitely the wrong way to go. Just search the raw array data as-is instead, eg:
const
bytesToFind: array[0..7] of Byte = ($01, $49, $08, $EF, $48, $C0, $C6, $91);
var
myarray: array of byte;
I, FoundAtIndex, Len: integer;
begin
myarray := ...;
Len := Length(myarray);
FoundAtIndex := -1;
for I := 0 to Len-8 do
begin
if (myarray[I] = $01) and
((I+8) <= Len) and
CompareMem(#myarray[I], #bytesToFind, 8) then
begin
FoundAtIndex := I;
Break;
end;
end;
if FoundAtIndex <> -1 then
begin
// use FoundAtIndex as needed...
end else
begin
// not found...
end;
end;

convert 2 bytes into small integer

I need to generate a small integer data type out of 2 bytes, my code fails
with result = 0
function BytestoSmallInt(B0, B1: Byte): SmallInt;
var
Number: SmallInt;
pointer : ^SmallInt;
small: array [0 .. 1] of Byte absolute Number;
begin
pointer := #Number;
small[0] := B1;
small[1] := B0;
Result := pointer^;
end;
I can't reproduce the issue you describe. The code you have shown works fine for me.
However, you don't need the pointer variable at all:
function BytesToSmallInt(B0, B1: Byte): SmallInt;
var
Number: SmallInt;
small: array [0 .. 1] of Byte absolute Number;
begin
small[0] := B1;
small[1] := B0;
Result := Number;
end;
And you can even get rid of the array, too:
function BytesToSmallInt(B0, B1: Byte): SmallInt;
begin
Result := (Smallint(B0) shl 8) or B1;
end;

WideChar to Bytes?

I have simple question here. How to convert WideChar to 2xByte in Delphi - 7? I searched the internet and the StackOverflow but with no results...
David gave you the preferable way, namely,
var
b1, b2: Byte;
wc: WideChar;
...
b1 := WordRec(wc).Lo;
b2 := WordRec(wc).Hi;
A few other options (just for fun):
b1 := Lo(Word(wc));
b2 := Hi(Word(wc));
and
b1 := Byte(wc);
b2 := Byte(Word(wc) shr 8);
and
b1 := PByte(#wc)^;
b2 := PByte(NativeUInt(#wc) + 1)^;
and
var
wc: WideChar;
bytes: WordRec absolute wc;
begin
// Magic! The bytes are already found in bytes.Lo and bytes.Hi!
Lots of ways to do this. For example my personal choice would be:
var
b1, b2: Byte;
wc: WideChar;
....
b1 := WordRec(wc).Lo;
b2 := WordRec(wc).Hi;

Delphi XE2 64bit: record pointer, invalid typecast

How would I recode this to compile on 64-bit for Delphi XE2?
On the first code I get an error size is too large over 2gb.
On the second, Invalid Typecast on: if int64(TMethod(FOnChangeOO[i1])) = int64(TMethod(changeEvent)) then
1)
TExtBool = (no, yes, other);
TAByte = array [0..maxInt -1] of byte;
TAShortInt = array [0..maxInt -1] of shortInt;
TAChar = array [0..maxInt div sizeOf(Char)-1] of Char;
TAAnsiChar = array [0..maxInt -1] of AnsiChar;
TAWideChar = array [0..maxInt shr 1-1] of WideChar;
TABoolean = array [0..maxInt -1] of boolean;
TAExtBool = array [0..maxInt -1] of TExtBool;
TAWord = array [0..maxInt shr 1-1] of word;
TASmallInt = array [0..maxInt shr 1-1] of smallInt;
TACardinal = array [0..maxInt shr 2-1] of cardinal;
TAInteger = array [0..maxInt shr 2-1] of integer;
TAPointer = array [0..maxInt shr 2-1] of pointer;
TAString = array [0..maxInt shr 2-1] of string;
TAAnsiString = array [0..maxInt shr 2-1] of AnsiString;
TAWideString = array [0..maxInt shr 2-1] of WideString;
TAUnicodeString = array [0..maxInt shr 2-1] of UnicodeString;
TAIUnknown = array [0..maxInt shr 2-1] of IUnknown;
TAInt64 = array [0..maxInt shr 3-1] of int64;
2)
TMethod = record code, data: pointer; end;
TIListChangeEventOO = procedure (const list: ICustomBasicList; const item: IBasic;
beforeChange: boolean;
changeType: TChangeType; oldIndex, index: integer) of object;
ICustomBasicList = interface (IList) ['{EE6D35A0-5F85-11D3-A52D-00005A180D69}']
TChangeType = (lctUnchanged, lctChanged, lctNew, lctDeleted);
IBasic = interface ['{53F8CE42-2C8A-11D3-A52D-00005A180D69}']
procedure TICustomBasicList.RegisterChangeEvent(changeEvent: TIListChangeEventOO);
var i1 : integer;
begin
FSection.Enter;
try
if CheckValid then begin
for i1 := 0 to high(FOnChangeOO) do
if int64(TMethod(FOnChangeOO[i1])) = int64(TMethod(changeEvent)) then
exit;
i1 := Length(FOnChangeOO);
SetLength(FOnChangeOO, i1 + 1);
FOnChangeOO[i1] := changeEvent;
end;
finally FSection.Leave end;
end;
function TICustomBasicList.UnregisterChangeEvent(changeEvent: TIListChangeEvent) : boolean;
var i1, i2 : integer;
begin
result := false;
FSection.Enter;
try
i2 := high(FOnChange);
for i1 := i2 downto 0 do
if #FOnChange[i1] = #changeEvent then begin
FOnChange[i1] := FOnChange[i2];
dec(i2);
result := true;
FSuccess := true;
end;
if result then SetLength(FOnChange, i2 + 1)
else SetLastError(ERROR_FILE_NOT_FOUND);
finally FSection.Leave end;
end;
1) Instead of "shr 1/2/3" you should always use SizeOf(T) because "shr 2 = div 4" is not equal to "div SizeOf(Pointer)" in 64 bit. The same for UnicodeString, WideString, IUnknown, ...
2) TMethod is a record with two pointers. In 32 bit, the two pointers need 8 bytes (32bit * 2). In 64 bit, the two pointers need 16 bytes (64bit * 2). And an Int64 can't hold 128 bit. So you now have to compare the two fields directly instead of casting it.
if (TMethod(FOnChangeOO[i1]).Data = TMethod(changeEvent).Data) and
(TMethod(FOnChangeOO[i1]).Code = TMethod(changeEvent).Code) then

Delphi - Convert byte array to string

How do I convert a byte array to a string (base 256) in Delphi?
Use the built-in SetString command. It sets the string to the required length and copies the bytes. There's no need for the array to be null-terminated. In fact, if the array has zero--valued bytes in it, they'll correctly appear within the string; they won't terminate the string.
SetString(AnsiStr, PAnsiChar(#ByteArray[0]), LengthOfByteArray);
If you have a UnicodeString, then you'll need to halve the length parameter since it measures characters, not bytes:
SetString(UnicodeStr, PWideChar(#ByteArray[0]), LengthOfByteArray div 2);
See also, Converting TMemoryStream to String in Delphi 2009.
I'm not sure what do you mean by Base256. If you want to get hex representation of data, use this:
function bintostr(const bin: array of byte): string;
const HexSymbols = '0123456789ABCDEF';
var i: integer;
begin
SetLength(Result, 2*Length(bin));
for i := 0 to Length(bin)-1 do begin
Result[1 + 2*i + 0] := HexSymbols[1 + bin[i] shr 4];
Result[1 + 2*i + 1] := HexSymbols[1 + bin[i] and $0F];
end;
end;
If you want to just render the data as a string (this doesn't change the content!), where for each byte of data you'd get a single ASCII symbol with that code, do
function bintoAscii(const bin: array of byte): AnsiString;
var i: integer;
begin
SetLength(Result, Length(bin));
for i := 0 to Length(bin)-1 do
Result[1+i] := AnsiChar(bin[i]);
end;
var
LString : string;
LBytes : TArray<byte>;
begin
LBytes := TArray<byte>.Create($01, $02, $03);
LString := TEncoding.ANSI.GetString(ABytes);
end;
Being GetString() the reverse operation of GetBytes().
I think there is another nice way to convert byte arrays in strings - an Indy function called BytesToString contained in IdGlobal. It also allows you to specify StartIndex, Length and TEncoding for your string. I've used it several times and I find it very useful.
function bintostr_r(const bin: array of byte): string;
var i,j:integer;
res:string ;
begin
res:='';
for i:=0 to length(bin)-1 do
begin
for j:=1 to 8 do
res:=Inttostr( ((bin[i] shr (j - 1)) and ((1 shl 1) - 1)) ) +res ;
end;
result:=res;
end;
procedure TForm1.FormCreate(Sender: TObject);
var OrigStat: array [1..6] of byte;
res:integer;
begin
OrigStat[1]:=253; // 11111101
OrigStat[2]:=252;
OrigStat[3]:=251;
OrigStat[4]:=250;
OrigStat[5]:=249;
OrigStat[6]:=248;
Edit9.text:=bintostr_r(OrigStat);
end;
result => 111110001111100111111010111110111111110011111101

Resources