Skip to main content

startsWith

Short summary

This assertion method checks if the current string stringToCheck starts with string start. Processed strings must be in UTF-8 encoding

Attention: All strings are handled as null-terminated byte streams

Parameters

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

Code

Declaration

METHOD startsWith
VAR_INPUT
(* current string to check *)
stringToCheck :POINTER TO BYTE;
(* expected start of ``stringToCheck`` *)
start :POINTER TO BYTE;
(* ``TRUE`` means ignore cases; ``FALSE`` means that cases must be equal too *)
ignoreCases :BOOL;
(* ``TRUE`` means truncation of spaces on the left side of ``stringToCheck``*)
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 bytes *)
lengthStringToCheckInByte :UDINT;
(* length of ``searchString`` in bytes *)
lengthSearchStringInByte :UDINT;
(* 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.GetUtf8StringLength(stringAddress := stringToCheck, byteCount => lengthStringToCheckInByte);
CNM_UnicodeUtilities.GetUtf8StringLength(stringAddress := start, byteCount => lengthSearchStringInByte);

IF (((
NOT normalizeStrings
) OR (
lengthStringToCheckInByte = 0
) OR (
lengthSearchStringInByte = 0
)) AND_THEN(
NOT THIS^.isContainsCheckNecessary(
stringToCheck := stringToCheck,
searchString := start,
lengthStringToCheck := lengthStringToCheckInByte,
lengthSearchString := lengthSearchStringInByte,
additionalText := THIS^.getDebugInfo('startsWith'),
message := message
)
)
) THEN
RETURN;
END_IF

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

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

(* convert ``stringToCheck`` to code points *)
CNM_UnicodeUtilities.GetCodepointsFromUtf8String(
utf8StringAddress := stringToCheck,
utf8StringByteCount := lengthStringToCheckInByte,
codePointBuffer := usedCodePointsToCheck,
bufferSize := SIZEOF(CNM_UnicodeUtilities.UnicodeCodePoint)*lengthStringToCheckInByte,
codePointsCount => usedCodePointToCheckCount);

(* convert ``searchString`` to code points *)
CNM_UnicodeUtilities.GetCodepointsFromUtf8String(
utf8StringAddress := start,
utf8StringByteCount := lengthSearchStringInByte,
codePointBuffer := usedStartCodePoints,
bufferSize := SIZEOF(CNM_UnicodeUtilities.UnicodeCodePoint)*lengthSearchStringInByte,
codePointsCount => usedStartCodePointCount);



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

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

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

IF (trim) THEN
CNM_UnicodeUtilities.TrimLeftCodepoints(
codepoints := usedStartCodePoints,
codepointCount := usedStartCodePointCount,
newCodepointCount => usedStartCodePointCount
);
CNM_UnicodeUtilities.TrimLeftCodepoints(
codepoints := usedCodePointsToCheck,
codepointCount := usedCodePointToCheckCount,
newCodepointCount => usedCodePointToCheckCount
);
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('startsWith'));
END_IF;

__DELETE(usedCodePointsToCheck);
__DELETE(usedStartCodePoints);