Problem with packing and unpacking data in Bin2* and *2Bin functions

This forum is meant for questions and discussions about the X# language and tools
Post Reply
leon-ts
Posts: 429
Joined: Fri Feb 03, 2017 1:43 pm

Problem with packing and unpacking data in Bin2* and *2Bin functions

Post by leon-ts »

Hi,

While debugging the converted VO application, I found a difference in the way of converting strings between a group of functions like Mem2String, StringAlloc, etc. on the one hand, and Bin2_, _2Bin on the other. As we know, strings in NET are Unicode, and in VO they are ANSI. XSharp (as I saw from the source code in XSharpPublic) uses Windows code page (Encoding (WinCodePage)) string transformations for consistent behavior. But it is used only in the set of functions Mem2String, StringAlloc, etc. And the Bin2_, _2Bin function set uses a different approach - an attempt to store the original byte value in Unicode strings. As a result, it turns out that these functions work correctly within their sets, but not among themselves. And this leads to the inoperability of the VO application, where all these functions were compatible.

At the same time, as I understand it, these functions came from VO and should provide compatibility in a VO application. After all, if we are talking about a NET application, then there is a huge selection of tools for such operations: BitConverter, System.Text.Encoding, Marshal.StringToHGlobalAnsi, etc.

Need some advice on how to work around this issue in XSharp in a converted VO application now. Will there be any changes in Runtime related to these?

Best regards,
Leonid
Best regards,
Leonid
User avatar
Chris
Posts: 4562
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Problem with packing and unpacking data in Bin2* and *2Bin functions

Post by Chris »

Hi Leonid,

There can me changes in the runtime, or you may just simply redefine those functions in your code, making them work exactly as you want them to.

Can you please post a small (but compilable) sample demonstrating the incompatibilities you are getting?
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
leon-ts
Posts: 429
Joined: Fri Feb 03, 2017 1:43 pm

Problem with packing and unpacking data in Bin2* and *2Bin functions

Post by leon-ts »

Hi Chris,

The example is very simple:

Code: Select all

LOCAL DIM p[2] AS BYTE // In a real application, this data is read, for example, from a file.
p[1] := 0xF0
p[2] := 0x10
	
LOCAL c AS STRING
c := Mem2String(@p, 2)
	
LOCAL w AS WORD
w := Bin2W(c)
Result: w equals 0x1040 instead of 0x10F0

Best regards,
Leonid
Best regards,
Leonid
User avatar
Chris
Posts: 4562
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Problem with packing and unpacking data in Bin2* and *2Bin functions

Post by Chris »

Hi Leonid,

Thanks! I understand that this is only a sample, but in your real code, do you rely on the first conversion to a string with Mem2String(), do you use this returned string for anything else, apart from using it as an intermediate result, before you convert it again with Bin2W()? If it's not needed for anything else, then I think the best solution is to adjust the code so it simply generates the word directly from the byte pointer values.

If you do need the string for something more, or if this is used in too many places and you do not want to change the existing code, then you can just adjust the Bin2W(), so it works as needed by your code. Please define the following in any of your base libraries, the compiler will now pick this one, instead of the one defined in the X# runtime. Can you please check if it always gives the expected results?

Code: Select all

FUNCTION Bin2W(cUnsignedInt AS STRING) AS WORD
    LOCAL wResult := 0 AS WORD
    IF cUnsignedInt!= NULL .AND. cUnsignedInt:Length >= 2
    	cUnsignedInt := cUnsignedInt:Substring(0,2)
        LOCAL aBytes AS BYTE[]
        aBytes := StringHelpers.WinEncoding:GetBytes(cUnsignedInt)
        wResult := BitConverter.ToUInt16(aBytes, 0)
    ENDIF
    RETURN wResult
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
leon-ts
Posts: 429
Joined: Fri Feb 03, 2017 1:43 pm

Problem with packing and unpacking data in Bin2* and *2Bin functions

Post by leon-ts »

Chris,

Yes, this string contains a lot of different data packed into a string. In a real application, there is an array (ARRAY), in which different types of data: numbers, texts.
For example:

Code: Select all

{
    { 0, "SomeName0" },
    { 1, "SomeName1" },
    { 2, "SomeName2", { Date, Val1, Val2, .... "some text"  } },
    ...
}
Using a special function, such an array is packed into a string (STRING) and saved, for example, to a file (in a separate file or in the MEMO field of a DBF file). When reading back, the read data buffer (BYTE PTR) is converted into a string (Mem2String) and parsed into its components - numbers, strings. Numbers are read using Bin2, strings - as is.

After your first answer, I wrote a set of static methods (so as not to interfere with the original functions) that use WinEncoding:

Code: Select all

BEGIN NAMESPACE <MyNamespace>

    PUBLIC STATIC CLASS WinEncoding

	PUBLIC STATIC METHOD DW2Bin(dwValue AS DWORD) AS STRING
	    LOCAL byteArray := BitConverter.GetBytes(dwValue) AS BYTE[]
	    RETURN StringHelpers.WinEncoding:GetString(byteArray)

	PUBLIC STATIC METHOD Bin2DW(cUnsignedInt AS STRING) AS DWORD
	    IF ( cUnsignedInt != NULL .AND. cUnsignedInt:Length >= 4 )
                VAR byteArray := BYTE[]{ 4 }
                StringHelpers.WinEncoding:GetBytes(cUnsignedInt, 0, 4, byteArray, 0)
                RETURN BitConverter.ToUInt32(byteArray, 0)
            ENDIF
            RETURN 0

	... etc ...

    END CLASS

END NAMESPACE
Best regards,
Leonid
Best regards,
Leonid
User avatar
Chris
Posts: 4562
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Problem with packing and unpacking data in Bin2* and *2Bin functions

Post by Chris »

Hi Leonid,

OK, sounds good, that's the beauty of it, you can make everything work exactly the way it suits you!
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
Post Reply