IBM Doors DXL: Die fehlenden Stringfunktionen / The missing String functions

Problem

DXL besitzt leider nur sehr wenige Stringfunktionen. Man muss sich für einfache Stringmanipulationen eine eigene Bibliothek bauen.
DXL consists only of a very less number of string functions. For this purpose you have to implement your own library.

Ansatz – Approach

Ich habe die wichtigsten Stringfunktionen aus JAVA/PHP in eine Bibliothek ausgelagert, die ich im Kopf meiner DXL Skripte einbinde…
I have implemented a library with the most important string function from JAVA/PHP, which can be included in the head of DXL scripts…

Lösung – Solution

Das Einbinden erfolgt z.B. mit

#include "\\\\der\\netzwerk\\pfad\\strings.inc";

wobei oben ein Netzwerkpfad genutzt wird. Ohne Pfadangebe muss die Datei direkt im dxl-Verzeichnis der Installation des Doors-Clients liegen.


/******************************
 * String funktionen
 * @Author: Bjoern Karpenstein 
 * @Datum:  2012-11-06 
 ******************************/
// Zweistellige Ganzzahl mit fuehrender Null
string getZeroPrefixedInt(int i)
{
	string s = i "";
	if (i < 10) s = "0" s "";
	return s;
}
 
// Gib datum und Uhrzeit als String
string getDateTime()
{
	string dateTimeString = "";
	int now = intOf(dateAndTime(today));
	Date d = dateOnly(today);
	int day = intOf(date(stringOf(d)));
	int diff = now-day;
	int hours = diff / 3600;
	int mins = (diff - (3600 * hours)) / 60;
	int secs = diff - (hours * 3600) - (mins * 60);

	return "<td>" stringOf(today, "yyyy-MM-dd") "</td><td>" getZeroPrefixedInt(hours) ":" getZeroPrefixedInt(mins) ":" getZeroPrefixedInt(secs) "</td>";
} 

// Gib datum und Uhrzeit als String für Dateien
string getFileTimestamp()
{
	string dateTimeString = "";
	int now = intOf(dateAndTime(today));
	Date d = dateOnly(today);
	int day = intOf(date(stringOf(d)));
	int diff = now-day;
	int hours = diff / 3600;
	int mins = (diff - (3600 * hours)) / 60;
	int secs = diff - (hours * 3600) - (mins * 60);

	return stringOf(today, "yyyy-MM-dd") "_" getZeroPrefixedInt(hours) "_" getZeroPrefixedInt(mins) "_" getZeroPrefixedInt(secs) "";
} 

// Gib datum und Uhrzeit als String für Dateien
string getAvitumTimestamp()
{
	string dateTimeString = "";
	int now = intOf(dateAndTime(today));
	Date d = dateOnly(today);
	int day = intOf(date(stringOf(d)));
	int diff = now-day;
	int hours = diff / 3600;
	int mins = (diff - (3600 * hours)) / 60;
	int secs = diff - (hours * 3600) - (mins * 60);

	return stringOf(today, "yyyy-MM-dd") " " getZeroPrefixedInt(hours) ":" getZeroPrefixedInt(mins) ":" getZeroPrefixedInt(secs) "";
} 

// Gib datum und Uhrzeit als String für Dateien
string getAvitumDate(Date d)
{
	return stringOf(d, "yyyy-MM-dd");
} 
 
// Gibt die Groesse eines Arrays zurück
int getArraySize(Array a){
    int size = 0;
    while( !null(get(a, size, 0) ) )
        size++;
    return size;
}

// Fuegt einen String in ein Array hinzu
void addArrayString(Array a, string str)
{
    int array_index = getArraySize(a);

    put(a, str, array_index, 0);
}

// Gibt den String im Array zurueck
string getArrayString(Array a, int index)
{
    return (string get(a, index, 0));
}

// Setze String für vorhandene Array-Position
void setArrayString(Array a, int change_index, string newString)
{
	put(a, newString, change_index, 0);
}

// Der notorische Sortieralgorithmus für Arme
void bubbleSort(Array a, bool asc)
{
	int size=getArraySize(a);

	int i=0;
	int j=0;
	for(i=0; i<size; i++)
	{
		for(j=0;j<size; j++)
		{
			bool sortierKriterium=asc?getArrayString(a,i)<getArrayString(a,j):getArrayString(a,i)>getArrayString(a,j);
			if(sortierKriterium)
			{
				// Tauschen
				string swapRAM=getArrayString(a,j);
				setArrayString(a, j, getArrayString(a,i));
				setArrayString(a, i, swapRAM);
				
			}
		}
	}	
}


// Zum analysieren eines Strings auf seine Ascii Zeichen
string giveMeAscii(string withoutAscii)
{
	string myAsciiString = "";
	for (i=0; i<length(withoutAscii); i++)
	{  
   		char c = withoutAscii[i];            // <<<--- here you go, get the char
   		int ascii = intOf(c);        // <<<--- convert char to Ascii Code
   		myAsciiString = myAsciiString "" c "[" ascii "]";
	}
	
	return myAsciiString;
}

// Erstellt z.B. einen CSV String 
string joinString(string joiner, Array str_array)
{
    Buffer joined = create;
    int array_index = 0;

    joined += "";

    for(array_index = 0; array_index < getArraySize(str_array); array_index++)
    {
        joined += getArrayString(str_array, array_index);
        if( array_index + 1 < getArraySize(str_array) )
            joined += joiner;
    }

    return stringOf(joined)
}

// Zerhackt einen String nach einem definierten Zeichen und gibt ihn als Array zurueck
Array split(string splitter, string str)
{
    Array tokens = create(1, 1);
    Buffer buf = create;
    int str_index;

    buf = "";

    for(str_index = 0; str_index < length(str); str_index++){
        if( str[str_index:str_index] == splitter ){
            addArrayString(tokens, stringOf(buf));
            buf = "";
        }else{
            buf += str[str_index:str_index];
        }
    }
    addArrayString(tokens, stringOf(buf));

    delete buf;
    return tokens;
}

// If the string starts with another string
bool startsWith(string theString, string startsWithWhat)
{
	if(length(theString)<length(startsWithWhat))
	{
		return false;
	}
	return theString[0:length(startsWithWhat)-1]==startsWithWhat
}

// Zaehlt wie oft Skip-Listen-Keys mit einem Teilstring anfangen
int countKeysThatStartWith(string prefixPfad, Skip skipListeToLookForStart)
{
	int countedKeys=0;
	for myIterator in skipListeToLookForStart do 
  	{
    	string keyValue = (string key(skipListeToLookForStart));
    	
    	string currentPfad = "";
    	if(find(skipListeToLookForStart, keyValue, currentPfad))
    	{
	    	if(startsWith( keyValue, prefixPfad))
	    	{
		    		countedKeys++;
	    	}
  		}
  	}
  	
  	return countedKeys;
}

// A String Replace function because there is nothing in the standard
string replace (string sSource, string sSearch, string sReplace) 
{
    int iLen = length sSource
    if (iLen == 0) return ""
    
    int iLenSearch = length(sSearch)
    
    if (iLenSearch == 0) 
    { 
        print "Parameter error", "in strings.inc/replace: search string must not be empty"
        return "" 
    }
    
    // read the first char for latter comparison -> speed optimization
    char firstChar = sSearch[0]
    
    Buffer s = create() 
    int pos = 0, d1,d2;    
    int i
    
    while (pos < iLen) { 
        char ch = sSource[pos]; 
        bool found = true
        
        if (ch != firstChar) {pos ++; s+= ch; continue}
        for (i = 1; i < iLenSearch; i++) 
           if (sSource[pos+i] != sSearch[i]) { found = false; break }
        if (!found) {pos++; s+= ch; continue}
        s += sReplace
        pos += iLenSearch
    }
    
    string result = stringOf s
    delete s
    return result
}

// Backslashes maskieren und LF durch <br> ersetzen
string mask(string toMask)
{
	string backslashStrip   = replace(toMask, "\\", "\\\\");
	string doubleQuoteStrip = replace(backslashStrip, "\"", "\\\"");
	string replaceLFWithBRs = replace(doubleQuoteStrip,"\n","<br/>");		
	// string replaceLFWithBRs = replace(doubleQuoteStrip,"\012","<br/>");		
	//return replace(replaceLFWithBRs, "\015", "");
	return replaceLFWithBRs;
}

// Backslashes maskieren und LF durch <br> ersetzen
string unmask(string toUnMask)
{
	string backslashStrip = replace(toUnMask, "\\\\","\\");
	string doubleQuoteStrip = replace(backslashStrip, "\\\"","\"");
	
	// wenn da <br/> drinne sind ignoriere 13 oder 10 
	
	string machLFWeg = replace(doubleQuoteStrip,"<br/>","\n");
	
	// string machLFWeg = replace(doubleQuoteStrip,"<br/>","\012") <- 10 wech;
	// return replace(machLFWeg, "\015", "") <- 13 wech;
	
	return machLFWeg;
}

// LTRIM gibts wohl nicht
string leftTrim(string einString)
{
   int dieLetztePosition=-1;
   for (x=0; x<length(einString); x++)
   {
      if( einString[x:x] != " " )
      {
        dieLetztePosition=x;
         break;
      }
   }

   return einString[dieLetztePosition:];
}

// RTRIM gibts wohl nicht
string rightTrim(string einString)
{
   int dieLetztePosition=-1;
   for (x=length(einString)-1; x>=0; x--)
   {
      if( einString[x:x] != " " )
      {
        dieLetztePosition=x;
         break;
      }
   }

   return einString[0:dieLetztePosition];
}

// Gibt die erste Position eines Strings zurück
int indexOf(string testString, string part)
{
	Buffer buf = create()
	buf = testString
	int index = 0
	while(true)
	{
	    index = contains(buf, part, index)
	    if(0 <= index)
	    {
	        return index;
	        index += length(part)
	    }
	    else { return -1; break }
	}
	delete(buf)
}

// Gibt die erste Position eines zeichens zurueck
int indexOfChar(string derString, string dasZeichen)
{
   int dieLetztePosition=-1;
   
   for (x=0; x<length(derString)-1;x++)
   {
      if( derString[x:x] "" == dasZeichen "")
      {
        dieLetztePosition=x;
         break;
      }
   }

   return dieLetztePosition;
}

// Gibt die Auftretens-Haeufigkeit eines Characters zurueck
int getCharOccurrence(string characterChain, string charToCheckFor)
{
   int countChars=0;

   for (x=0; x<length(characterChain);x++)
   {
      if( characterChain[x:x] "" == charToCheckFor"")
      {
		countChars++;
      }
   }
   return countChars;
}

// Gibt die erste Position eines zeichens zurueck
int indexOfFrom(string derString, string dasZeichen, int n)
{
   int dieLetztePosition=-1;
   int zeichenCount=0;
   
   for (x=0; x<length(derString)-1;x++)
   {
      if( derString[x:x] "" == dasZeichen "")
      {
      	zeichenCount++;
      	
      	if(zeichenCount!=n)
      	{
      		continue;
      	}
      	
        dieLetztePosition=x;
        break;
      }
   }

   return dieLetztePosition;
}

// Gibt die letzte Position eines zeichens zurueck
int lastIndexOf(string derString, string dasZeichen)
{
   int dieLetztePosition=-1;
   
   for (x=length(derString)-1; x>=0; x--)
   {
      if( derString[x:x] "" == dasZeichen "")
      {
        dieLetztePosition=x;
         break;
      }
   }

   return dieLetztePosition;
}

// Alle Zeichen links und rechts abschneiden
string trim(string einString)
{
	return leftTrim(rightTrim(einString)) "";
}

// Ersetze Zeilen in einem String
string replaceLines(string content, int startLine, int targetLine, string toReplace)
{
	string newContent="";
	Array stringLines = split("\n", content);
	int stringLineCount=getArraySize(stringLines);
	
	if(startLine>targetLine)
	{
		return "replaceLines: the start index is bigger than the target index";
	}
	
	if(startLine==-1||targetLine==-1)
	{
		return "replaceLines: Select start and target index bigger or equal to zero";
	}
	
	int i=0;
	for(i=0;i<stringLineCount;i++)
	{
		string stringZeile=getArrayString(stringLines,i);	
		
		if(i>=startLine&&i<=targetLine)
		{
			if(i==startLine)
			{
				newContent=newContent "" toReplace "\n";
			}
		}
		else
		{
			newContent=newContent "" stringZeile "\n";
		}

	}
	
	return newContent;
}