lengthIsExact
Short summary
This assertion method checks if the current string stringToCheck length is equal to expectedLength.
Processed strings must be in UTF-8 encoding
Attention: All strings are handled as null-terminated byte streams
Parameters
| Name | Type | Comment | Kind |
|---|---|---|---|
| stringToCheck | POINTER TO BYTE | current string to check | input |
| expectedLength | UDINT | expected length of stringToCheck | input |
| stringLengthUnit | UnicodeStringLengthUnit | string length units of measurement | input |
| message | AssertMessage | message if the assertion is false | input |
Code
Declaration
METHOD lengthIsExact
VAR_INPUT
(* current string to check *)
stringToCheck :POINTER TO BYTE;
(* expected length of ``stringToCheck`` *)
expectedLength :UDINT;
(* string length units of measurement *)
stringLengthUnit :UnicodeStringLengthUnit;
(* message if the assertion is false *)
message :AssertMessage;
END_VAR
VAR
(* length of current string to check in bytes *)
stringToCheckByteCount :UDINT;
(* length of current string to check in characters *)
stringToCheckCodePointCount :UDINT;
normalizedStringBuffer :POINTER TO BYTE;
bufferSize :UDINT;
normalizedLength :UDINT;
width :DINT;
visibleCharacters :UDINT := 0;
END_VAR
VAR CONSTANT
(*After decomposition one codepoint can extend up to 4 codepoints*)
NORMALIZATION_FACTOR :UDINT := 4;
END_VAR
Implementation
CNM_UnicodeUtilities.GetUtf8StringLength(
stringToCheck,
byteCount => stringToCheckByteCount,
characterCount => stringToCheckCodePointCount
);
// check if string is empty
IF (stringToCheckByteCount = 0) THEN
IF (expectedLength <> 0) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('LengthIsExact'));
END_IF
RETURN;
END_IF
CASE (stringLengthUnit) OF
UnicodeStringLengthUnit.BYTES:
IF (stringToCheckByteCount <> expectedLength) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('LengthIsExact'));
END_IF
UnicodeStringLengthUnit.CHARACTERS:
IF (stringToCheckCodePointCount <> expectedLength) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('LengthIsExact'));
END_IF
UnicodeStringLengthUnit.CHARACTERS_NFC:
// string size cant increase with NFC
normalizedStringBuffer := __NEW(BYTE, (stringToCheckByteCount+1));
IF normalizedStringBuffer = 0 THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('lengthIsExact, malloc failed'));
RETURN;
END_IF
bufferSize := stringToCheckByteCount + 1; // stringsize + NULL terminator
CNM_UnicodeUtilities.NormalizeUtf8String(
utf8StringBuffer := stringToCheck,
normalForm := CNM_UnicodeUtilities.NormalizationForm.NFC,
normalizedStringBuffer := normalizedStringBuffer,
bufferSize := bufferSize,
normalizedStringLength => normalizedLength
);
CNM_UnicodeUtilities.GetUtf8StringLength(
stringAddress := normalizedStringBuffer,
characterCount => stringToCheckCodePointCount
);
__DELETE(normalizedStringBuffer);
IF (stringToCheckCodePointCount <> expectedLength) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('LengthIsExact'));
END_IF
UnicodeStringLengthUnit.CHARACTERS_NFD:
// string size can increase with NFD
normalizedStringBuffer := __NEW(BYTE, (stringToCheckByteCount * NORMALIZATION_FACTOR + 1));
IF normalizedStringBuffer = 0 THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('lengthIsExact, malloc failed'));
RETURN;
END_IF
bufferSize := stringToCheckByteCount * NORMALIZATION_FACTOR + 1; // stringsize can increase for NFD + NULL terminator
CNM_UnicodeUtilities.NormalizeUtf8String(
utf8StringBuffer := stringToCheck,
normalForm := CNM_UnicodeUtilities.NormalizationForm.NFD,
normalizedStringBuffer := normalizedStringBuffer,
bufferSize := bufferSize,
normalizedStringLength => normalizedLength
);
CNM_UnicodeUtilities.GetUtf8StringLength(
stringAddress := normalizedStringBuffer,
characterCount => stringToCheckCodePointCount
);
__DELETE(normalizedStringBuffer);
IF (stringToCheckCodePointCount <> expectedLength) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('LengthIsExact'));
END_IF
UnicodeStringLengthUnit.VISIBLE_CHARACTERS:
CNM_UnicodeUtilities.GetUtf8StringWidth(stringToCheck, visibleCharacters => visibleCharacters);
IF (visibleCharacters <> expectedLength) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('lengthIsExact'));
END_IF
UnicodeStringLengthUnit.WIDTH:
width := CNM_UnicodeUtilities.GetUtf8StringWidth(stringToCheck);
IF ((width < 0) OR_ELSE (TO_UDINT(width) <> expectedLength)) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('LengthIsExact'));
END_IF
ELSE
; // do nothing
END_CASE