Skip to main content

startsWith

Short summary

This assertion method checks if the current string stringToCheck starts with start

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

Parameters

NameTypeCommentKind
stringToCheckPOINTER TO WORDcurrent string to checkinput
startPOINTER TO WORDexpected start of stringToCheckinput
ignoreCasesBOOLTRUE means ignore cases; FALSE means cases must be equal tooinput
trimBOOLTRUE means truncation of spaces on the left sideinput
messageAssertMessagemessage if the assertion is falseinput
normalizeStringsBOOLnormalize both strings for checkinput

Code

Declaration

METHOD startsWith
VAR_INPUT
(* current string to check *)
stringToCheck :POINTER TO WORD;
(* expected start of ``stringToCheck`` *)
start :POINTER TO WORD;
(* ``TRUE`` means ignore cases; ``FALSE`` means cases must be equal too *)
ignoreCases :BOOL;
(* ``TRUE`` means truncation of spaces on the left side *)
trim :BOOL;
(* message if the assertion is false *)
message :AssertMessage;
(*normalize both strings for check*)
normalizeStrings :BOOL := TRUE;
END_VAR
VAR
(* length of ``stringToCheck`` in characters *)
lengthStringToCheck :UDINT;
(* length of ``stringToCheck`` in words *)
lengthStringToCheckInWord :UDINT;
(* length of ``start`` in characters *)
lengthOfStart :UDINT;
(* length of ``start`` in words *)
lengthOfStartInWord :UDINT;
(* string address we use to compare, if it's case sensitive it's equal to ``stringToCheck`` *)
usedStringToCheck :POINTER TO WORD;
(* seacrch string address we use to compare, if it's case sensitive it's equal to ``start`` *)
usedStartString :POINTER TO WORD;
END_VAR
VAR
(* DWORD array we use to check *)
usedCodePointsToCheck, normalizedUsedCodePointsToCheck :POINTER TO CNM_UnicodeUtilities.UnicodeCodePoint;
usedCodePointToCheckCount :UDINT;

(* DWORD array we use to compare *)
usedStartCodePoints, normalizedUsedStartCodePoints :POINTER TO CNM_UnicodeUtilities.UnicodeCodePoint;
usedStartCodePointCount :UDINT;
END_VAR
VAR CONSTANT
(*After decomposition one codepoint can extend up to 4 codepoints*)
NORMALIZATION_FACTOR :UDINT := 4;
END_VAR

Implementation

CNM_UnicodeUtilities.GetUtf16StringLength(
utf16StringAddress := stringToCheck,
wordCount => lengthStringToCheckInWord
);

CNM_UnicodeUtilities.GetUtf16StringLength(
utf16StringAddress := start,
wordCount => lengthOfStartInWord
);

usedCodePointsToCheck := __NEW(CNM_UnicodeUtilities.UnicodeCodePoint, (lengthStringToCheckInWord+1));
IF (usedCodePointsToCheck = 0) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16StartsWith, malloc failed'));
RETURN;
END_IF

usedStartCodePoints := __NEW(CNM_UnicodeUtilities.UnicodeCodePoint, (lengthOfStartInWord+1));
IF (usedStartCodePoints = 0) THEN
__DELETE(usedCodePointsToCheck);
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16StartsWith, malloc failed'));
RETURN;
END_IF

(* convert ``stringToCheck`` to code points *)
CNM_UnicodeUtilities.GetCodepointsFromUtf16String(
utf16StringAddress := stringToCheck,
utf16StringWordCount := lengthStringToCheckInWord,
codepointBuffer := usedCodePointsToCheck,
bufferSize := SIZEOF(CNM_UnicodeUtilities.UnicodeCodePoint)*(lengthStringToCheckInWord+1),
codePointCount => usedCodePointToCheckCount);

(* convert ``searchString`` to code points *)
CNM_UnicodeUtilities.GetCodepointsFromUtf16String(
utf16StringAddress := start,
utf16StringWordCount := lengthOfStartInWord,
codepointBuffer := usedStartCodePoints,
bufferSize := SIZEOF(CNM_UnicodeUtilities.UnicodeCodePoint)*(lengthOfStartInWord+1),
codePointCount => usedStartCodePointCount
);

IF (((
NOT normalizeStrings
) OR_ELSE (
(lengthOfStartInWord = 0) OR_ELSE (lengthStringToCheckInWord = 0)
)
) AND_THEN (
NOT THIS^.isContainsCheckNecessary(
stringToCheck := usedCodePointsToCheck,
searchString := usedStartCodePoints,
lengthStringToCheck := usedCodePointToCheckCount * SIZEOF(CNM_UnicodeUtilities.UnicodeCodePoint),
lengthSearchString := usedStartCodePointCount * SIZEOF(CNM_UnicodeUtilities.UnicodeCodePoint),
additionalText := THIS^.getDebugInfo('utf16StartsWith'),
message := message
)
)
) THEN
__DELETE(usedCodePointsToCheck);
__DELETE(usedStartCodePoints);
RETURN;
END_IF

IF normalizeStrings THEN
normalizedUsedCodePointsToCheck := __NEW(CNM_UnicodeUtilities.UnicodeCodePoint, (lengthStringToCheckInWord * NORMALIZATION_FACTOR));
IF (normalizedUsedCodePointsToCheck = 0) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16StartsWith, malloc failed'));
__DELETE(usedCodePointsToCheck);
__DELETE(usedStartCodePoints);
RETURN;
END_IF

normalizedUsedStartCodePoints := __NEW(CNM_UnicodeUtilities.UnicodeCodePoint, (lengthOfStartInWord*NORMALIZATION_FACTOR));
IF (normalizedUsedStartCodePoints = 0) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16StartsWith, malloc failed'));
__DELETE(usedCodePointsToCheck);
__DELETE(usedStartCodePoints);
__DELETE(normalizedUsedCodePointsToCheck);
RETURN;
END_IF

CNM_UnicodeUtilities.NormalizeCodepointsFormD(
codePoints := usedCodePointsToCheck,
codePointsCount := usedCodePointToCheckCount,
normalizedCodepoints := normalizedUsedCodePointsToCheck,
bufferSize := (lengthStringToCheckInWord * NORMALIZATION_FACTOR) * SIZEOF(CNM_UnicodeUtilities.UnicodeCodePoint),
normalizedCodepointsCount => usedCodePointToCheckCount
);
__DELETE(usedCodePointsToCheck);
usedCodePointsToCheck := normalizedUsedCodePointsToCheck;

CNM_UnicodeUtilities.NormalizeCodepointsFormD(
codePoints := usedStartCodePoints,
codePointsCount := usedStartCodePointCount,
normalizedCodepoints := normalizedUsedStartCodePoints,
bufferSize := (lengthOfStartInWord * NORMALIZATION_FACTOR) * SIZEOF(CNM_UnicodeUtilities.UnicodeCodePoint),
normalizedCodepointsCount => usedStartCodePointCount
);
__DELETE(usedStartCodePoints);
usedStartCodePoints := normalizedUsedStartCodePoints;
END_IF

IF trim THEN
CNM_UnicodeUtilities.TrimLeftCodepoints(
codepoints := usedCodePointsToCheck,
codepointCount := usedCodePointToCheckCount,
newCodepointCount => usedCodePointToCheckCount
);
CNM_UnicodeUtilities.TrimLeftCodepoints(
codepoints := usedStartCodePoints,
codepointCount := usedStartCodePointCount,
newCodepointCount => usedStartCodePointCount
);
END_IF


IF (ignoreCases) THEN
CNM_UnicodeUtilities.GetUpperCaseForCodepoint(usedCodePointsToCheck, usedCodePointToCheckCount);
CNM_UnicodeUtilities.GetUpperCaseForCodepoint(usedStartCodePoints, usedStartCodePointCount);
END_IF

IF (Tc2_System.MEMCMP(
usedCodePointsToCheck,
usedStartCodePoints,
usedStartCodePointCount * SIZEOF(CNM_UnicodeUtilities.UnicodeCodePoint)
) <> CNM_ReturnTypes.ComparationResult.EQUAL
) THEN
THIS^.assertionWasWrong(message, THIS^.getDebugInfo('utf16StartsWith'));
END_IF;

__DELETE(usedCodePointsToCheck);
__DELETE(usedStartCodePoints);