gmslCharacterClass
The Character Service Class
Section titled “The Character Service Class”The service class Character processes character strings in various ways. Internally, this class assumes that all character strings are sequences of 8-bit unsigned bytes — i.e. with values in the range 0-255. Though not required all current implementations of this class use ASCII or UTF-8 variable length encoding and the descriptions of the methods assume that encoding.
Character.Compare Method
Section titled “Character.Compare Method”Declaration
<Method id="Compare" type="Integer" opcode="SCM.Character_Compare"> <Argument id="string1" type="String" status="ByVal" /> <Argument id="string2" type="String" status="ByVal" /> <Argument id="nCompare" type="Integer" status="ByVal" /></Method>The Character.Compare method does a case-insensitive comparison between two character vectors. This is a bounded comparison. The null-character is treated exactly like any other special character. If all characters within the specified range are identical, up to case distinctions, then the method returns a zero. If two characters within the specified range disagree, then the value of the character in the first vector minus that in the second vector is returned. The parameters are:
| Parameter | Description |
|---|---|
| string1 | contains the first character vector in the comparison. |
| string2 | contains the second character vector in the comparison. |
| nCompare | specifies the number of characters to be compared. |
Note that the characters within the strings are retrieved and compared as byte values in the range 0 to 255.
This method is used by the engine when it evaluates the relational arguments applied to the string type. The following code shows this as well.
string name1 = "Fred";string name2 = "Freddy";
Write.Line "Unit test for Character.Compare() Method"if(name1 != name2) Write.Line(name1 + " does not equal " + name2);Write.Line("Character.Compare(name1,name2,6) = " + Character.Compare(name1,name2,6));Write.Line("Character.Compare(name2,name1,6) = " + Character.Compare(name2,name1,6));Write.Line("Character.Compare(name1,name2,4) = " + Character.Compare(name1,name2,4));This code produces the following output.
Unit test for Character.Compare() MethodFred does not equal FreddyCharacter.Compare(name1,name2,6) = -68Character.Compare(name2,name1,6) = 68Character.Compare(name1,name2,4) = 0The inequality check fails because the comparison is done over the length of the longest string. The return value is the value in the first string minus the value in the second string as the above shows. Finally, limiting the comparison to the first four characters reports a zero difference.
Character.FindFirst Method
Section titled “Character.FindFirst Method”Declaration
<Method id="FindFirst" type="Integer" opcode="SCM.Character_FindFirst" > <Argument id="source" type="String" status="ByVal" /> <Argument id="iStart" type="integer" status="ByVal"/> <Argument id="substr" type="String" status="ByVal" /></Method>The Character.FindFirst method finds the first occurrence of substring in a string starting at the front of the string. All character comparisons are case insensitive. It returns when it finds a first occurrence or when it reaches the end of the string. Its parameters are:
| Parameter | Description |
|---|---|
| source | contains the string which is being searched. |
| iStart | specifies the position relative to zero of the start of the search. |
| substr | contains the substring which is being searched for. |
If all characters within the substring are identical to a sequence of characters within the string, up to case distinctions, then the method returns the position, relative to one, of the start of the matching sequence in the string. If no matching sequence can be located in the string, then a zero is returned. The following code shows this.
string input;int index;
Write.Line "Unit test for Character.FindFirst() Method"input = "\fkgtest\FmStocks\src\WebSite\t_begin_cart.asp";index = Character.FindFirst(input,0,"\");Write.Line("Index of \ in <" + input + "> is " + index);input = Character.Replace(input,"\","_");index = Character.FindFirst(input,0,"\");Write.Line("Index of \ in <" + input + "> is " + index);As the output of the code shows
Unit test for Character.FindFirst() MethodIndex of \ in <\fkgtest\FmStocks\src\WebSite\t_begin_cart.asp> is 1Index of \ in <_fkgtest_FmStocks_src_WebSite_t_begin_cart.asp> is 0The first backslash found in the string is the 1st character, but when backslashes are replaced by underscores it is zero since there are no more backslashes.
Character.HexiDecimal Method
Section titled “Character.HexiDecimal Method”The HexiDecimal method converts an unsigned integer value into a character string using hexadecimal, decimal, octal, or binary notation.
<Method id="HexiDecimal" type="string" opcode="SCM.Character_HexiDecimal" > <Argument id="iValue" type="Integer" status="ByVal" /> <Argument id="base" type="Integer" status="ByVal" /></Method>Note that the decimal, octal, and binary notation digits are simply subsets of the hexadecimal digits. Its parameters are:
| Parameter | Description |
|---|---|
| iValue | is the integer value to be converted. |
| base | is the base to be used — 2, 8, 10, or 16. |
The method returns the string containing the character representation. This can be seen in the following code.
void TestHexidecimal{ int value = 59;
Write.Line "Unit test for Character.HexiDecimal() Method" Write.Line("Representation of " + value + " as base 2 is: " + Character.HexiDecimal(value,2)); Write.Line("Representation of " + value + " as base 8 is: " + Character.HexiDecimal(value,8)); Write.Line("Representation of " + value + " as base 10 is: " + Character.HexiDecimal(value,10)); Write.Line("Representation of " + value + " as base 16 is: " + Character.HexiDecimal(value,16));}This method produces the following result.
Unit test for Character.HexiDecimal() MethodRepresentation of 59 as base 2 is: 111011Representation of 59 as base 8 is: 73Representation of 59 as base 10 is: 59Representation of 59 as base 16 is: 3bCharacter.Insert Method
Section titled “Character.Insert Method”The Insert method inserts a substring into a base string starting at a zero-based offset.
<Method id="Insert" type="string" opcode="SCM.Character_Insert" > <Argument id="source" type="String" status="ByVal" /> <Argument id="iStart" type="integer" status="ByVal"/> <Argument id="subStr" type="String" status="ByVal" /></Method>Its parameters are:
| Parameter | Description |
|---|---|
| source | base string that receives the substring |
| iStart | zero-based offset in the base string where the insertion is to begin |
| subStr | substring being inserted |
The method returns the result of the insertion. The following code shows how the ”?” characters in an SQL select string can be replaced by the ”@” character concatenated with an index value.
void TestInsert(){ string oldSQL = "select * from accounts where accountID < ? and FirstName like ?"; string newSQL = oldSQL; int index; int iPos; int lPos;
Write.Line "Unit test for Character.Insert() Method" iPos = 0; for(index = 0; index < 10; index = index + 1) { lPos = Character.FindFirst(newSQL,iPos,"?"); if(!lPos) break; iPos = iPos + lPos - 1; newSQL = Character.Remove(newSQL,iPos,1); newSQL = Character.Insert(newSQL,iPos,"@" + index); } Write.Line("OLD: " + oldSQL); Write.Line("NEW: " + newSQL);}The output of the method shows the original string and its revised version.
Unit test for Character.Insert() MethodOLD: select * from accounts where accountID < ? and FirstName like ?NEW: select * from accounts where accountID < @0 and FirstName like @1Character.Remove Method
Section titled “Character.Remove Method”The Remove method forms a new string by removing a specified number of characters from a string starting at a zero-based offset into the string.
<Method id="Remove" type="string" opcode="SCM.Character_Remove" > <Argument id="strValue" type="string" status="ByVal"/> <Argument id="iStart" type="integer" status="ByVal"/> <Argument id="length" type="integer" status="ByVal"/></Method>Its parameters are:
| Parameter | Description |
|---|---|
| strValue | contains the string from which characters are to be removed |
| iStart | specifies the zero-based offset of the first character to be removed. |
| length | specifies the number of characters to be removed. |
The method returns the newly formed string. The code below shows how it can be used to remove certain name-value pairs from a connection string.
void TestRemove(){ int iPos; int semi; string dbs = "UID=stocks_login;PWD=password;Database=stocks;" + "Server=GMI-CS-01.gmi.local;Driver={SQL Server};" + "DSN='';"; string connect = dbs;
Write.Line "Unit test for Character.Remove() Method" iPos = Character.FindFirst(connect,0,"Driver="); if(iPos) { iPos = iPos - 1; semi = Character.FindFirst(connect,iPos,";"); if(semi) { connect = Character.Remove(connect,iPos,semi); } } iPos = Character.FindFirst(connect,0,"DSN="); if(iPos) { iPos = iPos - 1; semi = Character.FindFirst(connect,iPos,";"); if(semi) { connect = Character.Remove(connect,iPos,semi); } } Write.Line("OLD: " + dbs); Write.Line("NEW: " + connect);}The output of the method shows the connection string before and after the removal.
Unit test for Character.Remove() MethodOLD: UID=stocks_login;PWD=password;Database=stocks;Server=GMI-CS-01.gmi.local;Driver={SQL Server};DSN='';NEW: UID=stocks_login;PWD=password;Database=stocks;Server=GMI-CS-01.gmi.local;Character.Replace Method
Section titled “Character.Replace Method”The Replace method forms a new string from an existing one in which all occurrences of a specified substring have been replace by a new substring.
<Method id="Replace" type="string" opcode="SCM.Character_Replace" > <Argument id="source" type="string" status="ByVal"/> <Argument id="oldStr" type="integer" status="ByVal"/> <Argument id="newStr" type="integer" status="ByVal"/></Method>Its parameters are:
| Parameter | Description |
|---|---|
| source | contains the original string to be modified. |
| oldStr | contains the substring whose occurrences are to be replaced. |
| newStr | contains the replacing substring. |
The method returns the new string. The code below shows examples of this.
void TestReplace{ string input; string result;
Write.Line "Unit test for Character.Replace() Method" input = "\Manual\FmStocks\WebSite\t_begin_cart.asp"; result = Character.Replace(input,"\","_"); Write.Line("Input<" + input + "> result<" + result + ">"); input = "some sort of text/string right here"; result = Character.Replace(input,"right","in"); Write.Line("Input<" + input + "> result<" + result + ">"); input = "Mary had a little lamb."; result = Character.Replace(input,"lamb","tiger"); Write.Line("Input<" + input + "> result<" + result + ">"); input = "Good dog, good dog"; result = Character.Replace(input, "Good","Bad"); Write.Line("Input<" + input + "> result<" + result + ">");}The output of the method shows both the input string and the result string.
Unit test for Character.Replace() MethodInput<\Manual\FmStocks\WebSite\t_begin_cart.asp> result<_Manual_FmStocks_WebSite_t_begin_cart.asp>Input<some sort of text/string right here> result<some sort of text/string in here>Input<Mary had a little lamb.> result<Mary had a little tiger.>Input<Good dog, good dog> result<Bad dog, Bad dog>Character.Substr Method
Section titled “Character.Substr Method”The Substr method forms a new string by extracting a substring from a supplied one.
<Method id="Substr" type="string" opcode="SCM.Character_Substr" > <Argument id="strValue" type="string" status="ByVal"/> <Argument id="iStart" type="integer" status="ByVal"/> <Argument id="length" type="integer" status="ByVal"/></Method>Its parameters are:
| Parameter | Description |
|---|---|
| strValue | is the supplied source string. |
| iStart | is the starting offset in the source string, relative to zero, of the start of the substring. |
| length | is the desired length of the substring. If it is negative or zero, then it is added to the length of the source string to determine its final value. |
The method returns the new string. The following code shows how the method is used to extract the actual reference files from a project file.
void TestSubstr(){ int vbpRoot; tInfoFile vbpInfo; Handle textStream; int rai; int length; string record; int nRecord; int curRecord; int nString; string refName;
Write.Line "Unit test for Character.Substr() Method" Store.Open("\Manual\FmStocks\usr\FmStocks.vbi",StorageUnit.USER,0); vbpRoot = Store.FindVector("\Manual\FmStocks\src\FMStocks_DB.vbp",0); vbpInfo = Store.GetVector(vbpRoot); textStream = Text.Open(Store.GetHandle(),vbpInfo.textBase); nRecord = Text.Maximum(textStream); curRecord = 0; while(curRecord < nRecord) { curRecord = curRecord + 1; Text.Position(textStream,curRecord); record = Text.Access(textStream, length, rai, 0); if(length > 12) { if(Character.Compare(record,"Reference=",10) == 0) { nString = length - 10; refName = Character.Substr(record,10,nString); Write.Line("Found Reference: " + refName); } } } Store.Close();}The actual reference names found are as follows
Unit test for Character.Substr() MethodFound Reference: *\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\WINDOWS\system32\stdole2.tlb#OLE AutomationFound Reference: *\G{00000205-0000-0010-8000-00AA006D2EA4}#2.5#0#..\..\..\..\..\Program Files\Common Files\system\ado\msado25.tlb#Microsoft ActiveX Data Objects 2.5 LibraryFound Reference: *\G{2A005C00-A5DE-11CF-9E66-00AA00A3F464}#1.0#0#..\..\..\..\..\WINDOWS\system32\COMSVCS.DLL#COM+ Services Type LibraryCharacter.ToLower Method
Section titled “Character.ToLower Method”The ToLower method forces the case of any alphabetic characters contained in a specified string to lower-case. Characters that are not alphabetic or that already have lower-case are not changed.
<Method id="ToLower" type="string" opcode="SCM.Character_Tolower" > <Argument id="strValue" type="string" status="ByVal"/> <Argument id="iStart" type="integer" status="ByVal"/> <Argument id="length" type="integer" status="ByVal"/></Method>Its parameters are:
| Parameter | Description |
|---|---|
| strValue | is the string containing the value to be converted. |
| iStart | is the starting relative to zero of the characters to be converted. |
| length | is the number of characters to be considered for conversion. |
The code below shows this.
void TestTolower(){ string input; string output;
Write.Line "Unit test for Character.Tolower() Method" input = "abcdefg" output = Character.Toupper(input,0,2); Write.Line("toupper(""" + input + """,0,2) = " + output) input = Character.Tolower(output,1,1) Write.Line("tolower(""" + output + """,1,1) = " + input)}The first call sets the first two characters to upper case and then the second call sets the second character back to lower case.
Unit test for Character.Tolower() Methodtoupper("abcdefg",0,2) = ABcdefgtolower("ABcdefg",1,1) = AbcdefgCharacter.ToUpper Method
Section titled “Character.ToUpper Method”The ToUpper method forces the case of any alphabetic characters contained in a specified string to upper-case. Characters that are not alphabetic or that already have upper-case are not changed.
<Method id="ToUpper" type="string" opcode="SCM.Character_Toupper" > <Argument id="strValue" type="string" status="ByVal"/> <Argument id="iStart" type="integer" status="ByVal"/> <Argument id="length" type="integer" status="ByVal"/></Method>Its parameters are:
| Parameter | Description |
|---|---|
| strValue | is the string containing the value to be converted. |
| iStart | is the starting relative to zero of the characters to be converted. |
| length | is the number of characters to be considered for conversion. |
The code below shows this.
void TestToupper(){ string input; string output;
Write.Line "Unit test for Character.Toupper() Method" input = "abcdefg" output = Character.Toupper(input,0,2); Write.Line("toupper(""" + input + """,0,2) = " + output) input = Character.Tolower(output,1,1) Write.Line("tolower(""" + output + """,1,1) = " + input)}The first call sets the first two characters to upper case and then the second call sets the second character back to lower case.
Unit test for Character.Toupper() Methodtoupper("abcdefg",0,2) = ABcdefgtolower("ABcdefg",1,1) = AbcdefgCharacter.Unpack Method
Section titled “Character.Unpack Method”The Unpack method extracts a specified string from a set of strings packed into a single string instance.
<Method id="Unpack" type="string" opcode="SCM.Character_Unpack" > <Argument id="strValue" type="string" status="ByVal"/> <Argument id="iStart" type="integer" status="ByVal"/></Method>Its parameters are:
| Parameter | Description |
|---|---|
| strValue | contains the packed set of strings. |
| iStart | is the index relative to one of the desired string. |
The method returns the unpacked string. One of the packed string sets used by gmBasic contains the handler and argument class names for an event. The code here extracts these for the individual events in the ADODB.ConnectionEvents class.
void TestUnpack(){ int classRoot; int compRoot; tLibComp libComp; int evtType; string evtInfo;
Write.Line "Unit test for Character.Unpack() Method" Store.Open("\Manual\FmStocks\usr\FmStocks.vbi",StorageUnit.USER,0); classRoot = Symbol.FindIdentifier("ADODB.ConnectionEvents" ,0); for(compRoot = Store.GetFirst(classRoot); compRoot != 0; compRoot = Store.GetNext(compRoot)) { libComp = Store.GetVector(compRoot); if(libComp.refType == ComponentType.EVENT) { evtType = libComp.type; if(evtType > Defines.OPC_MAXIMUM) { evtInfo = Store.GetString(evtType); Write.Line("Event components for:" + Store.GetName(compRoot)); Write.Line(" Handler:" + Character.Unpack(evtInfo,0)); Write.Line(" Args:" + Character.Unpack(evtInfo,1)); } } } Store.Close();}The result of the scan and unpacking is shown below.
Unit test for Character.Unpack() MethodEvent components for:InfoMessage Handler:ADODB.ConnectionEvents_InfoMessageEventHandler Args:ADODB.ConnectionEvents_InfoMessageEventEvent components for:BeginTransComplete Handler:ADODB.ConnectionEvents_BeginTransCompleteEventHandler Args:ADODB.ConnectionEvents_BeginTransCompleteEventEvent components for:CommitTransComplete Handler:ADODB.ConnectionEvents_CommitTransCompleteEventHandler Args:ADODB.ConnectionEvents_CommitTransCompleteEventEvent components for:RollbackTransComplete Handler:ADODB.ConnectionEvents_RollbackTransCompleteEventHandler Args:ADODB.ConnectionEvents_RollbackTransCompleteEventEvent components for:WillExecute Handler:ADODB.ConnectionEvents_WillExecuteEventHandler Args:ADODB.ConnectionEvents_WillExecuteEventEvent components for:ExecuteComplete Handler:ADODB.ConnectionEvents_ExecuteCompleteEventHandler Args:ADODB.ConnectionEvents_ExecuteCompleteEventEvent components for:WillConnect Handler:ADODB.ConnectionEvents_WillConnectEventHandler Args:ADODB.ConnectionEvents_WillConnectEventEvent components for:ConnectComplete Handler:ADODB.ConnectionEvents_ConnectCompleteEventHandler Args:ADODB.ConnectionEvents_ConnectCompleteEventEvent components for:Disconnect Handler:ADODB.ConnectionEvents_DisconnectEventHandler Args:ADODB.ConnectionEvents_DisconnectEvent