CRuntimeJavalike - StringJc - Stringverarbeitung

CRuntimeJavalike - StringJc - Stringverarbeitung

Inhalt


1 Stringverarbeitung

Topic:.String_Jc.

Die String-Verarbeitung in CRuntimeJavalike lehnt sich an Java-Konzepte an, ist aber auf die Verwendung in der schnellen Echtzeitverarbeitung orientiert. Die Zeichenkettenverarbeitung ist auch in Echtzeit-Anwendungen wichtig, beispielsweise für

Die maximale Länge von Strings ist in CRuntimeJavalike auf einen Wert von ca. 16000 Zeichen begrenzt, gegebenenfalls weniger entsprechend bereitgestellten Puffer-Größen. Komplexe Stringverarbeitungen mit langen Zeichenkette (mehrere zig Kilobyte) sind für Echtzeitsysteme eher nicht zu erwarten. Man sollte für Echtzeitanwendungen an die Kopplung verschiedener Ablaufsysteme eventuell auf mehreren Prozessoren oder in verschiedenen Threads eines Prozessors denken und komplexer Stringverarbeitungsroutinen direkt in Java programmieren.

Die Stringverarbeitung in der CRuntimeJavalike funktioniert in reinem C und bietet dort bessere und insbesondere sichere Möglichkeiten als in C sonst üblich. Wichtig ist weiterhin, dass es Strategien der threadsicheren Puffer-Bereitstellung gibt. Es erfolgt auch eine Adaption für C++. Man kann dann wie in C++ gewohnt Strings einfach mit den Operator + verketten und automatisch konvertieren, vergleichbar mit dem was andere String-Klassen in C++ bieten. Dabei wird aber immer die Kompatibilität mit in C geschriebenen Programmteilen gewahrt. Reine C++-Objectfiles lassen sich mit reinen C-Objectfiles zusammenlinken. Das dürfte ein Alleinstellungsmerkmal sein. Typische C++-Stringklassen lassen sich sonst nicht für C anwenden, der C-Programmierer wird mit sprintf & co. allein gelassen.


1.1 Vergleich mit der konventionellen Stringverarbeitung in C und mit Java

Topic:.String_Jc.CvsJava.

In C gängig für solche Dinge ist die Verwendung von sprintf:

 char buffer[100];
 sprintf(buffer,"Ausgabe wert=%i, text=%s\n", value, sText);

sprintf hat ein Problem, ein möglicher unkalkulierter Bufferüberlauf. Was ist im obigen Beispiel, wenn der sText mehr als 70 Zeichen umfasst, und die Zahl auch sehr groß ist. Das wird durch nichts kontrolliert außer durch manuelle Längentests.

In Java sieht das vergleichbare Problem wie folgt aus:

 String output = "Ausgabe wert=" + value + ", text=" + sText;

Vom Ablauf im Maschinencode muss in etwa das gleiche passieren: In einem Buffer werden die Zeichenketten zusammenkopiert, Zahlen müssen konvertiert werden. Der Puffer wird in Java dynamisch allokiert und vom Garbage-Collector wieder entsorgt, wenn der Ergebnisstring nicht mehr referenziert wird. Für den Anwender ist das einfach. Für schnelle Echtzeitverarbeitung ist ein dynamisch allokierter Puffer weniger geeignet.

In Java hat man auch die Möglichkeit, einen StringBuffer oder StringBuilder zu benutzen. Der Vorteil ist, ein einmalig allokierter Puffer kann wiederverwendet werden. Eine Doppel-Verwendung muss dabei aber geeignet ausgeschlossen werden. Auch in Java spart man sich hier das dynamische Allokieren und entlastet gegebenenfalls die Rechenzeit, beispielsweise bei Operationen der Textverarbeitung in einer Schleife.

Als letztes gibt es in Java auch eine Art printf, in Form String.format(formatString, arguments ...). Diese Schreibweise ist an C-Gewohnheiten angelehnt, funktioniert intern aber ganz anders.


1.2 Probleme der Stringverarbeitung in C

Topic:.String_Jc.StringProblemsC.

Die Stringverarbeitung in C auf Basis 0-terminierter Zeichenketten, printf usw. ist ein Standard aus den 70/80-ger Jahren, als Programmierung noch 'handgeschrieben und handverlesen' wurde. Man hat eher nebenbei an die Maschinencodierung gedacht, Programme waren nicht zu komplex und daher manuell sorgfältig testbar. Folgende Probleme können auftreten:


1.3 Probleme bei der Stringverarbeitung in C++-Libraries

Topic:.String_Jc.stdCppLibs.

Jede C++-Library kommt mit einer eigenen String-class. Es gibt auch einen Quasi-Standard in der STL (standard Template Library). Diese Lösungen sind insoweit nicht für embedded-realtime tauglich, weil meist extensiv dynamischer Speicher verwendet wird. Es sind C++-Klassen typisch für PC-Applikationen. C-orientierte C++-Entwickler verwenden meist dennoch sprintf & co.

In den Anfängen von C++ hat man sich eine neue Variante der Schreibweise des Streamings, insbesondere anwendbar für die Textverarbeitung überlegt:

 cout << "text" << value;

Diese Schreibweise ist eher besser dafür geeignet, zu demonstrieren wie gut man Operatoren überladen kann. Wirklich hilfreich ist sie nicht.


1.4 Antwort auf die Probleme der Stringverarbeitung in CRuntimeJavalike

Topic:.String_Jc..

Das Problem der 0-terminierten Zeichenketten wird häufig gelöst mit Speicherung der Länge des Strings als erstes Element. Damit kann man aber keine Teilzeichenketten durch einfache Zeigerung bilden, sondern man braucht dazu wieder einen eigenen Puffer. In der Jc-Lib ist dagegen eine struct StringJc definiert, die einen Zeiger char const* und die Länge enthält. Die Struktur ist so gestaltet, dass sie bei dem jeweiligen Compiler als Returnwert in Register passt. Diese Struktur ist von einem Typ OS_ValuePtr abgeleitet, die compiler- und zielsystemspezifisch in dem Basis-Headerfile os_types_def definiert ist.

Mit einer Instanz StringJc kann man konstante Strings mit größerer Länge an beliebigen Speicherorten (auch als Teilzeichenkette) referenzieren. Da die Instanz in zwei Prozessorregister passt, wird eine solche Instanz auch meist Subroutinen als Parameter über call per value übergeben und als Instanz im Stack gehalten. Aber auch die Verwendung als Element einer class oder struct von dauerhaften Daten ist möglich. Die String-Referenz StringJc kann auch die Rolle einer sogenannten enhanced Reference spielen. Eine enhanced Reference enthält einen Index auf eine Verweisliste in einem Bereich in einem Heap, genutzt für das Blockheap-Konzept der CRuntimeJavalike. Unabhängig davon ist die struct StringJc und einfache aber wesentliche Definitionen und Methoden aber bereits für systemnahe Routinen (OSAL) definiert. Damit ist die Grundeigenschaft der Zeigerung von char const* mit angegebener Länge bereits auf dieser Ebene nutzbar, ohne das man sich bereits im Jc-Konzept bewegt.

Instanzen von StringJc sind wie ein String in Java für konstante Zeichenketten gedacht. Um Zeichenketten aufzubereiten, gibt es den StringBufferJc. Dieser müsste eigentlich StringBuilderJc heißen, aber die class StringBuilder ist in Java erst mit der Version 5 herausgekommen, da gab es die struct StringBufferJc bereits. Der Unterschied ist die Threadsicherheit. StringBufferJc ist nicht threadsicher, sondern muss außen gesichert werden, wie StringBuilder in Java. Das ist rechenzeiteffektiver. Die Bildung von Strings mit Hilfe eines StringBuffer erfolgt in der Jc-Lib adäquat wie in Java. Es gibt aber einige C-Besonderheiten wie die Möglichkeit, Puffer und Kopfstruktur in einem gemeinsamen Speicherbereich unterzubringen.

Für die Verkettung von Strings (Aufbereitung) gibt es eine struct StringBufferJc. Diese enthält ähnlich wie StringJc den Zeiger, diesmal als char* auf den Puffer, die maximale Pufferlänge, die aktuelle Länge und Flag-Bits. Optional kann der Puffer sich sofort an diese Basisdaten anschließen oder an beliebiger anderer Stelle als char*-Array stehen. Ersteres hat den Vorteil, dass man nicht zwei Instanzen hat. Für die String-Verarbeitung in C soll der StringBufferJc direkt genutzt werden. Die Konkatierung ist ein Aufruf von append...() nacheinander mit den einzelnen Argumenten. In Java2C werden die Java-String-Operationen auf solche Operationen direkt umgewandet.

Für die manuelle Programmierung in C++ ist es aber interessant, die Leistungsfähigkeit des C++-Compilers für den Subroutinenaufrufen von Operatoren ausgelöst zu verwenden (Konzept der überladenen Operatoren). Damit ist die Schreibweise ähnlich wie in Java eine Konkatierung mit einem '+', die dann auf C umgesetzt die entsprechenden append-Methoden aufruft. Am Anfang einer Stringverkettung steht aber immer die Bereitstellung des entsprechenden zunächst leeren StringBufferJc, siehe Beispiele. Damit hat der Programmierer es selbst in der Hand, wie der Puffer beschafft wird. Die entsprechenden Aufrufe sind relativ einfach.

Für den Ort der Speicherung der Strings gilt folgendes:

Ein String im Threadcontext-Puffer darf allerdings nicht dauerhaft referenziert werden. Der rückgegebene String ist nur zur direkten Weiterverwendung (Kopieren) bestimmt. Das sind allerdings auch die typischsten Anwendungsfälle. Java2C erkennt den Fall der Referenzierung und generiert dann einen dynamisch angelegten neuen Puffer. Die oft direkt in C programmierten Routinen, die den String produzieren, müssen aber diese Bedingungen nicht beachten und also keine dynamische Speicherverwaltung vorraussetzen.


1.5 Beispiele für Stringverarbeitung in CRuntimeJavalike

Topic:.String_Jc.exam.

.


1.5.1 Einfache Angabe von konstanten String-Literalen

Topic:.String_Jc.exam.s0_StringJc.

Im Standard-C ist es sehr einfach, eine Routine die etwa so definiert ist

 void exampleRoutine(const char* name, int value);

mit einer konstanten Zeichenkette zu rufen:

 exampleRoutine("TheName", 234);

Wenn aber eine solche Routine aus einem komplexeren Kontext aufgerufen wird, bei dem die Zeichenkette vorher zusammengestellt wird, dann hat man den 0-terminierten String mit allen seinen Nachteilen. Besser ist es, den Typ StringJc bereits in Softwareebenen des Basis- oder Betriebssystems zu verwenden. Daher ist der Typ StringJc auch bereits im Headerfile fw_String.h vor dem Jc-Konzept definiert.

 void exampleRoutine(StringJc name, int value);

Eine konstante Zeichenkette muss beim Aufruf dennoch möglichst einfach angegeben werden können. Es gibt dafür zwei Wege:

 const StringJc sName = CONST_StringJc("TheName");
 ...
 exampleRoutine(sName, 234);

Dieser Fall ist geeignet auch für verschiedene Spracheinstellungen. Die Zeichenkette wird irgendwo außerhalb als Konstante definiert und beim Aufruf einfach benutzt. Maschinentechnisch werden zwei Konstanten gebildet: Zum Einen das Stringliteral selbst (wie im Standard-C, auch hier hantiert man maschinentechnisch mit einem Zeiger, auf eine Konstante), zum Anderen werden noch die Bytes für den StringJc, bestehend aus Zeiger und Länge, benötigt. Programmtechnisch hat man zwei Stellen zu beachten, ungünstig für schnelle Programmierrung.

Für die direkte Angabe eines Stringliterals ist die zweite Variante geeignet:

 exampleRoutine(s0_StringJc("TheName"), 234);

Programmtechnisch ist gegenüber der Standard-C Variante etwas mehr Schreibaufwand nötig: s0_StringJc(...), aber mehr nicht. Maschinentechnisch ist das etwas unoptimaler, statt einer einfachen Übergabe des konstanten Zeigers auf das Stringliteral (Standard-C) wird hier eine echte Subroutine gerufen. Es lässt sich auch nicht als Makro organisieren. Die Subroutine s0_StringJc(...) übernimmt eine 0-terminierte Zeichenkette, ermittelt deren Länge und bildet eine StringJc-Instanz als Returnwert. Diese wird als Parameter per Value weitergeben. Das geschieht zwar speichereffektiv durch Übergabe in Registern. Insgesamt gesehen handelt es sich aber maschinentechnisch nur um den Aufwand eines zusätzlichen Call und dem Aufruf von strlen(), der aber dafür zumeist bei der Verarbeitung eingespart wird (weil, Stringlänge wird schon fertig übergeben). Wenn man unterstellt, dass eine Methode, die eine Zeichenkette erwartet, nicht zu der Gruppe von Methoden gehört, die in der extrem schnellsten Zeitscheibe laufen, dann ist das nicht wirklich ein ins Gewicht fallender Aufwand.


1.5.2 Zusammensetzen eines Filenamens aus Indentnummer und Datum/Uhrzeit

Topic:.String_Jc.exam.examFilenameDate.

Das folgende Beispiel zeigt eine etwas komplexe und praxisrelevante Stringaufbereitung, die mithilfe der CRuntimeJavalike-Routinen plattformunabhängig und einfach gelingt. Bei diesem Problem stoßt man ansonsten meist an plattformspezifische Grenzen und aufwändige Überlegungen. Es geht um die Bildung eines Filenames aus einem gegebenem Path, einer Identifikationsnummer und aus dem aktuellem Datum zwecks Anlegen/Öffnen.

In Java sieht die Lösung mit den Standardmitteln von Java plattformunabhänig wie folgt aus:

 Writer openFile(String sPath, int ident)  //Java!
 {  Date date = new Date();
   SimpleDateFormat dateFormat = new SimpleDateFormat("yy_MMM_dd_HHmmss_SS");
   String sDateString = dateFormat.format(date);
   String sFileName = sPath + "file_" + ident + "_" + sDateString + ".txt";
   Writer retFile = new FileWriter(sFileName);
 return retFile;
 }

Ein Writer ist adäquat in C ein geöffneter File. Date ist eine Klasse, die Datum und Uhrzeit speichert. Der parameterlose Konstruktor speichert die momentane Zeit beim Aufruf. Die Klasse zur textuellen Aufbereitung einer Datums- und Zeitangabe ist SimpledateFormat. Man kann über einen Steuerstring bestimmen, wie der Zeitstempel textuell zusammengebaut wird. Für Filenamen sind beispielsweise die üblichen ':' zwischen den Bestandteilen der Uhrzeit nicht geeignet. Der hier konstant angegebene Steuerstring kann auch beispielsweise in einer Parametrierung vorgegeben werden.

Die Realisierung in C folgt diesem Muster:

FILE* exampleOpenAssembledFilenameWithDate(StringJc sPath, int identNumber)
{ FILE* retFile = null;
 StringJc sDateString;
 StringBuilderJc* bufferName;
 STACKTRC_ENTRY("exampleAssembleFilenameWithDate");
 { struct{ StringBuilderJc buffer; char _b[236]; } sBuffer = { CONST_addSizeStack_StringBuilderJc(&sBuffer.buffer, 236), {0}};
   DateJc_s date = {0};
   SimpleDateFormatJc_s dateFormat = {0};
   bufferName = &sBuffer.buffer;
   /**The parameterless constructor of DateJc initializes the current time. */
   ctorO_DateJc(&date.base.object, _thCxt);
   /**The constructor of SimpleDateFormat saves the format String, no more. */
   ctorO_s_SimpleDateFormatJc(&dateFormat.base.object, z_StringJc("yy_MMM_dd_HHmmss_SS"), _thCxt);
   /**Build the filename. Attention: routines, which returns the String in threadcontext,
    * should call immediately before the result is used.
    * Because the thread buffer will be overwritten from the next call. */
   append_s_StringBuilderJc(bufferName, sPath, _thCxt);
   replace_CC_StringBuilderJc(bufferName, '/', '\\');
   append_z_StringBuilderJc(bufferName, "file_", _thCxt);
   append_I_StringBuilderJc(bufferName, identNumber, _thCxt);
   append_z_StringBuilderJc(bufferName, "_", _thCxt);
   /**Conversion routine of given Date with the given format. */
   sDateString = format_SimpleDateFormatJc(&dateFormat, date.val, _thCxt);
   append_s_StringBuilderJc(bufferName, sDateString, _thCxt);
 }
 /**Open the file: */
 { /**The buffer contains the filename, it is \0-terminated. */
   char* sFileName = chars_StringBuilderJc(bufferName);
   retFile = fopen(sFileName, "wb");
 }
 STACKTRC_LEAVE;
 return retFile;
}

Die selbe Routine mit C++-Mitteln sieht wie folgt aus:

FILE* exampleOpenAssembledFilenameWithDate(StringJc sPath, int identNumber)
{ FILE* retFile = null;
  StringJc sDateString;
  StringBuilderJc* bufferName;
  STACKTRC_ENTRY("exampleAssembleFilenameWithDate");
   StringBuilder240Jcpp sBuffer(true);
   bufferName = &sBuffer;
   DateJcpp date;
   SimpleDateFormatJcpp dateFormat("yy_MMM_dd_HHmmss_SS");
   //sPathOsSpecific = replace_StringJc(sPath, '/', '\\', _thCxt);
   sBuffer(sPath).replace('/', '\\') + "file_";
   sDateString = dateFormat.format(&date);
   sBuffer + identNumber + "_" + sDateString;

 /**Open the file: */
 { /**The buffer contains the filename, it is \0-terminated. */
   char* sFileName = chars_StringBuilderJc(bufferName);
   retFile = fopen(sFileName, "wb");
 }
 STACKTRC_LEAVE;
 return retFile;
}

Hier werden wie in Java Instanzen für den Zeitstempel date und die Konvertierung dateFormat angelegt. Die Anlage erfolgt im Stack, weil sie nur temporär gebraucht werden. Für den Zusammenbau des Filenamens wird ein StringBufferJc mit einem Puffer für 240 Zeichen (ausreichend viel) ebenfalls im Stack angelegt. Der Stackbereich ist meist groß genug für solche Anforderungen.

Der zusammengebaute String wird nur temporär benutzt, da die Routine fopen den Filenamen nur in seinem eigenem Verlauf benutzt und nirgends als Referenz speichert. Dass das so ist, muss in der Parametervereinbarung klar geregelt sein. C kennt hier kein Sprachmittel dafür, es geht nur verbal oder manchmal nur per Vermutung. Das ist eine Schwäche in C, die aber nicht nur in diesem Beispiel auffällig ist. Programmierer machen sich um solche Dinge häufig wenig Gedanken - wenn es funktioniert dann ist es gut. Bei solchen Standardfunktionen wie fopen(...) ist auch nicht damit zu rechnen, dass es Abweichungen von der Vermutung der nur temporären Nutzung des Filenamens gibt. Anders aber bei selbstgeschriebenen Routinen, die in der Entwicklung sind. Fehler passieren dadurch, dass ein Bearbeiter etwas vermutet, was früher auch richtig war, aber nicht mehr nach einer Softwareänderung. Daher die klare Aufforderung: Bitte diese Dinge in die Beschreibung der Parameter aufnehmen.

Weil der String nur temporär benutzt wird, braucht man außen keine Aufwendungen. Keinen globalen Puffer, der dann möglicherweise thread-unsicher wird, kein Puffer, der als Parameter von außen übergeben werden muss, dessen Größe dann getestet werden muss bzw. den Aufrufenden belastet und ähnliches. Von außen gesehen ist der Aufruf der Routine einfach. Innen ist sie ebenfalls einfach.

Ein Puffer-Überlauf, der hier passieren kann wenn beispielsweise der sPath als Parameter sehr lang ist, führt nicht wie bei einem einfachen sprintf(...) zum Pufferüberlauf und nachfolgendem Absturz. Damit rechnet man normalerweise nicht, aber insbesondere während der Softwareentwicklung kann ein solcher Fall provoziert werden kann, weil Umgebungsbedingungen noch falsch sind. Für diesen Fall gibt es das Exceptionhandling. In der Tat wird in der überlauferzeugenden append...-Routine eine Exception erzeugt, die außen aufgefangen werden kann oder, wenn nicht aufgefangen, doch eine eindeutige Fehlerdiagnose ermöglicht.

Die Frage stellt sich: Wo befindet sich der Pufferbereich des Strings, der von der Routine format_SimpleDateFormatJc(...) zurückgegeben wird? Antwort: Im Thread-Context-Bereich. Für diesen Bereich gibt es klare Regelungen, siehe 1 Stringverarbeitung. Dieser String wird hier kopiert in den String, der im Stack steht. Damit kann diese Routine anstatt den geöffneten File zurückzugeben beispielsweise auch den zusammengebauten Filenamen zurückgeben. Dieser wird dann nach der Aufbereitung im Stack für die Rückgabe in den Threadlokalen bereich kopiert. Natürlich könnte man einfach den Zeiger auf den String im Stack zurückgeben und ist formal fertig - Die Fehlersuche überlässt man dann dem Anwender. Diese Gefahr besteht in der freien Nutzung von C oder C++.

In den Lösungen, wie man sie oft findet, wenn die CRuntimeJavalike nicht zur Verfügung steht, wird oft folgendes programmiert:


1.6 C++-Sprachmittel

Topic:.String_Jc.cpp.

Gegenüber C ist C++ verbessert. Relevant hier sind neben der syntaktisch klar geregelten Bindung von Methoden an Daten die Erkennung und Unterscheidung einer aufgerufenen Methode aufgrund ihrer Parametertypen und die mögliche Verwendung von Operatoren für die Verknüpfung von class-Instanzen mit anderen Werten (als 'überladene Operatoren' bezeichnet). Damit ist der C++-Quelltext insgesamt kürzer und oft besser zu lesen als das entsprechende C-Gegenstück. Das Beispiel in 1.5.2 Zusammensetzen eines Filenamens aus Indentnummer und Datum/Uhrzeit sollte dies demonstrieren.

Andererseits ist allerding bei einer 'überladenen Methode' nicht mehr einfach erkennbar, welche Methode gerufen wird. Der Programmier/Schreibaufwand bei C++ ist zwar geringer, aber die Nachvollziehbarkeit dessen, was im Ablauf tatsächlich passiert, ist weniger gut. Das ist ein allgemein bekannter Grund, in einigen Bereichen der Programmierung eher auf C zu setzen. Bezüglich der Stringverarbeitung kann man nun teils mischen.


1.6.1 Klassen und Methoden

Topic:.String_Jc.cpp.method.

Es sind C++-classes definiert StringJcpp und StringBuilderJcpp. Selbiges gilt auch für die hier verwendeten classes DateJcpp usw. jeweils mit der Endung Jcpp anstatt Jc. Die Klassen basieren jeweils auf den C-struct, so dass einerseits immer die selbe Datenabbildung erfolgt, andererseits eine implizite Typkonvertierung erfolgt wenn eine C-struct-Referenz beispielsweise irgendwo als Parameter benötigt wird. Damit ist die einfache Mischbarkeit von C- und C++-Verwendungen dieser class oder struct gegeben.

Die Methoden sind so definiert, das jeweils intern die C-Methoden aufgerufen werden. Das ist eine relativ einfache und gut nachvollziehbare Sache. Der ThreadContextFW-Zeiger _thCxt wird in der Regel nicht übergeben und kann bei den als operator+ definierten Methoden auch nicht übergeben werden. Daher wird er intern gebildet. Das benötigt etwas mehr Rechenzeit, gemessen im Nanosekundenbereich bei der PC-Programmierung. Es hängt von der Betriebssystemimplementierung der Thread-Funktionalitäten ab. Windows liefert mit den schnellen API-Funktionen TlsGetValue(...) die Möglichkeit der threadspezifischen Speicherung dieser Referenz.

Einige operator()-Routinen sind selbsterklärend, beispielsweise für das initiale Setzen von StringBuilder-Inhalten. StringBuilderJcpp.append(...)-Methoden können aneinander verkettet werden, da jeweils this wieder zurückgegeben wird.


1.6.2 Verkettung mit +

Topic:.String_Jc.cpp..

=

Die Schreibweise

 builder + "text" + value + ...
 

hängt jeweils den rechten Operand in den Puffer des als linken Operand angegeben StringBuilderJcpp an. Es wird garantiert von links nach rechts abgearbeitet.

Im grundlegenden Verständnis des +-Operators werden zwei Operanden verknüpft und ein drittes neues, das Ergebnis, gebildet. Das Ergebnis ist der Input für die rechts folgende +-Operation, existiert also nur temporär. Das Endergebnis wird ggf. für eine Zuweisung benutzt.

Würde man hier so arbeiten, dann bräuchte man für eine Verknüpfung von zwei Strings jeweils einen temporären Zwischenspeicher, der irgendwo existieren muss. Gut funktionieren kann dies nur, wenn der zwischenspeicher jeweils dynamisch angelegt wird. Das wiederspricht aber vollständig den Einsatzbereichen der Stringverarbeitung im Embedded-Bereich, wo auch mit C++ gearbeitet wird. Es wiederspricht auch einem effektivem Einsatz im PC-Bereich.

Daher ist das Verständis des +-Operators hier etwas anders, eigentlich genau das Verständnis des +=-Operators, der addierenden Zuweisung. Würde man aber den +=-Operator benutzen wollen, so wird der Zuweisungsausdruck allerdings von rechts nach links abgearbeitet. Das wäre schlecht lesbar und ungewöhnlich.

Bei der Verwendung des +-Operators für Instanzen von StringBuilderJcpp wird also jeweils die linksstehende StringBuilderJcpp-Instanz mit dem rechts stehendem Wert erweitert. Rechts kann ein StringJc, ein String-Literal, ein zeichen, ein numerischer Wert stehen. Das Ergebnis ist die StringBuilderJcpp-Instanz selbst, die also für die rechts folgende +-Operation wiederum als linksseitiger Operator zur Verfügung steht. Damit wird alles rechtsstehende nacheinander an den linksstehenden StringBuilder-Inhalt angehängt. selbiges kann man auch erreichen in dem geschrieben wird:

 builder.append("text").append(value).append ...
 

Das ist nur mehr Schreibarbeit.

Schreibt man links eine Zuweisung auf eine StringJc oder StringJcpp-Instanz, dann ist das ganze gut und logisch lesbar:

 StringJcpp result = builder + "text" + value;

Man muss aber als ersten Operand in der +-Kette immer eine StringBuilderJcpp-Instanz angegeben. Damit ist dann auch klar, wo der Ergebnis-Text steht und wo er gebildet wird. Soll der bisherige Inhalt des Builders keine Rolle spielen, dann muss er gelöscht werden, einfach durch Schreibweise

 StringJcpp result = builder.clear() + "text" + value;
 

Alle anderen Dinge, insbesondere die Persistenz, sind genau so zu beachten wie bei den C-Routinen. Die C++-Ausprägungen sind genauso wie die C-Routinen erstrangig für die Embedded-Programmierung gedacht und benutzen daher nicht unkontrolliert dynamischen Speicher.


1.6.3 Aufrufreihenfolge, Beachten bei Puffer im Thread-Context

Topic:.String_Jc.cpp..

Schreibt man

result = buffer.clean() + returnString(xyz) + returnOther();

dann ist zwar die Abarbeitung der Verkettung von links nach rechts gesichert. Der Compiler darf aber die Operanden vorher bestimmen und im Stack speichern, dabei ist keine Reihenfolge vorgeschrieben. Beobachtet wurde beim Visual-Studio-6-Compiler, dass zuerst die rechte Methode gerufen wurde, dann die linke. Das hat etwas mit der Reihenfolge der Parameter im Stack zu tun.

Diese beiden Methoden geben einen StringJc zurück, dessen Text beidemale im Thread-Context steht. Wenn beide Methoden nacheinander aufgerufen werden, dann überschreibt der zweite Aufruf den Text des ersteren, bevor die Verküpfung erfolgt. Das ergibt nicht das erwartet Ergebnis. Um dies zu vermeiden, muss man den Ausdruck teilen:

buffer.clean() + returnString(xyz);
result = buffer + returnOther();

Das selbe Problem tritt auch auf bei normalen artithmetischen Ausdrücken, wenn die aufgerufenen Methoden als Seiteneffekt Daten verändern, die der Folgeaufruf ungeändert voraussetzt, es handelt sich also um ein typisches C-Seiteneffektproblem, dass nur hier stärker auffällt, da der Puffer im Thread-Context häufig Verwendung findet.


1.7 Puffer im Thread-Context

Topic:.String_Jc.thCxtBuffer.

Der Puffer im Threadcontext kann für die String-Puffer-Aufbereitung geholt werden mit einem Aufruf in C

StringBufferJc* buffer = threadBuffer_StringBufferJc(_thCxt);

oder in C++ mit

 StringBufferJcpp* buffer = StringBufferJcpp::threadBuffer(_thCxt)

Der Parameter _thCxt ist die Referenz auf den Thread-Context. Diese Variable steht immer zur Verfügung, wenn STACKTRACE_ENTRY(...) gerufen wird, wie es nicht nur für das Exceptionhandling vorgesehen ist. Der Thread-Context ist Systemeigenschaft des Frameworks, dass der CRuntimeJavalike zugrunde liegt.


1.7.1 Nutzung und Bedingungen

Topic:.String_Jc.thCxtBuffer.rules.

Der Puffer im Thread-Context ist vorzugsweise dafür gedacht, einen String zu speichern, der als Returnwert zurückgegeben wird. Man braucht dann nirgends anders passend einen Puffer anzulegen, was konfliktträchtig sein kann. Man kann den Puffer auch für eine temporäre Stringaufbereitung nutzen, um keine Platz im Stack zu brauchen. Dann darf aber keine Routine aufgerufen werden, die einen String zurückgibt, also den Puffer auch nutzt.

Der Puffer im Thread-Context soll nicht referenziert werden. Er darf im laufenden Thread nur einmalig belegt werden. Ansonsten gibt es Nutzungskonflikte. Eine Verwaltung des Threadpuffers würde bereits wieder Overhead erzeugen mit der Frage, wie ein Nutzungskonflikt denn programmtechnisch aufgelöst werden sollte. Also muss sich jede Routine an die einfachen Regeln halten, dann funktioniert es immer.

Eine Alternative für den Puffer im Thread-Context wäre eine dynamische Speicherverwaltung, möglichst mit Garbage-Collector. So funktioniert es in Java und so ist es auch möglich in der CRuntimeJavalike mit dem BlockHeap-Konzept. Aber eine Bibliotheksroutine darf nicht voraussetzen, dass es eine dynamische Speicherverwaltung gibt. Der Puffer im Thread-Context ist dagegen für jedes Betriebssystem ohne Nebenwirkungen unterbringbar.


1.7.2 Beispiele der Nutzung des Puffers im ThreadContext

Topic:.String_Jc.thCxtBuffer.examDate.

Als Beispiel sei die Implementierung der String-Aufbereitung für einen Zeitstempel gezeigt, wie sie in der Quelle Jc/DateJc.c steht:

StringJc format_SimpleDateFormatJc(SimpleDateFormatJc_s* ythis, OS_TimeStamp timeStamp, ThCxt* _thCxt)
{StringBufferJc* buffer;
 STACKTRC_TENTRY("format_SimpleDateFormatJc");
 buffer = threadBuffer_StringBufferJc(_thCxt);
 format_tSb_SimpleDateFormatJc(ythis, timeStamp, buffer, null,_thCxt);
 STACKTRC_LEAVE; return toString_StringBufferJc(buffer, _thCxt);
}

Die eigentliche Konvertierung wird von einer Routine ausgeführt, die einen Puffer mit angegebener Länge als Parameter erwartet. Diese Kern-Routine is lo-Level programmiert, ohne die Nutzung von StringJc, ohne ThreadContext-Puffer, damit plattformunabhängig direkt nutzbar. Der Puffer wird im Thread-Context bereitgestellt, zurückgegeben wird dann eine StringJc-Instanz, die den Puffer referenziert. Diese Referenz steht im Stack, da die StringJc-Instanz als return-per-value zurückgegeben wird. Das ist zulässig. Nur eine Referenz, die außerhalb des Ablaufes sichtbar ist (persistent), darf nicht sein.

Ein weiteres Beispiel ist eine Routine aus TestString.c aus der Testumgebung für CRuntimeJavalike:

StringJc concatStringThreadBuffer()
{StringBuilder240Jc sBuffer = CONST_StringBuilder240Jc(&sBuffer);
 StringJc str;
 STACKTRC_ENTRY("concatStringThreadBuffer");
 str =
 ( setLength_StringBufferJc(&sBuffer.buffer, 0, _thCxt)
 , append_z_StringBufferJc(&sBuffer.buffer, "value = ", _thCxt)
 , append_I_StringBufferJc(&sBuffer.buffer, 5, _thCxt)
 , append_z_StringBufferJc(&sBuffer.buffer, ", ", _thCxt)
 , append_s_StringBufferJc(&sBuffer.buffer, returnConcatStringThreadBuffer(), _thCxt)
 , toString_StringBufferJc(&sBuffer.buffer, _thCxt)
 );
 printf(chars_StringBufferJc(&sBuffer.buffer));

 { //save string in the threadBuffer instead, to return it
 StringBufferJc* threadBuffer =  threadBuffer_s_StringBufferJc(str, _thCxt);
   str = toString_StringBufferJc(threadBuffer, _thCxt);
 }
 STACKTRC_LEAVE; return str;
}

In dieser Routine wird ein String erst in einem Puffer im Stack aufbereitet, da eine Routine gerufen wird, die selbst den Threadpuffer benutzt. Danach wird umkopiert, in dem nun mehr freien Threadpuffer.

Die Aufbereitung ist in mehreren Anweisungen in str = (...,...) geschrieben. Das ist nichts anderes als aufeinanderfolgende Anweisungen und in C möglich wenn auch nicht üblich. Durch diese Schreibweise soll betont werden, dass die Aufbereitung eigentlich eine Anweisung ist, die letztlich mit toString() abschließt und den letzten Part dem Ergebnis dann insgesamt zuweist.

Für den Nutzer dieser Routine ergibt sich der Vorteil, dass kein Platz für einen Puffer irgendwo reserviert werden muss. Er muss für den Return-String nur die Regel beachten: Zum alsbaldigen Verbrauch bestimmt.


1.7.3 Feststellen der doppelten Nutzung des ThreadContext

Topic:.String_Jc.thCxtBuffer..

Die einfache Regel ist: Alles was im ThreadContext gespeichert ist, wird unmittelbar genutzt, der ThreadContext-Puffer ist danach beliebig neu belegbar. Da nur der eigene Thread auf diesen Puffer zugreift, jeder Thread hat einen eigenen, kann es auch keine Threadkonflikte geben.

In Entwicklungssituationen der Software kommt es jedoch vor, dass der ThreadContext-Puffer nun doch versehentlich doppelt genutzt wird. Der Inhalt wird dann von der zweiten Nutzung einfach überschrieben und hat damit für die erste Nutzung, die per lokale Referenzen diesen Puffer referenziert, einen falschen Inhalt. Ergebnis sind dann falsche Daten. Dann muss man wieder debuggen und sehen woran es liegt. Denn selbstverständlich, würde man diesen Fehler schon kennen, würde man ihn gar nicht erst begehen.

Daher ist eine ein/ausschaltbare Überwachung der ThreadContext-Puffer-Nutzung vorgesehen:

bool wasCheching = setCheckingUserBuffer_ThreadContextFw(_thCxt, true);

Dann muss aber eine Nutzung des ThreadContext wieder freigeben werden mit

releaseUserBuffer_ThreadContextFw(_thCxt);  

Ansonsten gibt es bei der folgenden Nutzung eine IllegalStateException. Man muss dann die letzte Aktion aufsuchen, um die Fehlerstelle zu finden.

In einem StringJc wird mit den Bits mThreadContext__StringJc im Value-Wert gespeichert, ob der text zum StringJc im ThreadContext steht. Diese Information sollte von allen Routinen hineingeodert werden. Sie wird automatisch berücksichtigt, wenn

 StringJc myString = toString_StringBuilderJc(myBuilder);
 

gerufen wird, denn in der StringBuilder-Instanz ist gespeichert, dass diese im ThreadContext steht (mode-Bit _mThread_StringBuilderJc).

Mit dem Aufruf von

clear_StringJc(&myString);

wird dann der ThreadContext-Puffer mit freigegeben.

Diese Aktionen werden immer getan und kosten wenig Rechenzeit. Auf das clear_StringJc(...) kann man verzichten, wenn man setCheckingUserBuffer_ThreadContextFw(...) nicht aktiviert hat. Letzteres braucht man nicht grundsätzlich aktivieren sondern nur, wenn Fehler eingegrenzt werden soll oder eine Software im Test läuft.


1.8 Problem der Null-terminierung

Topic:.String_Jc.nullTerminiate.

Eine Reihe von C-Standardfunktionen erwarten einen \0-terminierten String. Im Anwendungsbereich werden sich auch eine Reihe solcher Anforderungen finden. Es muss also eine Kompatibilität geschaffen werden.

Die einfache Kompatibilität gibt es nicht. Man würde dann in der StringJc-Realisierung wichtige Vorteile aufgeben. Der Vorteil ist, dass sich Strings als Teilzeichenketten einfach bilden lassen, ohne einen originalen String umzukopieren. Damit braucht man wiederum keinen extra Puffer, spart etwas Rechenzeit bei String-Auswertungsroutinen, was sich aufsummieren könnte usw. - dann fangen die wirklichen Vorteile an.

Strings in einem Puffer sind aber automatisch 0-terminiert, wenn sie darin additiv aufbereitet werden. Der Puffer sollte/wird zuvor mit insgesamt \0 belegt, die Pufferlängenangabe in StringBufferJc ist so gestaltet, dass ein Reservebyte hinten bleibt. Wenn man insbesondere selbst einen String zusammengebaut hat, ist die \0-Terminierung danach garantiert. Man kann den Pufferinhalt gezeigert als char const* den verarbeitenden Routinen weitergeben.

Bei einem Parameter vom Typ StringJc darf man dagegen nicht mit einer \0-Terminierung rechnen, da man nicht wissen oder voraussetzen darf, wie der Parameter gebildet wird. Man kann aber vor der Verarbeitung testen, ob eine \0-terminierung vorliegt:

 int lengthString = length_StringJc(src);
 char termChar = charAt_StringJc(src, lengthString);
 if(termChar == 0){ ...

Diese Abfrage nützt aber nicht sehr viel, da man den Fall der nicht-\0-terminierung auch beherrschen muss. Es ist also nur eine Neugierde-Frage, keine mit praktischer Relevanz.

Man kann, wenn man weiß wo der String gespeichert ist, eine künstliche \0 an das bezeichnete Ende legen, den nunmehr \0-terminierten Zeiger weitergeben, und danach das ursprüngliche Zeichen wieder ersetzen. Das geht mit Hausmitteln von C. Das Verfahren soll aber nicht empfohlen werden. Es ist ein Trick, der an der Aufrufstelle hilft, jedoch Daten ändert, die nicht für die Änderung vorgesehen sind. In einem Multithreadsystem, wenn sich auch andere Threads des selben Strings beispielsweise als Control-String für irgendwas bedienen, kann es unvorhergesehene Nebenwirkungen geben. Eine Software wächst mit der Zeit und ihren Anforderungen, was heute scheinbar klar ist kann in der Weiterentwicklung nicht mehr gelten. Also Vorsicht mit solchen Tricks.

Will man von einem StringJc eine garantiert \0-terminierte Zeichenkette nebenwwirkungsfrei haben, so muss man einen Puffer bereitstellen und gegebenenfalls umkopieren. Die meisten Routinen erwarten einen \0-terminierten String als Parameter nur für den eigenen Ablauf (im Thread) und speichern keine Referenz darauf. Der String muss also nicht persistent sein und kann sich daher meist der Puffer im Stack befinden. Eine Pufferverwaltung ist somit nicht notwendig.

In der StringJc.h ist eine Routine definiert, die das Umkopieren besorgt wenn nötig. Man muss schreiben:

 char buffer[123]; //Im Stack, geschätzte ausreichende Größe
 char const* src0 = gets0_StringJc(src, buffer, sizeof(buffer), false, _thCxt);

Die Routine gets0_StringJc(...) kopiert nur dann um, wenn die in src referenzierte Zeichenkette nicht 0-terminiert ist. Ist sie 0-terminiert, dann wird der Zeiger auf das Original zurückgeliefert, Rechenzeit gespart und der buffer nicht benutzt. Man darf also im weiteren Verlauf nicht die Referenz von buffer nutzen, sondern den Rückgabewerte der gets0_StringJc(...). Der Speicherplatz für den buffer wird also nur für den Eventualfall vorbehalten, der aber vorkommen kann.

Beim Aufruf lässt sich steuern, ob bei einem zu kleinem buffer eine Exception gerufen werden soll oder nicht. Das ist im Folgekapitel erläutert.


1.9 Pufferüberlauf, Abschneiden oder Exceptions

Topic:.String_Jc.overflow.

In manchen Routinen des Standard-C passiert ein Pufferüberlauf unkontrolliert mit nachfolgenden schwer zuordenbaren Folgefehlern. In der Stringverarbeitung der CRuntimeJavalike gibt es so etwas nicht.

Die Konkatierung von Strings neigt aber zu dem Problem des Pufferüberlaufes insbesondere in Testphasen, in der Zuliefer-Parmeter auch mal falsch sein können weil noch nicht endgültig ausgetestet. Man kann bei einem erkannten Überlauf in zweierlei Richtungen reagieren:

  • Überlauf verhindern, Zeichenkette abschneiden, Warnung austestbar gestalten.

  • Exception werfen.

  • Beide Herangehensweisen haben ihre Vor- und Nachteile und müssen mit Systemeigenschaften abgestimmt sein. Daher wird in der CRuntimeJavalike beides unterstützt.

    Die Vor- und Nachteile vom Abschneiden der Zeichenketten sind:

    Die Vor- und Nachteile des Exceptionhandlings sind:

    Die Arbeitsweise Exception oder Abschneiden lässt sich pro Instanz von StringBuilderJc einstellen:

     bool setTruncateMode_StringBuilderJc(StringBuilderJc* ythis, bTruncate);
    

    Es wird dabei ein Bit im Mode-Wort gesetzt. Die bisherige Belegung wird zurückgegeben. Nachdem der String fertig zusammengestellt ist, kann man mit

     wasTruncated_StringBuilderJc(sb)
    

    abfragen, ob ein Abschneiden erfolgte.

    Die Schreibweise des Exceptionhandling in der CRuntimeJavalike ist in Exceptionhandling erläutert. Im Prinzip ist so wie in Java zu verfahren:

    Wenn man unter normalen Umständen nicht mit einem Pufferüberlauf rechnet, dann kann man entweder eine Exception übergeordnet auffangen oder gar nicht. Ersteres folgt dem Prinzip: Wenn irgend etwas im Ablauf in einem Modul nicht stimmt, folgt eine bestimmte Ausnahmebehandlung. Dabei ist es nicht wesentlich ob es ein Pufferüberlauf an bestimmter Stelle erfolgt oder ein anderer Fehler. Für die Fehlersuche hilfreich ist die Ausgabe des Stacktrace. Fängt man die Exception gar nicht auf, bekommt man immerhin die Stacktraceanzeige in der uncatched exception als Hilfe für die Ursachenforschung.


    1.10 Exception bei Parameterfehlern

    Topic:.String_Jc.paramException.

    Entgegen der Auswahl 1.9 Pufferüberlauf, Abschneiden oder Exceptions gibt es bei Parameterfehlern keine Wahlmöglichkeit. Ein String-Überlauf kann passieren, wenn die String-Quellen entsprechend zu lang sind. Ein Parameterfehler ist fast immer ein Softwarefehler, der vorderhand abzustellen ist. Wichtig ist, einen solchen Fehler rechtzeitig und deutlich zu erkennnen. Würde man etwa einen Leerstring zurückliefern, wenn bei substring(..., begin, end) falsche Parameter übergeben werden, dann würde dieser Fehler zuerst gar nicht auffallen.

    Für die Exception gilt ähnliches wie bei der Exception beim Pufferüberlauf: Man braucht nicht etwa jede Routine mit einem CATCH auffangen, sondern kann ein Exceptionhandling an Modul-globaler Stelle unterbringen. Kommt es zu einer Exception, dann ist mit Nutzung des Stacktrace-Mechanismus die Fehlerstelle einfach zu lokalisieren. Das gilt auch, wenn die Exception nicht aufgefangen wird.

    Die meisten Routinen, die Exceptions werfen könnten, übernehmen den Stacktrace als letzten Parameter. Der Parameter ist einfach mit _thCxt zu besetzen, wenn man den STACKTRC_ENTRY("Routinenname")-Mechanismus benutzt. Das sollte man tun, wenn eine Fehlerursache auch einfach aufgespürt werden sollte. Man kann an dieser Stelle auch null übergeben.


    1.11 Zuweisung, Persistenz von Zeichenketten

    Topic:.String_Jc.Persistence.

    Für die persistente Zuweisung eines Strings in eine andere Instanz von StringJc zur Nutzung über die Laufzeit einer Routine hinaus (für andere Threads) ist die Methode

     set_StringJc(StringJc* dst, StringJc src);
    

    vorgesehen. Das direkte Kopieren der Art

     dst = src;
    

    ist dann zulässig und soll verwendet werden, wenn es sich lediglich um eine temporäre Zwischenspeicherung handelt, die in der selben Routine unmittelbar 'verbraucht' wird. Für die persistente Zuweisung ist das einfache Setzen in einigen Fällen zwar auch ausreichend, es soll jedoch generell set_StringJc(...) verwendet werden. set_StringJc(...) führt einige Tests und Behandlungen durch. C++ kennt für solche Art Zuweisungen den Copy-Constructor. Dieser wird immer aufgerufen ohne explizite Notation in den Quellzeilen des Anwenders, sobald er definiert ist. Der Copy-Constructor ist in C++ für das Abfangen von Sonderfällen zuständig, wenn das einfache Kopieren des Inhaltes falsch sein könnte oder ist. Über die etwas höhere Rechenzeit (Subroutine wird gerufen, Tests erfolgen) auch im Fall der Nichtbehandlung wird in C++ gepflogenermaßen nicht geredet. Die höhere Programmiersicherheit steht im Vordergrund. Man sieht im Quelltext auch nicht explizit, dass da ein Zusatzaufwand erfolgt, wenn man die Stelle nicht gerade einzelschrittig debugged. -- Für den adäquaten Zusammenhang gibt es hier nun die genannte set-Routine. Die einfache Zuweisung, einfach und schnell, darf und kann dann vom Anwender benutzt werden, wenn er dieser Sache sicher ist und aufgrund Rechenzeitoptimierungen das notwendig ist (diese Möglichkeit hat man in C++ vorderhand nicht).

    Die set_StringJc(...)-Routine sorgt dafür, dass eine Referenz auf einen persistenten String entweder vorhanden ist (Test) oder erzeugt wird. Dabei wird die Verwaltung von einem Garbage-Collector (BlockHeap) eingerichtet. Es wird geprüft, ob der String etwa im Stack oder im Thread-Context-Puffer steht. Beides wird erkannt mit dem gesetztem Bit mNonPersists__StringJc im Speicherwort für die String-Länge. Ist der String so gekennzeichnet, muss er umkopiert werden. Ist dies nicht möglich insbesondere weil keine dynamische Speicherverwaltung gewünscht ist, dann liegt ein Programmierfehler vor und eine Exception wird erzeugt.

    Wenn man set_StringJc(...) nutzt um mit dynamischer Speicherverwaltung automatisch eine persistente Zeichenkette zu erzeugen, dann ist das relativ einfach und elegant zu programmieren. Aber es muss natürlich geklärt sein, wie der dynamische Speicher verwaltet wird, wann und von wem er wieder freigegeben wird. Wird die CRuntimeJavalike-Bibliothek in ihrer gesamten Breite genutzt, dann steht ein Garbage-Collector-Konzept, der BlockHeap oder ein anderes adäquates zur Verfügung. Damit ist die Frage der Speicherverwaltung außerhalb des Fokus der Anwenderprogrammierung, wie in Java. Die set_StringJc(...)-Routine sorgt dabei dafür, dass die Referenz auf den Speicher dem Garbage-Collector bekannt ist.

    Wenn man einen persistenten String temporär benötigt, etwa weil ein Rückgabe-Text einer toString-Routine im Thread-Kontext gespeichert werden soll, der Thread-Kontext-Puffer soll für eine andere Routine wieder belegbar sein, dann gibt es für diesen Zweck die Routine persist_StringJc(...). Diese prüft ebenfalls, ob eine Persistenz des Textes bereits vorliegt, legt einen neuen Puffer an wenn notwendig, aber diese Routine benötigt im Gegensatz zu set_StringJc(...) keine Instanz, in die gespeichert wird und richtet auch nicht die Verwaltung mit dem Garbage-Collector ein. Die persist_StringJc(...)-Routine realisiert also nur einen Teil der Aufgaben gegenüber set_StringJc(...). Kombiniert man beide miteinander, also etwa in

     StringJc meta = persist_StringJc(src);
     set_StringJc(&dst, meta);
     
    

    dann werden nicht etwa zwei Puffer eingerichtet. Da die set_StringJc-Routine erkennt, dass der String bereits persistent ist, erfolgt dies nicht.

    Damit ein angelegter Speicher in persist_Stringjc(src) auch wieder freigegeben wird, muss die Routine

     activateGarbageCollection(meta);
    

    gerufen werden. Man bekommt also nichts etwa geschenkt, automatisch oder so, sondern muss sich wie in C üblich eine Speicherfreigabe als Befehlszeile schreiben. Der Unterschied zu malloc/free ist, dass mit dem activateGarbageCollection die Freigabe nicht sofort erfolgt, sondern vom Garbage-Collector in einem eigenem Thread vorgenommen wird. Damit wird an dieser Stelle Rechenzeit eingespart. Außerdem prüft der Garbage-Collector, ob der Speicher noch anderweitig benutzt wird.

     
    

    Entgegen der empfohlenen Verwendung von set_StringJc(...) auch in Systemen ohne dynamische Speicherverwaltung hat die Anwendung des persist_StringJc(...) dort nichts zu suchen. Man kann nicht, wenn keine Speicherverwalung vorhanden ist, diese voraussetzen wollen, sondern man muss dann die persistente Speicherung geeignet selbst manuell programmieren. Diese Aussage ist wichtig bei Anwendung von Java2C. Soll damit C-Code für nicht-dynamische System erzeugt werden, dann muss bereits in Java die Persistenz dort wo notwendig mit entsprechender Speicherung erzeugt werden oder die Nicht-Persistenz-Notwendigkeit deklariert werden. Das erfolgt auf der Java-Quellebene mit Annotationen @java2c=... in Kommentaren. Enthält die Quelle dann einen persist_StringJc(...)-Aufruf, dann ist sie also nicht für nicht-dynamische Systeme geeignet. Allerdings kann auch in solchen Systemen dieser Aufruf vorkommen:


    1.11.1 Vergleich mit Standard-Java

    Topic:.String_Jc.Persistence.javalike.

    Im Standard-Java ist die Welt der persistenten Strings recht einfach und leistungsstark gelöst. Die Vorraussetzung ist: Es gibt dynamischen Speicher, dessen Allokierung ist relativ schnell möglich, solange genügend Speicher verfügbar ist. Für das Kopieren von Zeichenketten können meist leistungsstarke Blockbefehle der jeweiligen CPU verwendet werden. Das Ganze ist also optimal. Daher wird bei einem Aufruf von StringBuilder.toString() sofort der Inhalt in einen eigenen Speicher kopiert und ist persistent. Wird ein neuer String gebildet, dann wird sofort wieder temporär eine StringBuilder-Instanz mit allokiertem Speicher angelegt, es wird verkettet, das Ergebnis wird wiederum kopiert in einen neu angelegten Speicher. Damit ist das Programmumfeld immer sicher - und schnell genug.

    Die Aufwändungen, die dagegen in der CRuntimeJavalike auftreten, sind den Umständen der embedded-Programmierung im C-Bereich geschuldet:

    Daher ist gegenüber dem Standard-Java (Virtuelle Maschinen auf PC) folgende Verfahrensweise abgeändert:


    1.11.2 Persistenz bei toString_StringBuilderJc

    Topic:.String_Jc.Persistence.toStringPersist.

    Der StringBuilder wird benutzt insbesondere für die Bildung von Zeichenketten per Verkettung, die später als StringJc referenziert werden. Eine StringBuilderJc-Instanz wird verwendet insbesondere für die Sicherung der Persistenz von Texten. Damit stehen in dieser Klasse spezifische toString-Ausprägungen zur Verfügung:

    StringJc ref = toString_StringBuilderJc(builder);
    

    Die einfache toString_StringBuilderJc()-Methode liefert eine Referenz auf den text im StringBuilder selbst, legt also keine extra Instanz an und kopiert den text auch nicht in den Thread-Kontext-Puffer. Die Referenz wird als persistent bezeichnet, wenn der StringBuilder nicht im Stack und nicht im Thread-Kontext steht, also entweder dynamisch allokiert ist oder eine Instanz innerhalb statisch angelegter Daten ist. Damit ist diese Methode geeignet zum Erhalt eines persistenten Strings auch ohne dynamische Speicherverwaltung. Man kann aufrufen:

    set_StringJc(&mydata->str, ref);
    

    Diese Methode wird keine Excpetion erzeugen, wenn der text in einem StringBuilder steht, der persistent ist. Wird programmierfehlerhaft ein Text im stack zugewiesen bei nicht vorgesehener dynamischer Speicherverwaltung, wird das zur Laufzeit mit einer Exception bemerkt.

    Die StringBuilder-Instanz wird beim Aufruf von toString_StringBuilderJc() als freezed (eingefroren) markiert, denn nur dann ist die Persistenz gewährleistet. Eine Änderung des Textes in diesem StringBuilder (Aufruf von append oder dergleichen) nach der tostring-Bildung führt zu einer Exception, es ist ein Programmierfehler. Damit kann diese Herangehensweise insgesamt gewählt werden, um einen persistenten string zu erhalten bei fehlender dynamischer Speicherverwaltung.

    Es gibt eine Möglichkeit, den eingefrorenen Status der StringBuilderJc-Instanz wieder aufzuheben, mit Aufruf von releaseStringBuilt_StringBuilderJc(). Damit ist die eigentlich zugesicherte Peristenz der StringJc-Referenzen zu dem hier enthaltenen Text hinüber. Diese Methode darf also nur aufgerufen werden, wenn bekannt ist, dass die Änderung zulässig ist. Das ist beispielsweise der Fall, wenn der Text einen Path auf einen aktuell verwendeten File enthält, der File wird gewechselt, an keiner stelle ist der ältere Inhalt mehr zweckmäßig. Man sollte dann aber auch, wie in Java notwendig, den Aufruf von

    set_StringJc(&mydata->str, toString_StringBuilderJc(builder);
    

    wiederrholen, obwohl es auch in C funktioniert, wenn man es nicht wiederholt, denn die Referenz zum Puffer ist dieselbe wie zuvor. Mit dem erneutem Aufruf wird der freeze-Status wieder erreicht. Der Algorithmus nach Java übertragen funktioniert dann genauso.


    1.11.2.1 Persistenz ist nicht notwendig: toStringNonPersist(...)

    Topic:.String_Jc.Persistence.toStringPersist..

    Wenn in einem StringBuilderJc ein Text aufbereitet wird, der sofort danach verbraucht wird, dann kann die StringBuilder-Instanz danach sofort wieder für die nächste Aufbereitung genutzt werden. Das ist effektiv. Etwa so:

     struct _stringBuilder_t{ StringBuilderJc u; char _b[256-4]; }_stringBuilder =
       CONST_addSizeStack_StringBuilderJc(&_stringBuilder.u, 256-4);
     init_ObjectJc(&(ythis->oStream1.base.object), sizeof(ythis->oStream1), 0);
     ctorO_s_FileOutputStreamJc(/*static*/&(ythis->oStream1.base.object),
       ( setLength_StringBuilderJc(&_stringBuilder.u, 0, _thCxt)
       , append_s_StringBuilderJc(&_stringBuilder.u, sPath, _thCxt)
       , append_z_StringBuilderJc(&_stringBuilder.u, "file1.txt", _thCxt)
       , toStringNonPersist_StringBuilderJc(&(&_stringBuilder.u)->base.object, _thCxt)
       ), _thCxt);
     /***/
     //J2C: constructor for embedded element-ObjectJc
     init_ObjectJc(&(ythis->oStream2.base.object), sizeof(ythis->oStream2), 0);
     ctorO_s_FileOutputStreamJc(/*static*/&(ythis->oStream2.base.object),
       ( setLength_StringBuilderJc(&_stringBuilder.u, 0, _thCxt)
       , append_s_StringBuilderJc(&_stringBuilder.u, sPath, _thCxt)
       , append_z_StringBuilderJc(&_stringBuilder.u, "file2.txt", _thCxt)
       , toStringNonPersist_StringBuilderJc(&(&_stringBuilder.u)->base.object, _thCxt)
       ), _thCxt);
    

    Das Beispiel ist aus einem Testprogramm, dass über Java2C aus Java übersetzt wurde. Der Java-code dieses Teils sieht wie folgt aus:

     /**@java2c=StringBuilderInStack:100, toStringNonPersist. */
     oStream1 = new FileOutputStream(sPath+ "file1.txt");
     /**@java2c=StringBuilderInStack=256,toStringNonPersist. */
     oStream2 = new FileOutputStream(sPath+ "file2.txt");
    

    Die Überlegung ist also bereits im Java etablierbar: Der Text kann temporär im Stack aufbereitet werden, er braucht nicht persistent sein. Damit ist kein etwa dynamischer Speicher notwendig. Lo-Level in C würde man genauso herangehen: Ein char[256]-Array (genügend groß, man weiß ja nie) wird im Stack vereinbart, mit sprintf gefüllt und sofort verwendet. Bei dieser Art der Programmierung ist Insider-Wissen von nöten. Man sieht bei der Verwendung der Stack-Instanz nicht unmittelbar, dass diese im Stack steht. In diesen Beispielen dürfte der Maschinencode sogar noch etwas optimaler sein, da sprintf die Format-Zeichenkette interpretieren muss, hier aber die Argumente direkt angegeben sind. Aus Sicht der Quelle ist mit dem Aufruf

     toStringNonPersist_StringBuilderJc(...)
     
    

    deutlich gezeigt, dass dieser String nicht persistent ist.


    1.11.2.2 Persistenz ist notwendig: toStringPersist(...)

    Topic:.String_Jc.Persistence.toStringPersist..

    Der gegenteilige Fall - Persistenz ist unbedingt notwendig - kann über die entsprechende Methode

     toStringPersist_StringBuilderJc(...)
      
    

    gebildet werden. Diese Art des Aufrufes setzt dynamischen Speicher voraus. Der Vorteil ist: Die StringBuilderJc-Instanz wird nicht gefreezed, sondern es wird (wie in Java) ein Abbild des Textes in einer neuen dynamisch angelegten Instanz referenziert. Wenn die StringBuilderJc-Instanz aber gekennzeichnet ist als dynamisch angelegt nur für die Bildung dieses Strings, dann erfolgt keine nochmalige Instanzierung. Die Unterscheidung ist möglich mit gesetztem Bit


    1.11.3 Beispiel persistente Speicherung eines toString()-Ergebnisses

    Topic:.String_Jc.Persistence.setStringThrBu.

    Die toString()-Methoden von Standard-Routinen der CRuntimeJavalike benutzen keinen dynamischen Speicher. Einerseits wird damit nicht vorausgesetzt, dass dieser in der Anwendung auch vorgesehen ist, andererseits ist das Ressourcen-optimiert: Meist wird ein toString-Ergebnis sowieso kopierenderweise verarbeitet und muss nicht persistent vorhanden sein. Die toString()-Methoden nutzen den Speicher im Thread-Kontext, siehe 1.7 Puffer im Thread-Context.

    Ist im System dynamischer Speicher allokierbar, dann braucht der Anwender sehr wenig beachten. Um Beispielsweise die Rückgabe eines aufbereiteten Zeitstempel-Strings persistent zu speichern, braucht man nur schreiben:

    StringJc sDateString = format_SimpleDateFormatJc(dateFormat, date.val, _thCxt);
    set_StringJc(&myData->sPersistentDate, sDateString);
    

    Die erste Zeile ruft die Formatierung auf und gibt die Zeichenkette im Thread-Context zurück. Die zweite Zeile allokiert Speicherplatz, speichert die Zeichenkette persistent und setzt in der Datenstruktur myData das entsprechende Element.

    Steht im System kein dynamischer Speicher zur Verfügung, dann muss die Anwendung für einen passenden Platz sorgen. Als Beispiel kann folgendes stehen:

    StringJc sDateString = format_SimpleDateFormatJc(dateFormat, date.val, _thCxt);
    int nrofChars = copyToBuffer_StringJc(sDateString, myData->buffer, sizeof(myData->buffer));
    StringJc sPersistentString = zI_StringJc(myData->buffer, nrofChars);
    set_StringJc(&myData->sPersistentDate, sPersistentString);
    

    Die erste Zeile ist identisch, weil die Routine zur Aufbereitung des Zeitstempels mit dem Persistenz-Problem nichts zu tun hat. In der zweiten Zeile wird die rückgegebene Zeichenkette persistent umkopiert in einen normalen char[]-Buffer irgendwo in einem passenden Anwenderbereich. Der Anwender ist hier für die Persistenz verantwortlich. Es sind die gleichen Bedingungen, die man auch sonst in der C-Programmierung hat.

    Die dritte Zeile bildet mit der gezeigten Routine mit entsprechender Namensgebung temporär einen persistenten String. Wenn der Anwender diese Routine aufruft, dann muss er die Persistenz des Puffers also selbst sichern. Wenn ein Softwarereview diesen Aufruf sieht, dann ist klar dass die Persistenz des myData->buffer geprüft werden muss.

    Die beiden StringJc-Variablen sDateString und sPersistentString unterscheiden sich also abgesehen davon, dass ein anderer Puffer referenziert wird, insbesondere in der Kennzeichnung mit dem Bit mNonPersists__StringJc.

    Nun könnte man also die endgültige Variable myData->sPersistentDate gleich in der dritten Zeile setzen. Das Ergebnis ist das selbe. Aber die Darstellung hier ist einerseits mehr akademisch, andererseits folgt sie einer Richtlinie: Alle letztlich persistent notwendigen StringJc-Variablen dürfen nur mit set_StringJc...) gesetzt werden. Nachteil: Ein klein wenig mehr Rechenzeit. Vorteil: Ein Softwarereview kann kontrollieren, ob das so ist. Das geht also in Richtung Programmiersicherheit. Die set_StringJc(...)-Routine prüft, ob der String persistent ist und würde sonst einen Fehler melden.

    Vergleich mit 'normaler' C-Programmierung: An solchen Stelle muss der Anwender aufpassen und entsprechende Puffer definieren und memcpy-Befehle usw. unterbringen, die meist nicht einfach zu durchschauen und zu reviewen sind.


    1.11.4 Beispiel temporäres Zusammensetzen eines Strings mit nachfolgender persistenter Speicherung

    Topic:.String_Jc.Persistence.setStringConcat.

    Folgendes Beispiel baut einen String im Stack zusammen, bildet temporäre Strings und speichert persistent. Die Routine ist der Quelle TestString.c in den Testroutinen zur CRuntimeJavalike entnommen (kann dort debuggenderweise angeschaut werden) und ist hier im Detail kommentiert. Es wird hier vorausgesetzt, dass kein dynamischer Speicher verwendet wird.

    void testPersistence(int nException)
    {
    

    Folgende Anweisung zeigt, wie ein String-Puffer im Stack angelegt werden kann. Es wird eine struct von StringBuilderJc und einem im Speicher nachfolgenden Puffer gebildet. Das ist zulässig. Nicht zulässig wäre, die struct{...}-Umrahmung wegzulassen und vorauszusetzen, dass ein char _[50] nach dem StringBuilderJc b in der Quelle angeordnet auch die Stackvariablen in dieser Reihenfolge anordnen würde. Dem ist nicht so bzw. es ist nicht garantiert. Nur eine struct{...}-Zusammenstellung wird im Speicher auch in dieser Zusammenstellung abgebildet. Die Initialisierung der Struktur aus StringBuilderJc und nachfolgendem Puffer kann wie gezeigt erfolgen. Mit dem genanntem Makro wird die StringBuilderJc-Instanz als nicht persistent gekennzeichnet.

    //instance in Stack to concatenate:
     struct { StringBuilderJc b; char _[50]; } buffer = { CONST_addSizeStack_StringBuilderJc(&buffer.b, 50), 0};
    

    Die folgenden Anweisungen bauen den String zusammen...

     STACKTRC_ENTRY("testPersistence");
     append_z_StringBuilderJc(&buffer.b, "Test", _thCxt);
     append_I_StringBuilderJc(&buffer.b, 345, _thCxt);
    

    Folgend wird ein StringJc str gebildet, dass aber den String nicht persistent zeigert. Das ist okay für eine Weiterbenutzung als Parameter der gerufenen Methode. In der Methode ist ebenfalls die Persistenz abfragbar, weil sie im StringJc gespeichert ist, Bit mNonPersists__StringJc.

     { /**The building of a StringJc to a buffer in Stack is admissible.
        * It is able to use at example for parameter of called methods. */
       StringJc str = toString_StringBuilderJc(&buffer.b.base.object, _thCxt);
       testStringJcParam(str);  //use, but not save persistently.
    

    Der nächste Anweisungsblock versucht, den gegebenen String persistent zu speichern. Das wird in diesem Beispiel aber mit einer Fehlermeldung (Exception) beantwortet, weil kein dynamischer Speicher allokierbar ist. Das einfache Muster funktioniert hier nicht, wegen nicht vorhandenen Systemeigenschaften. Das Gute ist: Aufgrund der Nutzung von set_StringJc(...) wird der Fehler erkannt, da zur Runtime geprüft wird.

     
       /**The next statement causes an error, because in this running environment,
        * dynamic memory isn't present. Therefore it is set under if.
        * Note that an adequate error in Standard-C, referencing a String in Stack,
        * causes a difficult visible fatal error elsewhere. */
       if(nException >=2){
         set_StringJc(&sPersistentString, str);
       }
     }
    

    Der nächste Block ist ein Negativmuster. Wenn man so programmiert, sieht alles scheinbar gut aus, aber es wird nicht funktionieren. Eine einfache Zuweisung des nicht persistenten Strings. Immerhin ist im gespeicherten String sPersistentString die Nicht-Persistenz beispielsweise beim Debuggen erkennbar, weil das Bit mNonPersists__StringJc dort gesetzt ist.

     /**This call doesn't build a persistant String. It is inadmissible!
      * The StringJc is dedicated with a non-persistant flag-bit, so the error is able to detect. */
     sPersistentString = toString_StringBuilderJc(&buffer.b.base.object, _thCxt);
    

    Das dazu passende Positivmuster ist die Herstellung der Persistenz mittels Kopieren, und Aufruf von set_StringJc(...) zur Sicherheit. Eine direkte Zuweisung wie in der Zeile darüber gezeigt würde es für diesen Fall auch tun, aber es ist kein gutes Muster da Fehler nicht detektiert werden.

     /**Any persistant Buffer is necessary! Copy to temporary String to it!
      * The location of the buffer should controlled individually.
      */
     int nrofChars = copyToBuffer_StringBuilderJc(&buffer.b, bufferForPersistentString, sizeof(bufferForPersistentString));
     /**The next assignement checks, whether the source is persistent.
      * If a persistent String is necessary, the ,,set_StringJc(...),,-Method should use anyway,
      * a eyes-check of source should found them.
      * The input String is declared as persistent by using the named routine, it uses the persistent buffer.*/
     set_StringJc(&sPersistentString, zI_StringJc(bufferForPersistentString, nrofChars));
    

    Folgende Zeile zeigt ein weiteres Problem der Arbeit mit Strings und Puffern. Der Pufferinhalt des StringBuilderJc buffer.b wurde bereits mit toString() zwar nicht persistent, also nicht dauerhaft auch für andere Threads und über den Aufruf gespeichert, da im Stack befindlich. Aber immerhin sollte er von nun an konstant bleiben, solange der gebildete StringJc benutzt werden könnte. Dazu wird mit dem Aufruf von toString_StringBuilderJc ein Bit gesetzt, dass beim nachfolgendem Ändern abgefragt wird. Es wird dann eine Exception erzeugt, die anzeigt, dass etwas nicht stimmt. Das ist ebenfalls wieder eine Programmiersicherheit. Solche Dinge werden oft übersehen.

     /**This appends something to a StringBuilder, which was referenced by a String already.
      * It is not admissible, because the String may be used furthermore and it should be non-changed.
      * Because the StringBuilderJc-instance is dedicated with the bit _mStringBuilt_StringBuilderJc
      * set while toString() were processed, an exception is thrown.*/
     append_z_StringBuilderJc(&buffer.b, "second", _thCxt);
    

    In der vorliegenden Beispielroutine liegt aber die Nutzung des gebildeten StringJc str zurück. Aufgrund der Befehlsabfolge ist gewährleistet, dass der Puffer nicht mehr konstant sein muss. Also kann er ressourcenschonend für eine weitere Verkettung günstig genutzt werden. Da das der Programmierer weiß, kann er mit der folgenden Befehlsfolge die Nutzung als aufgelöst bezeichnen und damit weiter programmieren:

     /**If it is assured, that the buffered String isn't used any more, the same instance can be used
      * to concatenate furthermore. To communicate this fact, the release... method is called.
      * The programmer is responsible to the correctness of calling this method.*/
     releaseStringBuilt_StringBuilderJc(&buffer.b);
     append_z_StringBuilderJc(&buffer.b, "second", _thCxt);
    

    Als letztes soll gezeigt werden, dass eine weitere Zuweisung eines Strings, im Beispiel der nunmehr verlängerte, möglich ist aber selbstverständlich auch hier die Verantwortung des Programmierers gefragt ist. In einem Laufzeitsystem wie Standard-Java oder in CRuntimeJavalike mit extensiver Nutzung des BlockHeap ist das alles kein Problem, da die Strings jeweils neu persistent im eigenem Bereich gespeichert werden. Aber bei klassischer C-Anwendung ohne dynamischen Speicher ist das so wie hier gezeigt.

     /**The next statements saves the changed String in the same buffer for persistence like before.
      * It may be okay, because only one String uses the buffer.
      * But it may be able too, that the String is referenced any other where. The manually data structure
      * in the C-language Project should be complied to decide whether it is okay or not.
      * In an universal system a dynamically allocation prevents all problems.
      * But this simple examples doesn't assume a dynamically system.
      */
     copyToBuffer_StringBuilderJc(&buffer.b, bufferForPersistentString, sizeof(bufferForPersistentString));
     sPersistentString = z_StringJc(bufferForPersistentString);
     set_StringJc(&sPersistentString, z_StringJc(bufferForPersistentString));
    

    Der Rest der Routine:

     STACKTRC_LEAVE;
    }
    
    
     
    

    1.12 Einsatz der class StringPartJc

    Topic:.String_Jc.StringPart.

    Die Klasse StringPart enthält weiterführende Routinen. Der Name deutet an, dass hier viel mit einem Teil einer Zeichenkette gearbeitet wird. Der aktuelle Teil des Textes kann verschoben, vergrößert oder verkleinert werden. Operationen beziehen sich auf den aktuellen Teil. Die zeichenkette kann beispielsweise der komplette Inhalt eines textuellen Files sein, beispielsweise mit Steuer-Parametern, die ausgewertet werden sollen. Die Klasse verfügt über Such- und Scan-Routinen.

    Diese Klasse war ursprünglich bereits Anfang der 90-ger Jahre geschrieben und also getestet, als C++-Klasse. Ab 2003 wurde die Klasse als javadoc-src:_org/vishia/util/StringPart nach Java überführt und dort ebenfalls vielseitig genutzt, beispielsweise als Kern des ZBNF-Parsers. Die vorliegende Form in C, auch in C++ nutzbar, ist Ergebnis der Konvertierung des Java-Quelltextes nach dem C/C++-Quelltext. Bei der Nutzung braucht man aber das weder das Java2C-Konzept noch die Java-Wurzeln zu kennen. Der vorliegende Quelltext ist auch in C oder C++ ordentlich lesbar und debugbar. Die Routinen sind allesamt in C realisiert. Die Kern-struct heißt StringPartJc_s. Für die Nutzung in C++ gibt es die Wrapper-class StringPartJc, die auf der C-struct basiert, alle Routinen in der C++-Form enthält aber darin direkt die C-Routinen ruft. Damit ist auch diese Klasse als Mix von C und C++ nutzbar.

    Folgend ist an einem Beispiel die Leistungsfähigkeit gezeigt. Mit der relativ kurzen Routine

    void testScan(StringJc src, ExcampleScannedValues* values)
    {
     bool scanOk;
     StringPartJc sp(src);  //in stack, call ctor
     sp.setIgnoreWhitespaces(true);
     do {
      if(scanOk = sp.scan("value_A").scan("=").scanInteger().scan(";").scanOk()){
         values->value_A = (int32)sp.getLastScannedIntegerNumber();
       }
       else if(scanOk = sp.scan(z_StringJc("value_B")).scan(z_StringJc("=")).scanFloatNumber().scan(z_StringJc(";")).scanOk()){
         values->value_B = (float)sp.getLastScannedFloatNumber();
       }
       else if(scanOk = sp.scan(z_StringJc("value_C")).scan(z_StringJc("=")).scanFloatNumber().scan(z_StringJc(";")).scanOk()){
         values->value_B = (float)sp.getLastScannedFloatNumber();
       }
       else if(scanOk = sp.scan(z_StringJc("value_D")).scan(z_StringJc("=")).scanHexOrDecimal(8).scan(z_StringJc(";")).scanOk()){
         if(values->ixValue_D < ARRAYLEN(values->value_D)){
           values->value_D[values->ixValue_D++] = (int)sp.getLastScannedIntegerNumber();
         } else { /*overflow of user array. */ }
       }
     } while(scanOk);
    }
    

    wird ein gegebener Text src geparst. Er kann Elemente der Syntax

    value_X = wert;
    

    in beliebiger Reihenfolge enthalten. Das ist ein Beispiel für Parameter-Angaben. value_X kann eines der abgefragten Texte sein, je nachdem wird der Wert in die Ziel-Struktur values entsprechend eingetragen.

    Für die Gestaltbarkeit eines solchen Input-Textes beispielsweise für Parameter-Angaben ist folgendes wichtig:

    Der Letzte Punkt ist hier gegeben, in dem die Position im Text nach der Bearbeitung getestet und angegeben wird. Ist noch Text nach dem Scannen vorhanden, dann ist das ein unverarbeitbarer also syntaktisch fehlerhafter Text ab der nicht mehr abgearbeiteten Position. Alle anderen Punkte werden durch die interne Leistungsfähigkeit der class StringPart abgedeckt. Leerzeichen als 'Whitespaces' werden deshalb immer vor jedem Test überlesen, weil es anfänglich so angegeben wurde. Man kann auch Kommentare überlesen lassen und dabei die Kommentareinleitungs- und -ausleitungs-Zeichenfolgen sowie getrennt davon die Einleitungszeichenfolge eines Zeilenend-Kommentars angegeben.

    Das Parsen des Textes erfolgt hier so, dass jede einzelne scan...-Operation nur ausgeführt wird, wenn die vorige Operation erfolgreich war. Damit wird auch Rechenzeit gespart. Das Ganze geht jedesmal bis zu dem scanOk(). Diese Routine setzt die aktuelle scan-start-Position auf die erreichte Position, wenn die vorigen Aufrufe erfolgreich waren.

    Die Aufrufvariante in C benötigt für das selbe Beispiel etwas mehr Schreibaufwand, weil die Schreibweise des verketteten Aufrufes hier nicht so möglich ist. Zwar liefern auch die C-Routinen immer die Instanz als Zeiger zurück. Das nützt aber nichts, da der Zeiger nicht links vor der Routine steht wie in C++ sondern der erster Aufrufparameter ist. Daher ist es einfacher, die Instanz immer wieder zu benennen. Um auch in C dennoch alles in einem if(...)-Aufruf unterzubringen, kann man die Komma-Schreibweise nutzen. Diese ist nicht sehr gebräuchlich, aber auch ein C-Standard. Die C-Routine dieses Beispiels hat damit die folgende Form:

     void testScan(StringJc src, ExcampleScannedValues* values)
     {
       bool scanOk;
       StringPartJc_s sp = CONST_StringPartJc(&sp);
       STACKTRC_ENTRY("testCpp");
       ctorO_S_StringPartJc(&sp.base.object, src, _thCxt);
       setIgnoreWhitespaces_StringPartJc(&sp,true, _thCxt);
       do {
         if( scan_StringPartJc_F(&sp, z_StringJc("value_A"), _thCxt)
           , scan_StringPartJc_F(&sp, z_StringJc("="), _thCxt)
           , scanInteger_StringPartJc_F(&sp, _thCxt)
           , scan_StringPartJc_F(&sp, z_StringJc(";"), _thCxt)
           , scanOk = scanOk_StringPartJc_F(&sp, _thCxt)
           ){
           values->value_A = (int32)getLastScannedIntegerNumber_StringPartJc(&sp, _thCxt);
         }
         else
         if( scan_StringPartJc_F(&sp, z_StringJc("value_B"), _thCxt)
           , scan_StringPartJc_F(&sp, z_StringJc("="), _thCxt)
           , scanFloatNumber_StringPartJc_F(&sp, _thCxt)
           , scan_StringPartJc_F(&sp, z_StringJc(";"), _thCxt)
           , scanOk = scanOk_StringPartJc_F(&sp, _thCxt)
           ){
           values->value_B = (float)getLastScannedFloatNumber_StringPartJc_F(&sp, _thCxt);
         }
         else
         if( scan_StringPartJc_F(&sp, z_StringJc("value_C"), _thCxt)
           , scan_StringPartJc_F(&sp, z_StringJc("="), _thCxt)
           , scanFloatNumber_StringPartJc_F(&sp, _thCxt)
           , scan_StringPartJc_F(&sp, z_StringJc(";"), _thCxt)
           , scanOk = scanOk_StringPartJc_F(&sp, _thCxt)
           ){
           values->value_C = getLastScannedFloatNumber_StringPartJc_F(&sp, _thCxt);
         }
         else
         if( scan_StringPartJc_F(&sp, z_StringJc("value_D"), _thCxt)
           , scan_StringPartJc_F(&sp, z_StringJc("="), _thCxt)
           , scanHexOrDecimal_StringPartJc_F(&sp, 8, _thCxt)
           , scan_StringPartJc_F(&sp, z_StringJc(";"), _thCxt)
           , scanOk = scanOk_StringPartJc_F(&sp, _thCxt)
           ){
           if(values->ixValue_D < ARRAYLEN(values->value_D)){
             values->value_D[values->ixValue_D++] = (int32)getLastScannedIntegerNumber_StringPartJc_F(&sp, _thCxt);
           } else { /*overflow of user array. */ }
         }
       } while(scanOk);
       STACKTRC_LEAVE;
     }
    

    Im Beispiel werden die finalen varianten der C-Routinen gerufen (...StringPartJc_F). Fast alle Routinen in der originalen StringPart.java sind nicht final, also überladbar. Damit hat man generell die Möglichkeit, mittels einer abgeleiteten Klasse Eigenschaften zu modifizieren. Auch intern werden gegebenenfalls überladene Routinen gerufen, beispielsweise für Überlesen von Whitespaces. Das gilt nun auch für die C-Routine und benötigt ein klein wenig mehr Rechenzeit, praktisch aber wohl weniger genutzt. Es lässt sich aber auch eine finale Version von StringPart.java realisieren, die dann in C dieses Stück optimaler arbeitet. Meistenteils dürfte es jedoch so sein, dass für String-Verarbeitungsroutinen dieser Art, also suchen, parsen, etwas mehr Rechenzeit zur Verfügung steht, auch auf preiswerterer Hardware.

     
    

    1.13 Einsatz der class StringFormatterJc

    Topic:.String_Jc.StringFormatter.

    Diese Klasse kann als Gegenstück von StringPart angesehen werden. Ihre Aufgabe ist nicht das Einlesen, Parsen sondern die Ausgabe. Die Klasse ist wie javadoc-src:_org/vishia/util/StringPart in Java geschrieben: javadoc-src:_org/vishia/util/StringFormatter und unterstützt dort eine Ausgabe mit einer höheren Aufbereitungsfunktionalität als in sunJavadoc/java/lang/String und sunJavadoc/java/lang/StringBuilder angeboten. Beispielsweise ist die Hexa-Ausgabe besser steuerbar, eine ganze Zeile wird aufbereitet. Die Ausgabe von float-Werten in möglichst kurzer Form und Dreier-Exponentschritte wird mit javadoc-src:_org/vishia/util/StringFormatter#addFloatPicture(float, java.lang.String) ebenfalls hier bereitgestellt. Routinen der Konvertierung numerisch in String werden hier ähnlich wie in StringPart.java low-level ausgeführt. Das ist in Java ähnlich optimal wie in C und benötigt nicht etwa eine spezialisierte in Assembler geschriebene Library. Diese Klasse ist in C oder C++ verfügbar über die Java2C-übersetzte Form.


    1.14 Rechenzeitvergleich

    Topic:.String_Jc.calcTime.

    Im Java2C-Beispiel javadoc-src:_org/vishia/java2C/test/TestString#testStringProcessing() werden drei Methoden gerufen: TestString_classic.concatenate(...), testStringConcatenationInStack(...) und testStringConcatenationWithTemps(...). Die classic-Methode ist direkt in C ausprogrammiert unter Nutzung von sprintf(..). Die beiden anderen Methoden sind in Java als Quelle programmiert und werden nach C umgesetzt. In der InStack-Methode sind Annotations so angebracht, dass ausschließlich mit temporären instanzen im Stack gearbeitet wird, wogegen die WithTemps-Methode keinerlei Annotations angebracht sind. Benutzt wurde Visual Studio 6.0.

    Die direkt in C programmierte Methode mit sprintf ist etwas langsamer. 10 Aufrufe nacheinander benötigen 68 µs mit einem Intel-Atom-Prozessor 1.6 GHz. Das dürfte daran liegen, dass sprintf eigentlich ein kleiner Interpreter ist: Die Zeichenkette wird auf %Format geprüft, dann wird die entsprechende Konvertierungsroutine gerufen. Dagegen erfolgt der Aufruf der StringBuilderJc-Routinen direkt.

    Die von Java nach C übersetzte Methode, die die CRuntimeJavalike ohne dynamischen Speicher nutzt, benötigt für gleiche Bedingungen 63 µs. Die Zeiten schwanken etwas, das ist beim Test auf dem PC normal (Cache-Nutzung usw.). Mehrere Aufrufe unter verschiedenen Bedingungen zeigten adequate Ergebnisse. Wichtig ist, dass die Compilierung optimiert erfolgt (kein Debug-Mode), denn die Standard-C-Libraries ist ebenso compiliert. Dabei erfolgt in den StringBuilderJc-Routinen der Test der Parameter, Verhinderung des Pufferüberlaufs, Stacktrace-Organisation für den Fehlerfall, alles Dinge, die bei sprintf fehlen und schon lange Testzeiten bedingt haben weil ein Fehler dort nicht erkannt wurde.

    Der Vergleich muss bei einer anderen Plattform selbstverständlich neu ausgeführt werden. Aus diesen Messungen kann man als Richtwert für langsamere Prozessoren folgendes abschätzen: Da aufgrund des wiederholten Aufrufes der Maschinencode schon im Cache ist, kann man die Core-Taktfrequenz des Prozessors als Vergleich ansetzen. Die 10 Aufrufe mit je 3 String-Verkettungen benötigen daher ca. 2 µs pro String-Verkettung. Das sind ca. 1000 Maschinenbefehle, wenn man unterstellt, dass der Atom-Prozessor im Schnitt 3 Quarztakte pro Befehl benötigt. Für weniger leistungsstarke Prozessoren, wie sie in Embedded-Plattformen oft eingesetzt werden, muss man dann mit 10..50 µs für eine solche Aktion rechnen (300 MHz-Takt, oder 50 MHz-Takt aber oft 1 Befehl pro Takt). Für eine schnelle Interruptzeitscheibe, etwa 200 µs Abtastzeit, ist das sowieso ungeeignet. Man ist dann besser beraten, in der schnellen Zeitscheibe lediglich einen Integerwert etwa als Message-nummer zu setzen und Begleitwerte zur Message geeignet statisch zu speichern und die Melde-Ausgabe in einer anderen Zeitscheibe aufzubereiten. Hat man so etwas wie eine 10 ms-Zeitscheibe, dann kann man einen String im Fehlerfall schonmal aufbereiten. - Die Frage, wie lange eine String-Aufbereitung mit einer C++-String-Klasse dauert, wurde übrigens nicht untersucht.

    Die String-Aufbereitung unter Nutzung des dynamischen Speichers dauerte etwa 2000 µs, also um den Faktor 10 länger, also echt länger. Unbrauchbar in einer 10 ms-Zeitscheibe. Oder ? Das originale Java war mit dem gleichen Algorithmus doppelt so schnell, was für die Qualität der Virtuellen Maschine spricht. Aber auch unbrauchbar für kurze Abtastzeiten. Schlussfolgerung: Hier muss noch optimiert werden.

    Die Schlussfolgerungen sind:


    2 Generierte Doku aus Headerfiles

    Nachfolgende Dokumentation ist direkt aus den Headerfile-Kommentierungen

         in Object_Jc.h generiert, daher in englisch:
    

    2.1 ByteStringJc

    UML=/Package[fw_String_h]/Namespace.ownedElement[]/Class[ByteStringJc]

    Class ByteStringJc definiert in fw_String_h

    UML=/Package[fw_String_h]/Namespace.ownedElement[]/Class[ByteStringJc]

    CLASS_C_Description: The type ByteStringJc is the same as struct OS_PtrValue from the OSAL level (Operation System Adaption Layer). That type is designed to represent a structure, which is returned by value in 2 registers. Because it is defined in the compiler- and system-specific headerfile os_types_def.h, it can and should be adapted to the target system conditions independently of user programming.

    Because the feature of representation of a struct in registers, the usage of return per value and typically call per value for the type ByteStringJc is possible and proper.

    The ByteStringJc referes to a String which has byte-characters. The encoding is determined by the using software.

    Methoden:

    length_ByteStringJc (STR) :
    • STR: -

    • returns: -

    data_ByteStringJc (STR) :
    • STR: -

    • returns: -

    byteAt_ByteStringJc (STR, pos) :
    • STR: -

    • pos: -

    • returns: -


    2.2 Fw_String

    UML=/Package[fw_String_h]/Namespace.ownedElement[]/Class[Fw_String]

    Class Fw_String definiert in fw_String_h

    UML=/Package[fw_String_h]/Namespace.ownedElement[]/Class[Fw_String]

    CLASS_C_Description: The struct StringJc is the same as struct OS_PtrValue. A StringJc consists of a reference and the number of chars. But the value may contain also an index for enhanced referencing. Therefore the value is mask with some special bit definitions:

    Some methods are basicly. This methods and define are defined in a framework-context and not in the CRuntimeJavallike-Library. This elements are defined in this headerfile and they are named as Fw-String-class for UML-representation of C-Code. The basicly elements are able to use independend of all other features of the CRuntimeJavalike, they are independend simple C constructs with no other dependencies. Therefore there are able to use in a operation system adaption layer or in a operation system implementation too.

    A character string itself, representated in a char-array is named as text in the description parts of this headerfile. A text-literal is a construct written in C like "textliteral". It is stored in machine code commonly in a const memory area and can be referenced by a char const*. Where a instance of StringJc references such an text. The type StringJc consists of the pointer to the text, its length and some other bits, especially the persistent-bit.

    Notation hint: The notation char const* is the same as const char*, but it expresses more stronly, that it is a const-pointer.

    Methoden:

    INIT_StringJc (DST, src, val) :

    Initialize a StringJc instance with the reference to the given constant zeroterminated text. The up till now value inside DST is not respected. This method is usefull to initialize new instances espacially inside the stack.

     A pointer to StringJc structure containing null-values.
    

    NOTE: a pointer is necessary because a const problem occurs otherwise.

    • DST: - The destination instance. The instance is used directly (it is a macro).

    • src: - Any char-array. The src need not be 0-terminated, a 0-char is handled like a normal char.

    • val: - Number of valid chars and persistent bit.. The number of chars should be less than mLength__StringJc but it is not tested here. The Bit mNonPersists__StringJc may be set. The user is responsible to the persistence.

    • returns: - void, don't use inside an expression.

    INIT_s_StringJc (YTHIS, src) :

    Initialize a StringJc instance with an other given StringJc. The up till now value inside DST is not respected. This method is usefull to initialize new instances espacially inside the stack. It is a simple copy.

     A pointer to StringJc structure containing null-values.
    

    NOTE: a pointer is necessary because a const problem occurs otherwise.

    • src: - Any source StringJc

    • returns: - void, don't use inside an expression.

    z_StringJc (src) : StringJc

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Creates a StringJc-reference to the given zero terminated text (char array).
    

    This is a simple way if a method requires a StringJc object as value argument but the user want to write only a constant char literal. It is a fast C-routine, because the StringJc is stored in CPU-registers, no memory is need. The StringJc is designated as persistent, in most of cases a text-literal would be given. The user should not use this method with an argument of a non-persistent buffer, and than use the StringJc as persistent. To build a non-persistent String, use Fw_String.INIT_StringJc(...). In typically cases the persistence is not need, because this method is used only to build a temporary StringJc as parameter of a routine, which use the String non-persistent. Than a non-persistent buffer can be used as argument.

    • src: char -

    • returns: StringJc - StringJc-instance per value, it is hold in 2 register by most of C-compilers and therefore effective.

    • javalike - Java builds a String instance automatically, if "text-literal" is given. In Java it is able to write at example "checkChars".indexOf(ch) to convert a char into a index-number. The same it is able to write using indexOf_C_StringJc(z_StringJc("checkChars"), ch) in C javalike.

    zI_StringJc (src, len) : StringJc

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Creates a StringJc reference to the given char array with given length.
    

    This is a common way to get a StringJc-Instance if a char-buffer is given. It is a fast C-routine, because the StringJc is stored in CPU-registers, no memory is need. The StringJc is designated as persistent, mostly the persistence is not need. See z_StringJc(...). See StringJc.toStringFromPersist_zI_StringJc(...) to build a persistent StringJc from a persistent buffer.

    • src: char -

    • len: int - the number of chars valid from text

    • returns: StringJc - StringJc-instance per value, it is hold in 2 register by most of C-compilers and therefore effective.

    isNull_StringJc (STR) :

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Returns true if the StringJc contains null. The user should use this macro instead straigtly using of the basicly definitions,
    

    because the definition of OS_PtrValue and therefore the definition of StringJc is os-specific.

    • STR: - StringJc-instance to test. The macro uses the instance directly.

    • returns: - true only if the text-reference is null. false if it is an empty or non-empty text.

    isEmpty_s0_Fwc (TEXT) :

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

    • TEXT: -

    • returns: -

    length_StringJc (ythis) : int

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Returns the length. If the source stores the value mLength__StringJc in its value-element,
    

    the length is got calling strlen(ptr). Otherwise the length is the value-element, mask with mLength__StringJc, independent of the text. The text may contain 0-chars inside the given length.

    • returns: int - The length of the text.

    copyToBuffer_StringJc (ythis, buffer, maxSizeBuffer) : int

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Copy the content to a buffer of the user.
    

    The text will be terminated with 0 always. If the src text is to long. it will be truncated. If the returned length == maxSizeBuffer-1, it is not determined whether the text is truncated or not. Note: if the src-text (ythis) contains 0-characters in its active area, they will be copied too as normal chars.

    • buffer: char - The destination buffer as char[]

    • maxSizeBuffer: int - The number of bytes in Buffer.The max number of chars copied is maxSizeBuffer -1

    • returns: int - number of chars copied. It is the number of valid chars in buffer always.

    getCharConst_StringJc (thiz, buffer, zBuffer) : char

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Gets a zero-terminated String from a given String.
    

    This routine uses a buffer to copy the string. This buffer is used only if the given String is not zero-terminated already. If the String is zero-terminated in its original StringJc-reference, it is used without copying. In that case some calculation time will be saved. Only if the given String is not zero-termintated, the given part of string will be copied and terminated with a 0-character.

    If the length of the given String is greater then zBuffer-1, it is truncated. In this case the last character in the buffer is replaced with a '?'. Usual the length of the string may be limitated, the application may provide a buffer with enough size. The application can check whether strlen(buffer) == sizeof(buffer)-1 && buffer[strlen(buffer)] =='?'. In that case the String may be truncated. Otherwise an outputted String may be recognized as truncated.

    See also gets0_StringJc(...)

    • thiz: StringJc -

    • buffer: char - any buffer, where the content of thiz may be copied to.

    • zBuffer: int - size of the buffer. The size should be the really size. A \0 is guaranted at end of buffer.

    • returns: char - The pointer to the zero terminated String. Either it is the String referenced in thiz, or it is buffer.

    charAt_StringJc (YTHIS, idx) :

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Returns the char at position idx.
    
    • idx: - The index. It should be a positiv number and less than the length of the text. Because this is a fast access using a macro, the index in not tested. If the index is fault, an undefined value is returned. If the built position with this index is outside the memory area, an memory exception can be thrown. Therefore: Only use correct indices.

    • returns: - character at the position of text + idx.

    • javalike - sunJavadoc/java/lang/String#charAt(int) but a test of idx is not done.

    getCharsAndLength_StringJc (ythis, length) : char

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

    • length: int -

    • returns: char -

    PTR_StringJc (YTHIS) :

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Returns the pointer to the character text itself. Note: It is not a 0-terminated text.
    

    The pointer should used only for memory management tests. see getCharsAndCount_StringJc(...).

    • returns: - memory address of the text itself. The type is char const*.

    VAL_StringJc (YTHIS) :

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Returns the value which is stored in the SRC.
    

    This macro should be used inside only. The value contains the length mask with mLength__StringJc, the bit mNonPersists__StringJc and some additonal bits for enhanced-reference management (used for BlockHeap or another memory management).

    • returns: - value which is stored in the StringJc instance. The length of the text is mask with mLength__StringJc defined in the headerfile fw_Platform_conventions.h. If the bit mNonPersists__StringJc is set (see fw_Platform_conventions.h), than the referenced text may be not persistent. It may be located especially in the stack or in the thread context. If this bit is not set, than the StringJc should dedicated as persistent.

    isPersistent_StringJc (YTHIS) :

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Returns whether the StringJc should dedicated as persistent.
    
    • returns: - true if it should be persistent. The text is persistent really, if the user has kept in mind all building rules. The contract is: The user has to do so, and the StringJc referes a persistent text, if this routine returns true.

    isZeroTerminated_StringJc (ythis) : bool

    A pointer to StringJc structure containing null-values. NOTE: a pointer is necessary because a const problem occurs otherwise.

     Checks whether the text refered from this instance is zero-terminated.
    

    Note: The zero-termination is not a necessary property of any String and it cannot assumed. But in some cases, dependently from the source of the String, the zero-termination is given. It is a unexpensive machine code, if the pointer to the referenced text PTR_StringJc() is able to use immediately as a char const* to a zero-terminated text. But the user should test this situation with this method. If the text is not zero-terminated, it have to be copy to a buffer using copyToBuffer_StringJc(...) to get a zero-terminated pointer to the text.

    • returns: bool -

    CONST-Initializer:

    CONST-Initializer sind Makros für C-Konstanten, sie sind in Headerfiles definiert. C-Konstante sind Konstrukte in { ... } mit ausschließlich konstanten Werten. Die Makros der CONST-Initializer übernehmen Argumente, die zur Compilezeit die Konstanten bestimmen. Die Initializer sind deshalb als Makros definiert, weil die Struktur der Konstanten exakt der struct-Definition folgen muss, die struct ist im Headerfile definiert, daher auch dazu passend diese Makros. Mit denCONST-Intializer ist es auf einfache Weise möglich, C-struct-Daten (Plain Old Data) zu initialisieren. Für Klassen (C++) ist dieses Konzept nicht geeignet.

    CONST_StringJc(TEXT, LEN)

    Initializer-Macro for constant StringJc, initialize the StringJc-reference to a text with known length. Using this macro instead CONST_StringJc(...) saves calculation time to calculate the strlen().

    • TEXT - should be a text-literal only. If it references a char-array, a problem with persistence may existing.

    • LEN - The length as number. Do not use methods like strlen(...) to determine the length, because this is a const-initializing-macro. In C++, methods are syntaxtically able to use, but it produces more machine code and the definition cannot store in a const segment. In C it is an error.

    CONST_z_StringJc(TEXT)

    Initializer-Macro for constant StringJc, initialize the StringJc-reference to a zero-terminated text. The length of the text is not stored inside StringJc, the length bits are setted to there maximum (value of mLength__StringJc, see fw_Platform_conventions.h) to detect this constellation.

    • TEXT - should be a text-literal only. If it references a char-array, a problem with persistence may existing.


    2.3 StringJc

    UML=/Package[StringJc_h]/Namespace.ownedElement[]/Class[StringJc]

    Class StringJc definiert in StringJc_h

    UML=/Package[StringJc_h]/Namespace.ownedElement[]/Class[StringJc]

    CLASS_C_Description: The type StringJc is defined in fw_String.h. It is the same as struct OS_ValuePtr from the OSAL level (Operation System Adaption Layer). That type is designed to represent a structure, which is returned by value in 2 registers. Because it is defined in the compiler- and system-specific headerfile os_types_def.h, it can and should be adapted to the target system conditions independently of user programming.

    Because the feature of representation of a struct in registers, the usage of return per value and typically call per value for the type StringJc is possible and proper.

    The headerfile Fwc/fw_String.h defines the type and some basicly functionalities to use a StringJc-instance in a low independent level to refer a text.. This headerfile against that defines the typically String functionality, which followes the sunJavadoc/java/lang/String class-functinality. But some enhancements are given, because the string processing in fast real time embedded systems may work without dynamically memory too.

    A character string itself, representated in a char-array is named as text in the description parts of this headerfile. A text-literal is a construct written in C like "textliteral". It is stored in machine code commonly in a const memory area and can be referenced by a char const*. Where a instance of StringJc references such an text. The type StringJc consists of the pointer to the text, its length and some other bits, especially the persistent-bit.

    Methoden:

    clear_StringJc (ythis) : void

    Clears the content of the String. If the string references any buffer in the BlockHeap, the back references to this enhanced reference will be release. A StringJc is an enhanced reference too. The buffer may be inside the block of BlockHeap as part of a StringBuilderJc, or a substring, it is detected correctly.

    • returns: void -

    set_StringJc (ythis, src) : void

    Set this as reference to a text. The src-text may be a reference to a constant text, or any other text.

    If the src-text in not persistent, a new buffer will be created calling new_StringBuilderJc(...). Note, that that operation causes an exception if no dynamically memory for the new_StringBuilderJc(...) operation is available. Because the routine tests whether the text is persistent, it sh�uld be used in a system without dynamically memory always, to increase the software-safety by runtime-test.

    If the string references any buffer in the block heap, the back references to this enhanced reference will be set. A StringJc is an enhanced reference too. The buffer may be inside the block as part of a StringBuilderJc, or a substring, it is detected correctly.

    • src: StringJc - The source StringJc. It is given per value, not per reference, so direct output from StringJc-returning methods are useable as argument. The value consist of 2 processor registers.

    • returns: void -

    new_BYIICharset_StringJc (bytes, offset, length, charsetName, _thCxt) : StringJc

    Constructs a new String by decoding the specified subarray of bytes using the specified charset. The length of the new String is a function of the charset, and hence may not be equal to the length of the subarray.

    The behavior of this constructor when the given bytes are not valid in the given charset is unspecified. The CharsetDecoder class should be used when more control over the decoding process is required.

    • bytes: - - The bytes to be decoded into characters

    • offset: int - - The index of the first byte to decode

    • length: int - - The number of bytes to decode

    • charsetName: StringJc - - The name of a supported charset

    • returns: StringJc -

    • throws - UnsupportedEncodingException - If the named charset is not supported

    • throws - IndexOutOfBoundsException - If the offset and length arguments index characters outside the bounds of the bytes array

    • since - JDK1.1

    • javalike - String(byte[] bytes, int offset, int length, String charsetName) Note: The actual implementation doesn't support encoding. The method may be improved to convert from any charset to the internal used 8-byte non-UTF8 charset. Internally anytime a char has 8 bit.

    new_vIICharset_StringJc (bytes, offset, length, charsetName, _thCxt) : StringJc

    Constructs a new String by decoding the specified subarray of bytes using the specified charset. The length of the new String is a function of the charset, and hence may not be equal to the length of the subarray.

    The behavior of this constructor when the given bytes are not valid in the given charset is unspecified. The CharsetDecoder class should be used when more control over the decoding process is required.

    • bytes: ByteStringJc - - The bytes to be decoded into characters

    • offset: int - - The index of the first byte to decode

    • length: int - - The number of bytes to decode

    • charsetName: StringJc - - The name of a supported charset

    • returns: StringJc -

    • throws - UnsupportedEncodingException - If the named charset is not supported

    • throws - IndexOutOfBoundsException - If the offset and length arguments index characters outside the bounds of the bytes array

    • since - JDK1.1

    • javalike - String(byte[] bytes, int offset, int length, String charsetName) Note: The actual implementation doesn't support encoding. The method may be improved to convert from any charset to the internal used 8-byte non-UTF8 charset. Internally anytime a char has 8 bit.

    new_CY_StringJc (chars, _thCxt) : StringJc

    Returns the StringJc to the text which is stored in the given char-array. This method is able to use without dynamically memory.

    • chars: - Char-array.

    • returns: StringJc - non-peristent String zo the char array.

    • javalike - The method is defined in Java, but in opposite to Java no new string data were created. The returned String is a non-persistent String. The persistence will be produced while storing the String or calling persist_StringJc(...)

    new_CYI_StringJc (chars, offset, count, _thCxt) : StringJc

    Returns the StringJc to the text which is stored in the given char-array. This method is able to use without dynamically memory.

    • chars: - Char-array.

    • offset: int - start of text inside the Char-array

    • count: int - number of chars.

    • returns: StringJc - non-peristent String zo the char array.

    • javalike - The method is defined in Java, but in opposite to Java no new string data were created. The returned String is a non-persistent String. The persistence will be produced while storing the String or calling persist_StringJc(...)

    persist_StringJc (src) : StringJc

    Builds a persistent String, if the given String is non-persistent. This routine calls new_StringBuilderJc(...) if the String is non-persistent. The routine may not able to use in a system without any management of dynamically memory for text buffers. If a new text buffer is not able to allocate, an Exception is thrown. See Implementation of new_StringBuilderJc(...).

    • src: StringJc - any String, may be persistent or not

    • returns: StringJc - a persistent String. If src is persistent, src will be returned.

    declarePersist_StringJc (ythis) : StringJc

    Declares this string as persistent. The routine should be applied only to a String, which references a staticly buffer, which is persistent really. Attention: Do not apply to Strings in stack or thread-context.

    copyToThreadCxt_StringJc (src, _thCxt) : StringJc

    Copies the referenced text in the Thread-Context-Buffer and returns the reference to it. This method should be used especially if a routine should return a String, which is buffered in the stack up to now.

    gets0_StringJc (thiz, buffer, zBuffer, exceptionOnLessBuffer, _thCxt) : char

    Gets a zero-terminated String from a given String. This routine needs a buffer to copy the string. But if the given String is zero-terminated already, It is used without copying. In this case some calculation time will be saved. Only if the given String is not zero-termintated, the given part of string will be copied and terminated with a 0-character. If the length of the given String is greater then zBuffer-1, either an exception will be thrown or the String will be truncated.

    • thiz: StringJc -

    • buffer: char - any buffer, where the content of thiz may be copied to.

    • zBuffer: int - size of the buffer. The size should be the really size. A \0 is guaranted at end of buffer.

    • exceptionOnLessBuffer: bool - true then an exception is thrown if (zBuffer -1) is less then the length of thiz and thiz is not zero-terminated. If the string refered with thiz is zero terminated, an exception is never thrown. If false, then the string will be truncated. The parameter _thCtx may be null then.

    • returns: char - The pointer to the zero terminated String. Either it is the String referenced in thiz, or it is buffer.

    equals_StringJc (ythis, cmp) : bool

    Compares this string to the specified String.

    • cmp: StringJc - the String to compare

    • returns: bool - The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.

    • javalike - But the cmp-Parameter is of type StringJc always. sunJavadoc/java/lang/String#equals(java.lang.Object)

      NOTE compatibility with java: In Java this routine is defined as overrideable method of Object, the cmp-Parameter is of type Object. Java tests whether the parameter is of instance type String (String is derived from Object). Only if the parameter is of type java.lang.String this method compares the text. Otherwise it returns true if the instances this and cmp are the same instance, elsewhere returns false. There is not a call of Object.toString(). The Java2C-Translator tests, whether the parameter is of type String and generates the call of this method with the given String directly. If the parameter is of type Object or void*, a simple comparision of the addresses of the instances will be generated. That is the same behaviour as in Java. The comparision of Objects, which are the same String-instances, may be necessary if the reference to the String is stored in a List<Object>. This behaviour ist tested by me with Java Version 6, and it is documented in Sun-Javadoc.

    equals_zI_StringJc (ythis, strCmp, valueCmp) : bool

    Compares this string to the specified character text.

    • strCmp: char - Any character text

    • valueCmp: int - Number of chars to compare, but mask with mLength__StringJc. If -1 or all bits of mLength__StringJc are set, than the length is got from strlen_Fwc(sCmp, mLength__StringJc), The other bits were not used.

    • returns: bool - The result is true if and only if the argument is not null and the text of this represents the same sequence of characters as strCmp.

    equals_z_StringJc (YTHIS, CMP) :

    Compares this string to the specified text. The result is true if and only if the argument is not null and the StringJc referes the same sequence of characters as this object.

    • CMP: - 0-terminated String to compare with this.

    • returns: - The result is true if and only if the argument is not null and is a text that represents the same sequence of characters as this object.

    startsWith_StringJc (ythis, cmp) : bool

    Tests if this string starts with the specified prefix. javalike, see String.startsWith(String)

    • cmp: StringJc - String to compare.

    • returns: bool - true if the given String starts with the same character sequence as cmp.

    startsWith_zI_StringJc (ythis, strCmp, valueCmp) : bool

    Tests if this string starts with the specified prefix.

    • strCmp: char - pointer to a text (char const*).

    • valueCmp: int - number of chars to cmp. If it is -1, the strCmp is accepted as 0-terminated String.

    • returns: bool - true if the given String starts with the same character sequence as cmp.

    startsWith_z_StringJc (YTHIS, CMP) :

    Tests if this string starts with the specified prefix.

    • CMP: - pointer to a text (char const*) as 0-terminated text.

    • returns: - true if the given String starts with the same character sequence as cmp.

    endsWith_StringJc (ythis, cmp) : bool

    Tests if this string ends with the specified prefix. javalike, see String.endsWith(String)

    • cmp: StringJc - String to compare.

    • returns: bool - true if the given String ends with the same character sequence as cmp.

    endsWith_zI_StringJc (ythis, strCmp, valueCmp) : bool

    Tests if this string ends with the specified suffix. This is the base variant of the method.

    • strCmp: char - The suffix

    • valueCmp: int - The value from a StringJc, or the number of chars. Only bits mask with mLength__StringJc (defined in fw_Platform_Conventions.h) are considered. If this parameter is equal mLength__StringJc, than the param strCmp is recognized as 0-terminated text.

    • returns: bool - true if the given String ends with the same character sequence as cmp.

    endsWith_z_StringJc (YTHIS, CMP) :

    Tests if this string ends with the specified suffix.

    • CMP: - The suffix as 0-terminated text.

    • returns: - true if the given String ends with the same character sequence as cmp.

    substring_StringJc (ythis, beginIndex, endIndex, _thCxt) : StringJc

    Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.

    • beginIndex: int -

    • endIndex: int - the ending index, exclusive. If -1, than the endIndex is the length of string, This is used to support the Java-form without parameter endIndex. Java causes an excpetion in this case.

    • returns: StringJc -

    • throws - IndexOutOfBoundsException - if the beginIndex is negative, or endIndex is larger than the length of this String object, or beginIndex is larger than endIndex.

    • javalike - Lightly modified from Java, see sunJavadoc/java/lang/String#substring(int, int)

    substring_I_StringJc (STR, BEGIN, _THC) :

    Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the length of the given String..

    subSequence_StringJc (STR, BEGIN, END, _THC) :

    Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.

    • STR: -

    • BEGIN: -

    • END: -

    • returns: -

    • throws - IndexOutOfBoundsException - if the beginIndex is negative, or endIndex is larger than the length of this String object, or beginIndex is larger than endIndex.

    • javalike - Lightly modified from Java, see sunJavadoc/java/lang/String#substring(int, int)

    indexOf_C_StringJc (YTHIS, CH) :

    Returns the index within this string of the first occurrence of the specified character. If a character with value ch occurs in the character sequence represented by this String object, then the index of the first such occurrence is returned -- that is, the smallest value k such that:

     this.charAt(k) == ch
    

    is true. If no such character occurs in this string, then -1 is returned.

    indexOf_CI_StringJc (ythis, ch, fromIndex) : int

    Returns the index within this text of the first occurrence of the specified character, starting the search at the specified index.

    If a character with value ch occurs in the character sequence represented by this text object at an index no smaller than fromIndex, then the index of the first such occurrence is returned --that is, the smallest value k such that:

     (this.charAt(k) == ch) && (k >= fromIndex)
    

    is true. If no such character occurs in this text at or after position fromIndex, then -1 is returned.

    There is no restriction on the value of fromIndex. If it is negative, it has the same effect as if it were zero: this entire text may be searched. If it is greater than the length of this text, it has the same effect as if it were equal to the length of this text: -1 is returned. Same as in Java.

    • ch: int - - a character.

    • fromIndex: int - the index to start the search from.

    • returns: int - the index of the first occurrence of the character in the character sequence represented by this object, or -1 if the character does not occur.

    • javalike - sunJavadoc/java/lang/String#indexOf(int, int) without CodePoint-support.

    indexOf_sI_StringJc (ythis, str, fromIndex) : int

    Searches the text within the given String.

    • str: StringJc - text to search referenced with a StringJc

    • fromIndex: int - start position to search.

    • returns: int - position of the first occurence counted from start of this String (first position is 0). The return value is alway >= fromIndex, if the str is contained in this. Return -1 if the str is not contain in this.

    indexOf_s_StringJc (YTHIS, str) :

    Searches the text within the given String.

    indexOf_zI_StringJc (YTHIS, str, FROMINDEX) :

    Searches the text within the given String.

    • str: - text to search referenced with a StringJc. It is a 0-termninated simple char const* (recommending only string-literals)

    • FROMINDEX: - start position to search.

    • returns: - position of the first occurence from start of this String. The first position is 0. Return -1 if the str is not contain in this.

    indexOf_z_StringJc (YTHIS, str) :

    Searches the text within the given String.

    • str: - text to search referenced with a StringJc. It is a 0-termninated simple char const* (recommending only string-literals)

    • returns: - position of the first occurence from start of this String. The first position is 0. Return -1 if the str is not contain in this.

    lastIndexOf_CI_StringJc (ythis, ch, fromIndex) : int

    Searches the character within the given String backward started from fromIndex.

    • ch: int - Char to search

    • fromIndex: int - start position to search backward. There is no restriction on the value of fromIndex. If it is greater than or equal to the length of this string, it has the same effect as if it were equal to one less than the length of this string: this entire string may be searched. If it is negative, it has the same effect as if it were -1: -1 is returned.

    • returns: int - position of the last occurence of the char in this String, which is less or equal fromIndex. Return -1 if the str is not contain in this range.

    lastIndexOf_C_StringJc (YTHIS, ch) :

    Searches the character within the given String backward started from end.

    lastIndexOf_sI_StringJc (ythis, str, fromIndex) : int

    Searches the text within the given String backward started from fromIndex.

    • str: StringJc - text to search referenced with a StringJc

    • fromIndex: int - start position to search backward. If the text starts at this position with its first char, it is found. There is no restriction on the value of fromIndex. If it is greater than or equal to the length of this string, it has the same effect as if it were equal to one less than the length of this string: this entire string may be searched. If it is negative, it has the same effect as if it were -1: -1 is returned.

    • returns: int - position of the last occurence of the text in this String, which is less or equal fromIndex. Return -1 if the str is not contain in this range.

    lastIndexOf_s_StringJc (YTHIS, str) :

    Searches the text within the given String backward started from end.

    lastIndexOf_zI_StringJc (YTHIS, str, fromIndex) :

    Searches the text within the given String backward started from fromIndex.

    • str: - text to search referenced with a StringJc. It is given as 0-termninated simple char const* (recommending only string-literals)

    • fromIndex: - start position to search backward. If the text starts at this position with its first char, it is found. There is no restriction on the value of fromIndex. If it is greater than or equal to the length of this string, it has the same effect as if it were equal to one less than the length of this string: this entire string may be searched. If it is negative, it has the same effect as if it were -1: -1 is returned.

    • returns: - position of the last occurence of the text in this String, which is less or equal fromIndex. Return -1 if the str is not contain in this range.

    lastIndexOf_z_StringJc (YTHIS, str) :

    Searches the text within the given String backward started from fromIndex.

    • str: - text to search referenced with a StringJc. It is given as 0-termninated simple char const* (recommending only string-literals)

    • returns: - position of the last occurence of the text in this String. Return -1 if the str is not contain in this range.

    format_a_StringJc (format, typeArgs) : StringJc

    Returns a formatted string using the specified format string and arguments.

    • format: StringJc - A format string

    • typeArgs: char - 0-terminated text with the type chars for the following arguments. The arguments should be matching to the format String generally. But some modifications are allowed, see behaviour in Java. The type of the following arguments need 1 char per argument.

      • The char is BSIJFDZ for the basicly types int8, int16, int32, int64, float, double and boolean. The int-types are adequate the Java-types byte, short, int, long.

      • The char is szP for argument Types StringJc, char const* and void*. A void* will be shown with its pointer value, like used on sprintf.

      • An ObjectJc as argument is not supported yet. It should have the o as character, and the toString-Method should be invoked (TODO).

    • returns: StringJc - The formatted string, buffer in Thread-Context

    • javalike - sunJavadoc/java/lang/String#format(java.lang.String, java.lang.Object...). But the kind of handling with the variable argument list is modified. In Java the arguments are all of type Object, derived from it, and its type is able to test. In the C-Implementation the argument list is handled like described in <stdarg.h>. The types of the arguments should be given extra. The Java2C-Translator translates it correctly.

    format_za_StringJc (format, typeArgs) : StringJc

    Returns a formatted string using the specified format string and arguments.

    • format: char - A format string as 0-terminated text, recommended a text-literal.

    • typeArgs: char - Type of the Arguments referenced by the format specifiers in the format string. If there are more arguments than format specifiers, the extra arguments are ignored. The number of arguments is variable and may be zero. The maximum number of arguments is limited by the maximum dimension of a Java array as defined by the Java Virtual Machine Specification. The behaviour on a null argument depends on the conversion.

    • returns: StringJc - The formatted string, buffer in Thread-Context

    format_A_StringJc (format, vargList, _thCxt) : StringJc

    Returns a formatted string using the specified format string and arguments.

    • format: StringJc - A format string

    • vargList: Va_listFW - Arguments referenced by the format specifiers in the format string. If there are more arguments than format specifiers, the extra arguments are ignored. The number of arguments is variable and may be zero.

    • returns: StringJc - The formatted string, buffer in Thread-Context

    • javalike - sunJavadoc/java/lang/String#format(java.lang.String, java.lang.Object...). But the kind of handling with the variable argument list is modified. In Java the arguments are all of type Object, derived from it, and its type is able to test. This C-Implementation gets the argument list in form of a special structure.

    toString_DoubleJc (value, _thCxt) : StringJc

    Returns a string representation of the double argument. All characters mentioned below are ASCII characters. The representation is following the output of sprintf.

    valueOf_I_StringJc (VAL) :

    Returns the string representation of the int argument. The representation is exactly the one returned by the Int.toString method of one argument

    valueOf_D_StringJc (VAL) :

    Returns the string representation of the double argument. The representation is exactly the one returned by the Double.toString method of one argument

    replace_StringJc (ythis, oldChar, newChar, _thCxt) : StringJc

    Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar. If the character oldChar does not occur in the character sequence represented by this String object, then a reference to this String object is returned. Otherwise, a new String object is created that represents a character sequence identical to the character sequence represented by this String object, except that every occurrence of oldChar is replaced by an occurrence of newChar.

    replace_u_StringJc (ythis, oldChar, newChar, buffer, _thCxt) :

    Replaces the chars using a StringBuilder-buffer to store the result.

    • oldChar: char - The char which was to replace at any occurence.

    • newChar: char - Char to set.

    • buffer: - A StringBuilder-Instance to use as buffer for the result String. The buffer of the StringBuilder is intitialized with the content of the given text. It is typically, that the text of this is stored already in the buffer, because the same buffer in used to build the string. That situation is detected by compare the reference to the text in this and the buffer-address.

    • returns: - the given StringBuilder-Instance.

    • javalike - : Java doesn't know a simple method to replace chars in a StringBuilder. This method is created firstly to support String.replace(...), if the buffer is known and the String should not persistent. This conditions can be given by Java2C-Translation as annotations in the Java-source. Than the replacement works time-optimal.

    getChars_StringJc (ythis, srcBegin, srcEnd, dst, dstBegin, _thCxt) : void

    copies the content of the src into a char*-buffer. Copies characters from this string into the destination character array. The first character to be copied is at index srcBegin; the last character to be copied is at index srcEnd-1 (thus the total number of characters to be copied is srcEnd-srcBegin). The characters are copied into the subarray of dst starting at index dstBegin and ending at index:

      dstbegin + (srcEnd-srcBegin) - 1
    
    • srcBegin: int - index of the first character in the string to copy.

    • srcEnd: int - index after the last character in the string to copy.

    • dst: - the destination array.

    • dstBegin: int - the start offset in the destination array.

    • returns: void -

    • throws - IndexOutOfBoundsException - If any of the following is true:

      • srcBegin is negative.

      • srcBegin is greater than srcEnd

      • srcEnd is greater than the length of this string

      • dstBegin is negative

      • dstBegin+(srcEnd-srcBegin) is larger than dst.length.

    getBytes_StringJc (STR, THCXT) :

    Returns the String as byte stream.

    • STR: -

    • THCXT: -

    • returns: -

    getBytesEncoding_StringJc (ythis, encoding, _txCtx) : ByteStringJc

    Returns the String as byte stream.


    2.4 StringBufferJc

    UML=/Package[StringBufferJc_h]/Namespace.ownedElement[]/Class[StringBufferJc]

    Class StringBufferJc definiert in StringBufferJc_h

    UML=/Package[StringBufferJc_h]/Namespace.ownedElement[]/Class[StringBufferJc]

    Methoden:

    toStringBuffer_StringJc (src) : StringBufferJc

    Copies the string-reference into a reference of a StringBuffer. Either, the given reference references a string in a StringBuffer, only the content of the reference will be copied. Or the string is a direct String or substring. Than a new StringBuffer-instance will be created.


    2.5 StringBuilderJc

    UML=/Package[StringJc_h]/Namespace.ownedElement[]/Class[StringBuilderJc]

    Class StringBuilderJc definiert in StringJc_h

    UML=/Package[StringJc_h]/Namespace.ownedElement[]/Class[StringBuilderJc]

    A StringBuilderJc is a structure to manage char[]-arrays. It is derivated and adapted from the content of the java.lang.StringBuffer rsp. java.lang.StringBuilder. Some Java-like methods are supplied, but not all, but some methods are additional and specifical for usages in C or C++.

    There are 2 forms of memory layout of this struct:

    The first variant is usefull especially if a C-like text buffer (char* with given size) is located anywhere in the users data structures, and the StringBuilderJc-instance is only used temporary to assemble the text in the buffer.

    The last variant is possible either if a construct like

     struct { StringBuilderJc b; char _b[46];} myBuilder =
       CONST_addSizeStack_StringBuilderJc(&buffer.b, 50);
    

    is defined and initialized or if the ctorO_StringBuilderJc(...)-Constructor is called with an initialized ObjectJc with a size greater than sizeof(StringBuilderJc). It means more memory was allocated. That variant needs only 1 memory block for the buffer management and the buffer itself.

    The StringBuilderJc-instance holds some flags such as located in the Thread Context or buffer is located in Stack and truncated, see the appropriate methods. The internal attributes of this struct should not use immediately, only the methods of this C-class should be used.

    Problem of reallocating a buffer: In Java it's some more easier: Working with dynamically memory is usual, and the buffer is a private element of the StringBuilder. Therefore the buffer can be changed anytime, only a few amount of calculation time is need.

    But in C the StringBuilderJc is often associated with a determined buffer of the user. The user shows to its buffer, The StringBuilder-instance is only a helper to deal with the content. A situation, that an unexpected overflow of the buffer size occurs during an append operation, than the StringBuilder swaps the content in a new allocated buffer, will be a confusion. The user looks to its buffer, no content is changed, why? He doesn't look to the StringBuilder-Instance.

    Because on other side the handling with dynamically memory is restricted often in C-applications, the reallocation of buffer is only suitable by calling the method ensureCapacity. This method is not supported in this version, but it may be supported. Than the user is responsible to the correctness of handling with its old buffer. If the user ensures actively, it should look what it means. If the BlockHeap or an adequate mechanism with equal-size-blocks are used for dynamically memory-management, a new allocated buffer has the highest size of block which are possible in the system. So an enhancement of capacity is not possible. The system limit of equal size blocks are decisive anyway. An increasing is not possible, because the highest size is given anyway.

    The allocation is not limited in startup-phase using BlockHeap, but in a startup phase the allocated memory is used as fix memory on runtime. An accidental buffer for a String-building is not desired mostly.

    Therefore the concept is: An enhancement of content never changes the buffer. Either an exception is thrown (to detect maybe an error of given conditions) or an truncation is done.

    Attributes:

    +-------'-------'-------'-------'-------'-------'-------'-------+
    |                             base                              |
    +-------'-------+-------'-------+-------'-------'-------'-------+
    |    _count     |     size      |            _mode              |
    +-------'-------'-------'-------'-------'-------'-------'-------+
    |                            value                              |
    +-------'-------'-------'-------'-------'-------'-------'-------
    Pos. 0x0..0x13 = 0..19 ( 20 bytes): base :

    It based on ObjectJc.

    Pos. 0x14..0x15 = 20..21 ( 2 bytes): _count : int16

    Actual nr of characters. 0 or positive. All attributes are privave. The struct should use only via its methods.

    Pos. 0x16..0x17 = 22..23 ( 2 bytes): size : int16

    The size of the Buffer and marker to use value. If this number is negative, a buffer is referenced, use value.buffer. If this number is positive, the buffer follows immediately, use value.direct.

    Pos. 0x18..0x1B = 24..27 ( 4 bytes): _mode : int32

    Some mode-bits,see defines _m....

    Pos. 0x1C..0x1F = 28..31 ( 4 bytes): value : value_t

    The buffer itself is either referenced or it is embedded here.

    Inner class StringBuilderJc.value_t definiert in StringJc_h/StringBuilderJc

    UML=/Class[StringBuilderJc]/Namespace.ownedElement[]/Class[value_t]

    The buffer itself is either referenced or it is embedded here.

     The buffer itself is either referenced or it is embedded here.
    

    Methoden:

    INSTACK_StringBuilderJc (name, chars) :

    This macro defines a StringBuffer instance with an additional size to locate in the stack. which is located in the Stack. See CONST_addSize_StringBuilderJc(...) It have to be used if the StringBuilderJc-instance is located in Stack. The mode bits _mStack_StringBuilderJc is set. The definition of such an construct is recommended as astruct definition like following:

    struct { StringBuilderJc b; char _[120]; } uBuffer = { CONST_addSize_StringBuilderJc(&uBuffer.buffer, 120), { 0 }};

    The a StringBuilder with immediately buffer for 123 characters and a 0 on end is placed in the stack. See macro INSTACK_StringBuilderJc(...).

    • name: - The name of the StringBuilder-instance

    • chars: - number of chars inclusive the ending 0-char.

    • returns: -

    finalize_StringBuilderJc_F (othis, _thCxt) : void

    Finalize declaration. It is called by Garbage collector and inside other finalized methods. It should be called by the user if the instance is removed.

    • returns: void -

    ctorO_StringBuilderJc (othis, _thCxt) : StringBuilderJc

    Initializes the Stringbuffer with an immediate buffer after the StringBuffer management values. The size stored inside ObjectJc determines the size of the buffer.

    • returns: StringBuilderJc - the initialized instance at that memory placement.

    • throws - RuntimeException if the memory is to less.

    • javalike - In Java the sunJavadoc/java/lang/StringBuilder#StringBuilder() constructs an empty (small) buffer. The behaviour is similar, but the buffer has its fix size given by memory amount of the instance referes with othis. The difference is, that a realloc of buffer isn't supported.

    ctorO_zI_StringBuilderJc (othis, buffer, size, _thCxt) : StringBuilderJc

    Initializes the Stringbuffer to reference the given buffer with content with the given size. This method should be used if an external char[] is to be used. The nrof chars in the StringBuffer is determined by the content of the buffer with the 0-terminated C-like method. The char[] can also be a part of a char[].

    • buffer: char - A char[...]-buffer with content. write 0 at start if it should be empty.

    • size: int - the nrof bytes for buffer. The size inside the StringBuilderJc is set to this value -1, It is because a last zero-Byte should be able to place any time.

    • returns: StringBuilderJc -

    • javalike - In Java the sunJavadoc/java/lang/StringBuilder(int) constructs an empty buffer with the given size. Here it is similar respectively size, but the location of the buffer is given too. The difference is, that Java uses always the dynamical memory to allocate. where in C more possibilites of determine the locations of memory are need. The possibility of provide an initialized buffer is a combination with the sunJavadoc/java/lang/StringBuilder#StringBuilder(java.lang.string)-constructor.

    ctorO_I_StringBuilderJc (othis, size, _thCxt) : StringBuilderJc

    Initializes a StringBuffer with no characters in it and an initial capacity specified by the capacity argument.

    • size: int - the nrof bytes for buffer. A buffer will be allocated, if the size of the othis is less than size - (sizeof(StringBuilderJc) -4). Otherwise the space after the StringBuilderJc-instance started with the _buffer-Element (last 4 Bytes) is used as buffer.

    • returns: StringBuilderJc -

    • javalike - sunJavadoc/java/lang/StringBuilder#StringBuilder(int) with the difference, that the immediate buffer is supported here. Java allocates the buffer in heap anytime.

    ctorO_s_StringBuilderJc (othis, src, _thCxt) : StringBuilderJc

    Initalizes the given Instance with the content of src.

    • src: StringJc - the initializing content. If the length of src is less or equal the space of the othis for buffer, that buffer will be used. Elsewhere a buffer will be allocated in the heap.

    • returns: StringBuilderJc -

    • javalike - sunJavadoc/java/lang/StringBuilder#StringBuilder(java.lang.String) with the difference, that the immediate buffer is supported here. Java allocates the buffer in heap anytime. The other difference is: A reallocation of buffer is not supported. It means, if str is only the start content and an append will be called, it does fail here if the ctor allocates the space for buffer itself. It does not fail, if the space is allocated in the BlockHeap and the block-size is enaugh (the block size is constant), or if the allocation is done with enaugh space for the instance itself (than the text is stored immediately) or if the instance is embedded and has immediate space for the text after it, like described in CONST_addSize_StringBuilderJc(...).

    new_StringBuilderJc (SIZE, _thCxt) :

    Creates a new StringBuilder-instance if possible. This routine assumes, that dynamically memory is present. In long-running-realtime-applications a dynamic-memory-management may be spurious. But it may be possible to allocate some memory in startupt time. The implementation of this routine uses the routine alloc_ObjectJc(...). This routine may be implemented in a special way adequate to the system definitions.

    • SIZE: - The size for buffer. -1, than the standard size will be used (block size of BlockHeap or other concept).

    • returns: - the instance.

    • throws - Exception if no dynamically memory is available.

    • javalike - call of new StringBuilder(size)

    threadBuffer_StringBuilderJc (_thCxt) : StringBuilderJc

    Returns the StringBuilderJc-instance in the Thread Context. This instance should used if a StringJc is to return. The contract for such returned StringJc is: It should be used immediately, it shouldn't be referenced for further using. The reason therefore is: There is only one instance per Thread. The storing a text in the Thread Context prevent the needness of an extra Buffer.

    • returns: StringBuilderJc - the empty instance in thread-context-buffer. This instance is designated locate in threadBuffer using the mode-bit _mThread_StringBuilderJc.

    threadBuffer_s_StringBuilderJc (src, _thCxt) : StringBuilderJc

    Initializes the StringBuilderJc-instance in the Thread Context with the given String and returns it. This variant is proper to use at example if the src is stored in the Stack and should be returned now. If a StringJc should be returned, use this method and call than toString_StringBuilderJc() or call toStringInThreadCxt_StringBuilderJc(...) with the given StringBuilderJc-instance, it does the same.

    • src: StringJc - The initialized content.

    • returns: StringBuilderJc - the initialized instance in thread-context-buffer. This instance is designated as locate in threadBuffer using the mode-bit _mThread_StringBuilderJc.

    setStringConcatBuffer_StringBuilderJc (YTHIS) :

    Set the stringConcatBuffer flag. A StringBuilderJc-Instance should be dedicated in that way, if the instance is created only to concatenate a text, and there is no other reference to it. If hava to be a persistent location (not in Stack, not in Thread-Context, but allocated dynamically), its buffer is used as the persistent buffer for a StringJc immediately. The allocation of an extra buffer isn't need.

    • returns: - value of _mode, but do not use it. The macro is able to use in a ( expr, expr, ...) form.

    chars_StringBuilderJc (ythis) : char

    Gets the buffer as char* to use in C-Standard-Routines. The buffer content is zero-terminated always.

    • returns: char - 0-terminated content of buffer.

    copyToBuffer_StringBuilderJc (ythis, buffer, zBuffer) : int

    Copies the text in the given buffer. Use the set mode of setTruncateMode_StringBuilderJc(..) to desire, whether an exception is thrown or the text will be truncated if the zBuffer is less.

    • buffer: char - any buffer, where the content of ythis is copied to.

    • zBuffer: int - size of the buffer. The size should be the really size. A \0 is guaranted at end of buffer. It means, the length_StringBuilderJc(ythis) should less as zBuffer, not equal.

    • returns: int - number of chars without the terminating 0-char. The max value is zBuffer -1.

    setTruncateMode_StringBuilderJc (ythis, bTruncate) : bool

    Set the truncate mode. In this mode on buffer overflow the text will be truncated, instead calling an exception. Use wasTruncated_StringBuilderJc() to check whether a truncate was occured.

    • bTruncate: bool - true than truncate without exception, false than cause an exception on buffer overflow.

    • returns: bool - the current mode before.

    wasTruncated_StringBuilderJc (ythis) : bool

    Checks whether the buffer content was truncated any time before. The truncate bit is reseted thereby, so a next call returns false if a new truncation event doesn't occur.

    • returns: bool - true if the buffer content was truncated during an insert-, replace- or append-operation.

    releaseStringBuilt_StringBuilderJc (YTHIS) :

    Releases the buffer from the designation of a built StringJc-reference. The StringBuilder can used now for new changing operations. But see and use also toStringNonPersist_StringBuilderJc(...). If the user calls this method, it should be assured, that no reference is used furthermore, which assumes the previous content. It is a method to optimize buffer usage in C.

    • returns: - value of _mode, but do not use it. The macro is able to use in a ( expr, expr, ...) form.

    getCharsAndSize_StringBuilderJc (ythis, size) : char

    Gets the buffer and the size of the buffer.

    • size: int - a int* reference to a variable, into which the value of buffer-size is stored.

    • returns: char - char*-pointer to the buffer.

    getCharsAndCount_StringBuilderJc (ythis, count) : char

    Gets the buffer and the actual nr of chars in the buffer.

    • count: int - a int* reference to a variable, into which the value of number of chars is stored.

    • returns: char - char*-pointer to the buffer.

    getCharsSizeCount_StringBuilderJc (ythis, size, count) : char

    Gets the buffer, the size and the actual nr of chars in the buffer.

    • size: int - a int* reference to a variable, into which the value of buffer-size is stored.

    • count: int - a int* reference to a variable, into which the value of number of chars is stored.

    • returns: char - char*-pointer to the buffer.

    _setCount_StringBuilderJc (ythis, count) : void

    Sets the nr of chars immediately. Only internal use.

    • count: int - actual number of chars.

    • returns: void -

    setLength_StringBuilderJc (ythis, newLength, _thCxt) : void

    Sets the length of the character sequence. It's like java.lang.StringBuffer.setLength(). The sequence is changed to a new character sequence whose length is specified by the argument. For every nonnegative index k less than newLength, the character at index k in the new character sequence is the same as the character at index k in the old sequence if k is less than the length of the old character sequence; otherwise, it is the null character 'u0000'. In other words, if the newLength argument is less than the current length, the length is changed to the specified length.

    If the newLength argument is greater than or equal to the current length, sufficient null characters ('u0000') are appended so that length becomes the newLength argument.

    The newLength argument must be greater than or equal to 0.

    clear_StringBuilderJc (ythis) : void

    Clears the content. It is the same like setLength(0).

    length_StringBuilderJc (YTHIS) :

    Gets the number of chars in buffer.

    capacity_StringBuilderJc (ythis) : int

    Gets the size of buffer.

    substring_StringBuilderJc (THIZ, BEGIN, END, _THC) :

    Returns a new string that is a substring from the content in the StringBuilder. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.

    This method is a macro which calls substring_StringJc(...) from toString_StringBuilderJc(...). No additional data are created in stack or heap (proper for C usage). The StringBuilder (this) is designated as persistent after this call. It means that

    • BEGIN: -

    • END: -

    • returns: -

    • throws - IndexOutOfBoundsException - if the beginIndex is negative, or endIndex is larger than the length of this String object, or beginIndex is larger than endIndex.

    • javalike - Lightly modified from Java, see sunJavadoc/java/lang/StringBuilder#substring(int, int)

    substring_I_StringBuilderJc (THIZ, STR, BEGIN, _THC) :

    Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the length of the given String..

    indexOf_I_StringBuilderJc (THIZ, STR, POS, _THC) :

    Searches the text within the buffer of the StringBuilder.

    indexOf_StringBuilderJc (YTHIS, str, _THC) :

    Searches the text within the buffer of the StringBuilder.

    • str: - text to search referenced with a StringJc

    • returns: - position of the first occurence counted from start of this String (first position is 0). The return value is alway >= fromIndex, if the str is contained in this. Return -1 if the str is not contain in this.

    indexOf_s_StringBuilderJc (THIZ, STR, _THC) :

    Searches the text within the buffer of the StringBuilder.

    indexOf_z_StringBuilderJc (THIZ, STR, _THC) :

    Searches the text within the buffer of the StringBuilder.

    • STR: - text to search referenced with a 0-terminated C-string

    • returns: - position of the first occurence counted from start of this String (first position is 0). The return value is alway >= fromIndex, if the str is contained in this. Return -1 if the str is not contain in this.

    indexOf_sI_StringBuilderJc (THIZ, STR, POS, _THC) :

    Searches the text within the buffer of the StringBuilder.

    • STR: - text to search

    • POS: - start search from this position.

    • returns: - position of the first occurence counted from start of this String (first position is 0). The return value is alway >= fromIndex, if the str is contained in this. Return -1 if the str is not contain in this.

    indexOf_zI_StringBuilderJc (THIZ, STR, POS, _THC) :

    Searches the text within the buffer of the StringBuilder.

    • STR: - text to search referenced with a 0-terminated C-string

    • POS: - start search from this position.

    • returns: - position of the first occurence counted from start of this String (first position is 0). The return value is alway >= fromIndex, if the str is contained in this. Return -1 if the str is not contain in this.

    charAt_StringBuilderJc (ythis, index, _thCxt) : char

    Returns the char at position idx.

    • index: int - The index. It should be a positiv number and less than the length of the text. Because this is a fast access using a macro, the index in not tested. If the index is fault, an undefined value is returned. If the built position with this index is outside the memory area, an memory exception can be thrown. Therefore: Only use correct indices.

    • returns: char - character at the position of text + idx.

    • javalike - sunJavadoc/java/lang/StringBuilder#charAt(int) but a test of idx is not done.

    setCharAt_StringBuilderJc (ythis, index, ch, _thCxt) : void

    Sets the char at position.

    deleteCharAt_StringBuilderJc (YTHIS, IDX, _THC) :

    Deletes the char at the given position. The text-length will be reduced by 1 char.

    insert_s_StringBuilderJc (YTHIS, pos, str, _THC) :

    Insert a text at the given position.

    insert_sII_StringBuilderJc (ythis, pos, src, start, end, _thCxt) : StringBuilderJc

    Insert a part of a text at the given position.

    • pos: int - position of char at which the text will be inserted

    • src: StringJc - Reference to the text which will be insert. It may be non-persistent.

    • start: int - The starting index of the subsequence to be inserted.

    • end: int - The end index of the subsequence to be inserted.

    • returns: StringBuilderJc - this.

    • javalike - sunJavadoc/java/lang/StringBuilder#insert(int, java.lang.CharSequence, int, int). A CharSequence in Java is an interface to a String or a StringBuilder. In the CRuntimeJavalike this interface is not present. The Java2C-Translator will be generate a call to a conversion routine to StringJc, if the used instance in Java is not a String itself. A CharSequence-interface to a StringBuilder is the same as the non-persistent String returned by toStringNonPersist_StringBuilderJc(...) in the CRuntimeJavalike. It means, the buffer content is used as is.

    insert_CYII_StringBuilderJc (ythis, pos, src, offset, len, _thCxt) : StringBuilderJc

    Inserts the content of the character array at the given position.

    insert_CY_StringBuilderJc (YTHIS, pos, src, _THC) :

    Inserts the content of the character array at the given position.

    insert_C_StringBuilderJc (ythis, pos, src, _thCxt) : StringBuilderJc

    Inserts the character at the given position.

    insert_zI_StringBuilderJc (YTHIS, pos, src, len, _THC) :

    Inserts a referenced char const* text with given number of chars at the given position.

    • pos: - position of char at which the text will be inserted

    • src: - char const* text

    • len: - Number of chars to insert.

    • returns: - this.

    insert_z_StringBuilderJc (YTHIS, pos, src, _THC) :

    Inserts a referenced char const* 0-terminated text at the given position.

    • pos: - position of char at which the text will be inserted

    • src: - char const* text. The maximal detected length of the text is mLength__StringJc. Use it only for "literal".

    • returns: - this.

    replace_zI_StringBuilderJc (ythis, start, end, src, lenSrc, _thCxt) : StringBuilderJc

    Replaces the characters in a substring of this sequence with characters in the specified String. The substring begins at the specified start and extends to the character at index end - 1 or to the end of the sequence if no such character exists. First the characters in the substring are removed and then the specified String is inserted at start. (This sequence will be lengthened to accommodate the specified String if necessary.)

    It is the core method to insert, append, replace, delete with a given char* and a given lenght. All those methods are implemented with this method.

    • start: int - position of the first char which will be deleted. The parameter isn't use if start == end or end == 0.

    • end: int - position after the last char which will be deleted. If this parameter is 0, no characters were deleted. If this Parameter is negative, its absolute value is the number of chars to delete. This definition is in opposite to Java and supports the usage of macros for the other insert, append and replace-operations, if the number of chars are 0 or 1. NOTE: A twice usage of given value in macro may force twice call of the supplying method, and that may be false. See implementation of the macros using this method.

    • src: char - reference of type char const* to the text to insert, may be null, than nothing is inserted idenendent of len. The text is not 0-terminated. 0-chars are copied into the buffer without extra handling.

    • lenSrc: int - Number of chars to insert. It may be 0, than nothing is inserted independent of add.

    • returns: StringBuilderJc -

    • throws - StringIndexOutOfBoundsException if the range doesn't match.

    replace_StringBuilderJc (ythis, start, end, value, _thCxt) : StringBuilderJc

    Replaces the characters in a substring of this sequence with characters in the specified String. The substring begins at the specified start and extends to the character at index end - 1 or to the end of the sequence if no such character exists. First the characters in the substring are removed and then the specified String is inserted at start. (This sequence will be lengthened to accommodate the specified String if necessary.)

    It is the core method to insert, append, replace, delete with a given StringJc. All those methods are implemented with this method.

    • start: int - position of the first char which will be deleted. The parameter isn't use if start == end or end == 0.

    • end: int - position after the last char which will be deleted. If this parameter is 0, no characters were deleted. If this Parameter is negative, its absolute value is the number of chars to delete. This definition is in opposite to Java and supports the usage of macros for the other insert, append and replace-operations, if the number of chars are 0 or 1. NOTE: A twice usage of given value in macro may force twice call of the supplying method, and that may be false. See implementation of the macros using this method.

    • value: StringJc -

    • returns: StringBuilderJc -

    • throws - StringIndexOutOfBoundsException if the range doesn't match.

    insert_I_StringBuilderJc (YTHIS, pos, value, _THC) :

    Inserts the text representation of the second int argument into this sequence. The second argument is converted to a text as if by the method String.valueOf, and the characters of that text are then inserted into this sequence at the indicated position.

    insert_Ir_StringBuilderJc (ythis, pos, value, radix, _thCxt) : StringBuilderJc

    Inserts the text representation with given radix of the second int argument into this sequence. The second argument is converted to a text as if by the method String.valueOf, and the characters of that text are then inserted into this sequence at the indicated position.

    insert_J_StringBuilderJc (YTHIS, pos, value, _THC) :

    Inserts the text representation of the second int argument into this sequence. The second argument is converted to a text as if by the method String.valueOf, and the characters of that text are then inserted into this sequence at the indicated position.

    insert_Jr_StringBuilderJc (ythis, pos, value, radix, _thCxt) : StringBuilderJc

    Inserts the text representation with given radix of the second int argument into this sequence. The second argument is converted to a text as if by the method String.valueOf, and the characters of that text are then inserted into this sequence at the indicated position.

    insert_F_StringBuilderJc (ythis, offset, value, _thCxt) : StringBuilderJc

    Inserts the text representation of the second int argument into this sequence. The second argument is converted to a text as if by the method String.valueOf, and the characters of that text are then inserted into this sequence at the indicated position.

    insert_D_StringBuilderJc (ythis, offset, value, _thCxt) : StringBuilderJc

    Inserts the text representation of the second int argument into this sequence. The second argument is converted to a text as if by the method String.valueOf, and the characters of that text are then inserted into this sequence at the indicated position.

    append_z_StringBuilderJc (YTHIS, src, _THC) :

    Appends a text at the end.

    • src: - char const* text. The maximal detected length of the text is mLength__StringJc. Use it only for "literal".

    • returns: - this

    append_zI_StringBuilderJc (YTHIS, src, lenSrc, _THC) :

    C-like: appends a character text with given length.

    • src: -

    • lenSrc: -

    • returns: -

    append_s_StringBuilderJc (ythis, src, _thCxt) : StringBuilderJc

    Appends a text at the end.

    append_sII_StringBuilderJc (ythis, src, start, end, _thCxt) : StringBuilderJc

    Appends a text at the end.

    append_u_StringBuilderJc (ythis, src, _thCxt) : StringBuilderJc

    Appends the text of the given StringBuilder at the end.

    append_C_StringBuilderJc (YTHIS, char, _THC) :

    java:StringBuffer.append(String)

    • char: -

    • returns: -

    append_I_StringBuilderJc (YTHIS, value, _THC) :

    Appends the text reprentation of the given integer value at the end.

    append_F_StringBuilderJc (YTHIS, value, _THC) :

    Appends the text reprentation of the given float value at the end.

    append_D_StringBuilderJc (YTHIS, value, _THC) :

    Appends the text reprentation of the given double value at the end.

    append_J_StringBuilderJc (YTHIS, VALUE, _THC) :

    Appends the text reprentation of the given long value at the end.

    delete_StringBuilderJc (ythis, start, end, _thCxt) : StringBuilderJc

    Removes the characters in a substring of this sequence. The substring begins at the specified start and extends to the character at index end - 1 or to the end of the sequence if no such character exists. If start is equal to end, no changes are made.

    replace_CC_StringBuilderJc (ythis, oldChar, newChar) : StringBuilderJc

    Replaces single chars in the buffer.

    • oldChar: char - The char which was to replace at any occurence.

    • newChar: char - Char to set.

    • returns: StringBuilderJc - this.

    • javalike - : Java doesn't know a simple method to replace chars in a StringBuilder. But it may necessary.

    toString_StringBuilderJc (YTHIS, _THC) :

    Returns the String which represents the content of the StringBuffer.

    Implemenation Note: The StringBuffer will be designated as freezed. A changing of content after call of toString will be caused an error. The calling instance (this) should be given as ObjectJc-pointer. That is because this method is defined for Object and it is overwritten only. But the instance has to be a StringBuilderJc.

    • returns: - A StringJc instance which refers the buffer of the StringBuilder. It is designated as persistent only if the StringBuilderJc-instance is designated as an instance only for concatenating a String, see StringBuilder.setStringConcatBuffer_StringBuilderJc(...). Otherwise it is dedignated as non-persistent.

    • javalike - sunJavadoc/java/lang/StringBuilder#toString(), but Java returns an persistent String in a new allocated buffer anytime. If dynamically memory is present, the persistence is possible using set_StringJc(...).

    • see - toStringPersist_StringBuilderJc() and toStringNonPersist_StringBuilderJc().

    toString_StringJc (STRING) :
    • STRING: -

    • returns: -

    toStringNonPersist_StringBuilderJc (othis, _thCxt) : StringJc

    Returns the String which represents the content of the StringBuffer.

    The StringBuffer will not be designated as freezed.

    • returns: StringJc - A StringJc instance which refers the buffer of the StringBuilder. It is designated as non-persistent. If the text in this is changed, the String will be changed also.

    • javalike - : It is non java-like, but a special form of sunJavadoc/java/lang/StringBuilder#toString(), which is effective in C. It have the same behaviour like Java if the String is used only immediately without storing its reference.

    toStringPersist_StringBuilderJc (othis, _thCxt) : StringJc

    Returns the String which represents the content of the StringBuffer. If the StringBuilder is designated only to use for concatenation of a String, it is persistent itself. Than the returned String referes the StringBuffer. Otherwise a new Instance for the text is created dynamically and its refference is returned.

    The StringBuilder is designated only to use for concatenation if the method setStringConcatBuffer_StringBuilderJc() was called. Than the String must not located in Stack or ThreadContext, but it should be allocated dynamically too.

    • returns: StringJc - A StringJc instance which refers the buffer of the StringBuilder. It is designated as non-persistent. If the text in this is changed, the String will be changed also.

    • javalike - : It is the java-adequate behaviour of sunJavadoc/java/lang/StringBuilder#toString(),

    toStringInThreadCxt_StringBuilderJc (othis, _thCxt) : StringJc

    Copies the content of buffer in the Thread-Context-Buffer and refers it with the returned instance.

    • returns: StringJc - A StringJc instance which referes a text in the Thread Context. It is designated as non-persistent and with the threadContext-designation (bits mThreadContext__StringJc).

    cleanToSize_StringBuilderJc (ythis) : void

    cleans the Rest of content in the buffer after the valid chars. This method is enhanced in comparision to Java. It consideres a usage of StringBuilderJc for text fields in structures. The content in the structur's fields should be cleanly. The naming of the method is contrastable to the Java method sunJavadoc/java/lang/StringBuilder#trimToSize().

    • returns: void -

    new_StringBuilderJcpp (size) : StringBuilderJcpp

    Do not use, because it isn't settled, how to allocate without responsibility of the user but also without garbage collection. Therefore this solution isn't able to use.

    • size: int -

    • returns: StringBuilderJcpp -

    threadBuffer_StringBuilderJcpp (_thCxt) : StringBuilderJcpp
    • returns: StringBuilderJcpp -

    threadBuffer_s_StringBuilderJcpp (src, _thCxt) : StringBuilderJcpp
    • src: StringJc -

    • returns: StringBuilderJcpp -

    CONST-Initializer:

    CONST-Initializer sind Makros für C-Konstanten, sie sind in Headerfiles definiert. C-Konstante sind Konstrukte in { ... } mit ausschließlich konstanten Werten. Die Makros der CONST-Initializer übernehmen Argumente, die zur Compilezeit die Konstanten bestimmen. Die Initializer sind deshalb als Makros definiert, weil die Struktur der Konstanten exakt der struct-Definition folgen muss, die struct ist im Headerfile definiert, daher auch dazu passend diese Makros. Mit denCONST-Intializer ist es auf einfache Weise möglich, C-struct-Daten (Plain Old Data) zu initialisieren. Für Klassen (C++) ist dieses Konzept nicht geeignet.

    CONST_StringBuilderJc(OBJP)

    This macro defines a C-constant (with {..}) for empty-initializing a StringBuffer instance with its static size.

    • OBJP - Pointer to the instance itself. It is used to store the OWNADDRESS for the ObjectJc-part.

    CONST_addSizeStack_StringBuilderJc(OBJP, ADDSIZE)

    This macro defines a C-constant (with {..}) for initializing a StringBuffer instance with an additional size. which is located in the Stack. See CONST_addSize_StringBuilderJc(...) It have to be used if the StringBuilderJc-instance is located in Stack. The mode bits _mStack_StringBuilderJc is set. The definition of such an construct is recommended as astruct definition like following:

    struct { StringBuilderJc u; char _[120]; } uBuffer = { CONST_addSize_StringBuilderJc(&uBuffer.buffer, 120), { 0 }};

    The a StringBuilder with immediately buffer for 123 characters and a 0 on end is placed in the stack. See macro INSTACK_StringBuilderJc(...).

    • OBJP - The reference to the StringBuilder-instance itself

    • ADDSIZE - size of the char[] after the StringBuilderJc-instance.

    CONST_addSize_StringBuilderJc(OBJP, ADDSIZE)

    This macro defines a C-constant (with {..}) for initializing a StringBuffer instance with an additional size. This macro is usefull if a StringBuffer with a following char array is defined to increase the size of the immediate text in buffer. The definition of such an construct is possible inside a struct definition with followed sample:

    ,struct { ... ; StringBuilderJc buffer; char bufferIncreasingCharArray[120]; ... } myData =
    

    The bufferIncreasingCharArray have to be assembled immediately after the buffer. The initializer of this part may be written in form of:

    ,{ ... , CONST_addSize_StringBuilderJc(&myData.buffer, 120), { 0 }, ... },,
    

    The using of a following char array to increase the buffer is opportune to get a larger StringBuffer, because the compiler will always assigns the memory of the followed char array immediately after the previous element, the StringBuilderJc, and the own char array of the StringBuilderJc is assigned as the last element there. The problem of additional bytes because 4-Byte-allignment or such is not present, because a StringBuilderJc have a size of multiple 4 bytes. But the user should define the size of the char array as multiple of 4 to prevent alignment problems also.

    Note: Outside a struct, the definition of elements one after another doesn't may assigned one after another in memory. It differents from compiler versions or other conditions such as segmentation sizes of physical memory!

    • OBJP - Pointer to the instance itself. It is used to store the OWNADDRESS for the ObjectJc-part.

    • ADDSIZE - The additional size of the StringBuffer, defined by sizeof the followed char array.


    2.6 CharSequenceJc

    UML=/Package[StringJc_h]/Namespace.ownedElement[]/Class[CharSequenceJc]

    Class CharSequenceJc definiert in StringJc_h

    UML=/Package[StringJc_h]/Namespace.ownedElement[]/Class[CharSequenceJc]

    Attributes:

    +-------'-------'-------'-------'-------'-------'-------'-------+
    |                            object                             |
    +-------'-------'-------'-------'-------'-------'-------'-------
    Pos. 0x0..0x = 0..NaN ( NaN bytes): object : ObjectJc

    Inner class CharSequenceJc.Mtbl_ definiert in StringJc_h/CharSequenceJc

    UML=/Class[CharSequenceJc]/Namespace.ownedElement[]/Class[Mtbl_]

    To organize dynamic link method call the jump table of virtual methods is neccessary.

    Attributes:

    +-------'-------'-------'-------'-------'-------'-------'-------+
    |                         mtblObjectJc                          |
    +-------'-------'-------'-------+-------'-------'-------'-------+
    |            length             |            charAt             |
    +-------'-------'-------'-------+
    |         subSequence           |
    +-------'-------'-------'-------
    Pos. 0x0..0x18 = 0..24 ( 25 bytes): mtblObjectJc :
    Pos. 0x19..0x1C = 25..28 ( 4 bytes): length : MT_length_CharSequenceJc
    Pos. 0x1D..0x20 = 29..32 ( 4 bytes): charAt : MT_charAt_CharSequenceJc
    Pos. 0x21..0x24 = 33..36 ( 4 bytes): subSequence : MT_subSequence_CharSequenceJc

    Methoden:

    length_CharSequenceJc (THIZ, THC) :
    • THC: -

    • returns: -

    charAt_CharSequenceJc (THIZ, ix, THC) :
    • ix: -

    • THC: -

    • returns: -

    subSequence_CharSequenceJc (THIZ, from, to, THC) :
    • from: -

    • to: -

    • THC: -

    • returns: -