Exemples
Le Generic String Base
une bibliothèque est fournie pour rendre le traitement des chaînes aussi simple que possible. Cependant, il utilise VAR_GENERIC CONSTANT
fonction de compilation et ne peut donc être utilisée qu'à partir de CODESYS Mise à jour 5 V3.5 SP19.
Bibliothèque : Generic String Base
Voici un exemple (myString
) d'un GSB.UTF8String
d'une capacité de 128 octets est créé et le segment de chaîne avec la valeur d'une variable STRING (chiffre romain 1968) est initialisé. Les méthodes de STR.IString
sont disponibles.
STRING
à IString
VAR myString : GSB.UTF8String<128> := (sValue := UTF8#'𝕄CMℒ✖Ⅷ'); // römisch 1968 psString : POINTER TO STRING; udiSize, udiLength : UDINT; xASCII, xOk : BOOL; END_VAR psString := myString.GetSegment(udiSize=>udiSize, udiLength=>udiLength, xASCII=>xASCII); // Conversion back to the STRING data type xOk := ( myString.IsValid() AND // A valid UTF-8 encoding is present udiSize = 128 AND // The capacity of the string in bytes myString.Len() = 17 AND // The current length of the string in bytes STR.RuneCount(myString) = 6 // The current number of characters in the string );
VAR myString : GSB.UTF8String<20> := (sValue := UTF8#'𝕄CMℒ✖Ⅷ'); // roman 1968 sValue : STRING := 'wurden in Mexico-Stadt die'; wsValue : WSTRING := "ⅩⅨ."; diSpace : STR.RUNE := 32; myValue : GSB.UTF8String<128> := (sValue := UTF8#'Ѻℓƴμρ☤ṧḉнεη $$ρї℮łℯ α♭ℊεℌαʟ⊥℮ᾔ.'); myBuilder : GSB.Builder<(*udiInitialCapacity*) 64, (*usiExtensionFactor*) 50> := (itfString:=myString); myResult : GSB.UTF8String<128>; {attribute 'monitoring_encoding' := 'UTF-8'} sResult : STRING(128) := UTF8#'𝕄CMℒ✖Ⅷ wurden in Mexico-Stadt die ⅩⅨ. Ѻℓƴμρ☤ṧḉнεη $$ρї℮łℯ α♭ℊεℌαʟ⊥℮ᾔ.'; psResult : POINTER TO STRING; udiLength : UDINT; xOk : BOOL; END_VAR myBuilder.WriteRune(diSpace); myBuilder.WriteString(sValue); myBuilder.WriteRune(diSpace); myBuilder.WriteWString(wsValue); myBuilder.WriteRune(diSpace); myBuilder.WriteIString(myValue); udiLength := myBuilder.Len(); // The number of bytes occupied in the builder. myBuilder.ToIString(myResult); // The individual parts of the string are copied together to myResult. psResult := myResult.GetSegment(); xOk := (psResult^ = sResult); // Both memory areas should have the same content.
Dans l'exemple ci-dessus, une instance du générateur est créée avec une capacité initiale de 64 octets (udiInitialCapacity
) et un facteur dynamique de 50 (usiExtensionFactor
). La chaîne générée plus haut est toujours transmise dans la déclaration et, par conséquent, le générateur est rempli avec cette chaîne (UTF8#'𝕄CMℒ✖Ⅷ'
). À l'aide du usiExtensionFactor
paramètre, augmente le générateur de 50 % lorsque sa capacité actuelle est épuisée.
VAR sPath : STRING := 'myFilePath'; hFile : RTS_IEC_HANDLE := RTS_INVALID_HANDLE; myBuilder : GSB.Builder<(*udiInitialCapacity*) 16#10000, (*usiExtensionFactor*) 50>; abyBuffer : ARRAY[0..4095] OF BYTE; pbyData : POINTER TO BYTE; udiSize : UDINT; udiCount : UDINT; eEncoding : SCV.ENCODING; eErrorID : SCV.ERROR; udiResult : RTS_IEC_RESULT; END_VAR hFile := SysFileOpen(sPath, ACCESS_MODE.AM_READ, ADR(udiResult)); IF udiResult <> ERRORS.ERR_OK THEN // handle error condition RETURN; END_IF REPEAT // fake loop - We need the EXIT feature pbyData := ADR(abyBuffer); udiSize := TO_UDINT(SysFileRead(hFile, pbyData, XSIZEOF(abyBuffer), ADR(udiResult))); IF udiResult <> ERRORS.ERR_OK THEN // handle error condition EXIT; END_IF // Determination of the file encoding udiCount := SCV.DecodeBOM(pbyData, udiSize, eEncoding=>eEncoding, eErrorID=>eErrorID); IF eErrorID <> 0 THEN // handle error condition EXIT; END_IF pbyData := pbyData + udiCount; udiSize := udiSize - udiCount; WHILE udiSize > 0 DO // Convert file content to UTF-8 and copy to Builder-Content udiCount := myBuilder.WriteMemSegment(pbyData, udiSize, eEncoding, eErrorID=>eErrorID); IF eErrorID <> 0 THEN // handle error condition EXIT; END_IF pbyData := ADR(abyBuffer); udiSize := TO_UDINT(SysFileRead(hFile, pbyData, XSIZEOF(abyBuffer), ADR(udiResult))); IF udiResult <> ERRORS.ERR_OK THEN // handle error condition EXIT; END_IF END_WHILE UNTIL TRUE END_REPEAT IF hFile <> RTS_INVALID_HANDLE THEN SysFileClose(hFile); hFile := RTS_INVALID_HANDLE; udiCount : UDINT; END_IF
VAR myRange : SBD.Range := (itfBuilder := myBuilder); diRune : STR.RUNE; eError : STR.ERROR; END_VAR myRange.Reset(); WHILE (diRune := myRange.GetNextRune(eErrorID=>eErrorID)) <> 0 AND_THEN eErrorID = 0 DO IF UC.IsSpace(diRune) THEN // The characters in the builder which are considered as spaces according to UNICODE are counted. udiCount := udiCount + 1; END_IF END_WHILE
Pour transmettre du contenu codé en UTF-8, aucun cache n'est nécessaire pour le codage de la conversion car les données sont déjà codées en UTF-8 dans le générateur. Par conséquent, le contenu d'un segment d'un générateur peut être envoyé directement, par exemple via une connexion TCP/IP
VAR itfConnection : NBS.IConnection; pbySegment : POINTER TO BYTE; udiSize : UDINT; eError : NBS.ERROR; END_VAR (* Provide an active itfConnection *) pbySegment:= myBuilder.GetFirstSegment(udiSize=>udiSize, eErrorID=>eErrorID); WHILE pbySegment <> 0 AND eErrorID = 0 DO eError := itfConnection.Write(pbySegment, udiSize, udiCount=>udiCount); IF eError <> 0 OR udiCount <> udiSize THEN // Handle Error EXIT; END_IF pbySegment := myBuilder.GetNextSegment(pbySegment, udiSize=>udiSize, eErrorID=>eErrorID); END_WHILE (* e.g. Close itfConnection *)
En collaboration avec StringPool
et RangePool
blocs fonctionnels
Le code suivant montre comment utiliser la dynamique IString
instances provenant d'un StringPool
. StringPool
ou un RangePool
est bien adapté pour être transmis aux parties subordonnées d'un programme. Ils peuvent ensuite créer les instances correspondantes à partir du pool correspondant selon les besoins, les utiliser, puis renvoyer ces instances dans le pool.
StringPool
et RangePool
VAR myString : GSB.UTF8String<256> := (sValue:=UTF8#'Was du nicht willst, dass man dir tu’, das füg auch keinem andern zu.'); myRange : STR.Range := (itfString:=myString); myStringPool : GSB.StringPool<(*udiStringSize*) 30, (*udiInitialCapacity*) 25, (*usiExtensionFactor*) 0>; myRangePool : GSB.RangePool<GSB.RANGE_TYPE.ISTRING, (*udiInitialCapacity*) 10, (*usiExtensionFactor*) 0>; diRune : STR.RUNE; eErrorID : STR.ERROR; itfSubString : STR.IString; liStart, liEnd : LINT; udiCount : UDINT; END_VAR myRange.Reset(); // Decompose myString into substrings and analyze them via a subroutine. WHILE (diRune:=myRange.GetNextRune(eErrorID=>eErrorID)) <> 0 AND eErrorID = 0 DO IF diRune = 16#2C (*,*) OR diRune = 16#2E (*.*) THEN itfSubString := myStringPool.GetString(); IF itfSubString = 0 THEN (* Handle Error *) EXIT; END_IF myString.ToIString(itfSubString, liStart+1, liEnd, eErrorID=>eErrorID); IF eErrorID <> 0 THEN (* Handle Error *) EXIT; END_IF // Analyse the substring and use pool's // Will release itfSubString udiCount := Analyse(itfSubString, myStringPool, myRangePool); (* ... Handle Result ... *) IF diRune = 16#2E (*.*) THEN EXIT; END_IF diRune:=myRange.GetNextRune(eErrorID=>eErrorID); IF diRune = 16#20 (* space *) AND eErrorID = 0 THEN liEnd := liEnd + 1; ELSE myRange.UngetLastRune(); END_IF liStart := liEnd + 1; END_IF liEnd := liEnd + 1; END_WHILE
Utilisation des catégories de caractères Unicode
La norme Unicode vise à capturer numériquement tous les caractères du monde entier et à décrire leurs propriétés. Pour ce faire, les personnages sont regroupés en groupes (catégories). Dans la bibliothèque Unicode, il existe des fonctions qui vérifient la catégorie d'un caractère. Ces fonctions renvoient TRUE
si le caractère transmis appartient à la catégorie correspondante ; sinon FALSE
est renvoyé.
Nom | Fonction |
---|---|
| Reconnaît les caractères de contrôle généraux |
| Reconnaît les lettres au sens large |
| Reconnaît les combinaisons de caractères, par exemple les caractères diacritiques |
| Reconnaît les chiffres décimaux |
| Reconnaît les lettres minuscules |
| Reconnaît les chiffres et les caractères qui s'appliquent aux nombres |
| Reconnaît uniquement les caractères imprimables (y compris les différents types d'espaces) |
| Reconnaît les lettres majuscules |
| Reconnaît les caractères de ponctuation |
| Reconnaît uniquement les caractères imprimables (ne prend en compte que |
| Reconnaît les lettres majuscules pour les en-têtes |
| Détecte les espaces de différentes largeurs, les sauts de ligne, etc. |
| Reconnaît les symboles dans un sens plus large, par exemple les symboles mathématiques et les symboles monétaires. |
Le contenu d'un IString
ou IBuilder
l'instance peut être analysée « caractère par caractère » à l'aide d'un bloc fonctionnel approprié de type Range
. Les fonctions de la bibliothèque Unicode peuvent être très utiles pour l'analyse
VAR myString : GSB.UTF8String<50> := (sValue:='Hello World!'); myBuilder : GSB.Builder<100, 0> := (itfString:=myString); mySRange : STR.Range := (itfString:=myString); myBRange : SBD.Range := (itfBuilder:=myBuilder); diSRune, diBRune : STR.RUNE; eErrorID : STR.ERROR; udiCount : UDINT; END_VAR WHILE (diSRune:=mySRange.GetNextRune(eErrorID=>eErrorID)) <> 0 AND eErrorID = 0 DO diBRune := myBRange.GetNextRune(); IF diSRune <> diBRune THEN (* Solle nicht vorkommen *) END_IF IF UC.IsSpace(diSrune) THEN udiCount := udiCount + 1; END_IF END_WHILE
Conversion de caractères
Convertir les lettres en majuscules (
UC.ToUpper
)Convertissez les lettres en minuscules (
UC.ToLower
)
VAR diRuneA, diRuneB : STR.RUNE; END_VAR diRuneA := 16#1F3; // U+01F3 = Dž diRuneB := UC.ToUpper(diRuneA); // U+01F1 = DZ diRuneA := UC.ToLower(diRuneB); // U+01F3 = Dž diRuneB := UC.ToTitle(diRuneA); // U+01F2 = Dz
Comparaison de chaînes
Sensibilisation aux majuscules
STR.Compare
)Pas de distinction majuscules/minuscules (
UC.EqualFold
)
VAR myFirstString : GSB.UTF8String<50> := (sValue:='test'); mySecondString : GSB.UTF8String<50> := (sValue:='Test'); myThirdString : GSB.UTF8String<50> := (sValue:='CoDeSys'); myFourthString : GSB.UTF8String<50> := (sValue:='CODESYS'); diResult : DINT; xEqual : BOOL; END_VAR /// Comparing two Strings lexicographically /// diResult = 1 --> myFirstString > mySecondString diResult := STR.Compare(myFirstString, mySecondString); /// Unicode defined simple case folding /// xEqual = TRUE --> myThirdString == myFourthString xEqual := UC.EqualFold( ADR(myThirdString.sValue), myThirdString.Len(), ADR(myFourthString.sValue), myFourthString.Len() );