Skip to main content

lengthIsBetween

Short summary

This assertion method checks if the current string stringToCheck is length is equal or grater than minLength and equal or less than maxLength

Attention: All strings are handled as null terminated word streams. For UTF-16 is end of the string 16#00_00

Parameters

NameTypeCommentKind
stringToCheckPOINTER TO WORDcurrent string to checkinput
minLengthUDINTlower limit of the string lengthinput
maxLengthUDINTupper limit of the string lengthinput
stringLengthUnitUnicodeStringLengthUnitstring length units of measurementinput
messageAssertMessagemessage if the assertion is falseinput

Code

Declaration

METHOD lengthIsBetween
VAR_INPUT
(* current string to check *)
stringToCheck :POINTER TO WORD;
(* lower limit of the string length *)
minLength :UDINT;
(* upper limit of the string length *)
maxLength :UDINT;
(* string length units of measurement *)
stringLengthUnit :UnicodeStringLengthUnit;
(* message if the assertion is false *)
message :AssertMessage;
END_VAR
VAR
(* length of ``stringToCheck`` *)
stringToCheckWordCount, stringToCheckCodePointCount, stringToCheckByteCount :UDINT;
normalizedStringBuffer :POINTER TO WORD;
buffersize, 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

IF minLength > maxLength THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16lengthIsBetween'));
RETURN;
END_IF

CNM_UnicodeUtilities.GetUtf16StringLength(
stringToCheck,
wordCount => stringToCheckWordCount,
characterCount => stringToCheckCodePointCount
);
stringToCheckByteCount := 2 * stringToCheckWordCount;

// check if string is empty
IF (stringToCheckWordCount = 0) THEN
IF (minLength > 0) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16lengthIsBetween'));
END_IF
RETURN;
END_IF

CASE (stringLengthUnit) OF
UnicodeStringLengthUnit.BYTES:
IF (stringToCheckByteCount < minLength OR_ELSE stringToCheckByteCount > maxLength) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16lengthIsBetween'));
END_IF

UnicodeStringLengthUnit.CHARACTERS:
IF (stringToCheckCodePointCount < minLength OR_ELSE stringToCheckCodePointCount > maxLength) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16lengthIsBetween'));
END_IF

UnicodeStringLengthUnit.CHARACTERS_NFC:
// string size cant increase with NFC
normalizedStringBuffer := __NEW(WORD, (stringToCheckWordCount+1));
IF normalizedStringBuffer = 0 THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16LengthIsBetween, malloc failed'));
RETURN;
END_IF
buffersize := stringToCheckByteCount+SIZEOF(WORD); // stringsize + NULL terminator

CNM_UnicodeUtilities.NormalizeUtf16String(
utf16StringBuffer := stringToCheck,
normalForm := CNM_UnicodeUtilities.NormalizationForm.NFC,
normalizedStringBuffer := normalizedStringBuffer,
bufferSize := buffersize,
normalizedStringLength => normalizedLength
);

CNM_UnicodeUtilities.GetUtf16StringLength(
utf16StringAddress := normalizedStringBuffer,
characterCount => stringToCheckCodePointCount
);

__DELETE(normalizedStringBuffer);

IF (stringToCheckCodePointCount < minLength OR_ELSE stringToCheckCodePointCount > maxLength) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16lengthIsBetween'));
END_IF

UnicodeStringLengthUnit.CHARACTERS_NFD:
// string size can increase with NFD
normalizedStringBuffer := __NEW(WORD, (stringToCheckWordCount * NORMALIZATION_FACTOR + 1));
IF normalizedStringBuffer = 0 THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16LengthIsBetween, malloc failed'));
RETURN;
END_IF

// stringsize can increase for NFD + NULL terminator word
buffersize := stringToCheckByteCount * NORMALIZATION_FACTOR + SIZEOF(WORD);

CNM_UnicodeUtilities.NormalizeUtf16String(
utf16StringBuffer := stringToCheck,
normalForm := CNM_UnicodeUtilities.NormalizationForm.NFD,
normalizedStringBuffer := normalizedStringBuffer,
bufferSize := buffersize,
normalizedStringLength => normalizedLength
);

CNM_UnicodeUtilities.GetUtf16StringLength(
utf16StringAddress := normalizedStringBuffer,
characterCount => stringToCheckCodePointCount
);

__DELETE(normalizedStringBuffer);

IF (stringToCheckCodePointCount < minLength OR_ELSE stringToCheckCodePointCount > maxLength) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16lengthIsBetween'));
END_IF

UnicodeStringLengthUnit.VISIBLE_CHARACTERS:
CNM_UnicodeUtilities.GetUtf16StringWidth( utf16StringBuffer := stringToCheck, visibleCharacters => visibleCharacters);
IF (visibleCharacters < minLength) OR_ELSE ( visibleCharacters > maxLength ) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16lengthIsBetween'));
END_IF

UnicodeStringLengthUnit.WIDTH:
width := CNM_UnicodeUtilities.GetUtf16StringWidth(stringToCheck);
IF ((
width < 0
) OR_ELSE (
TO_UDINT(width) < minLength
) OR_ELSE (
TO_UDINT(width) > maxLength
)
) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16lengthIsBetween'));
END_IF
ELSE
; // do nothing
END_CASE