Closed sagatowski closed 4 years ago
The Tc2_Standard.LEN and Tc2_Standard.WLEN are limited to 255 characters. However Beckhoff states "As a rule, TwinCAT does not limit the string length" in infosys > TwinCAT 3 > TE1000 XAE > PLC > Reference Programming > Data types > STRING. I present two compare functions (below) for any length string or wstring. You can find a library with test suite at my forge account (with cfUnit). The functions themselves do not depend on any libs.
FUNCTION StringEquals : BOOL
VAR_INPUT
a : ANY;
b : ANY;
END_VAR
VAR
i : DINT;
END_VAR
IF a.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_STRING AND b.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_STRING THEN
//LOOP Exits when i = last byte of smallest Wstring,
//or when two bytes are not equal,
//or when either bytes is 0x00 (terminating character)
WHILE (i < (MIN(a.diSize,b.diSize) - 1)) AND (a.pValue[i] = b.pValue[i]) AND (a.pValue[i] <> 0) AND (b.pValue[i] <> 0) DO
i := i+1;
END_WHILE
StringEquals := (a.pValue[i] = 0) AND (b.pValue[i] = 0);
ELSE
StringEquals := FALSE;
END_IF
and
FUNCTION WstringEquals : BOOL
VAR_INPUT
a : ANY;
b : ANY;
END_VAR
VAR
i : DINT;
pwA : POINTER TO WORD;
pwB : POINTER TO WORD;
END_VAR
IF a.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_WSTRING AND b.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_WSTRING THEN
pwA := a.pValue;
pwB := b.pValue;
//LOOP Exits when i = last word of smallest wWstring,
//or when two words are not equal,
//or when either word is 0x0000 (terminating character)
WHILE (i < (MIN(a.diSize/2,b.diSize/2) - 1)) AND (pwA[i] = pwB[i]) AND (pwA[i] <> 0) AND (pwB[i] <> 0) DO
i := i+1;
END_WHILE
WstringEquals := (pwA[i] = 0) AND (pwB[i] = 0);
ELSE
WstringEquals := FALSE;
END_IF
The Tc2_Standard.LEN and Tc2_Standard.WLEN are limited to 255 characters. However Beckhoff states "As a rule, TwinCAT does not limit the string length" in infosys > TwinCAT 3 > TE1000 XAE > PLC > Reference Programming > Data types > STRING. I present two compare functions (below) for any length string or wstring. You can find a library with test suite at my forge account (with cfUnit). The functions themselves do not depend on any libs.
FUNCTION StringEquals : BOOL VAR_INPUT a : ANY; b : ANY; END_VAR VAR i : DINT; END_VAR IF a.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_STRING AND b.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_STRING THEN //LOOP Exits when i = last byte of smallest Wstring, //or when two bytes are not equal, //or when either bytes is 0x00 (terminating character) WHILE (i < (MIN(a.diSize,b.diSize) - 1)) AND (a.pValue[i] = b.pValue[i]) AND (a.pValue[i] <> 0) AND (b.pValue[i] <> 0) DO i := i+1; END_WHILE StringEquals := (a.pValue[i] = 0) AND (b.pValue[i] = 0); ELSE StringEquals := FALSE; END_IF
and
FUNCTION WstringEquals : BOOL VAR_INPUT a : ANY; b : ANY; END_VAR VAR i : DINT; pwA : POINTER TO WORD; pwB : POINTER TO WORD; END_VAR IF a.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_WSTRING AND b.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_WSTRING THEN pwA := a.pValue; pwB := b.pValue; //LOOP Exits when i = last word of smallest wWstring, //or when two words are not equal, //or when either word is 0x0000 (terminating character) WHILE (i < (MIN(a.diSize/2,b.diSize/2) - 1)) AND (pwA[i] = pwB[i]) AND (pwA[i] <> 0) AND (pwB[i] <> 0) DO i := i+1; END_WHILE WstringEquals := (pwA[i] = 0) AND (pwB[i] = 0); ELSE WstringEquals := FALSE; END_IF
This is neat stuff! The current version of TcUnit only supports the same string length as the beckhoff string-functions (255). I might include these functions into TcUnit (with appropriate credits), so that TcUnit can use strings/wstrings longer than 255!
Solved in commit 13276ed.
The method AssertEquals(ANY) takes an ANY. It does so by first comparing the data types, and if they match, compare the size of the inputs. For most data values this might make sense, but STRING and WSTRING are two exceptions. If two strings are declared as:
Although their declaration is different in terms of size, their content is equal,
This is visible when the free function F_AnyToUnionValue() is used, as this stores the data in a fixed size value (255 for string and wstring, although wstring actually stores more bytes than that).
Instead the following should be done: in.
Make exceptions for STRING and WSTRING, and use the Tc2_Standard.LEN and Tc2_Standard.WLEN functions instead.