Page suivante - Page précédente - Table des matières

16. Annexe C String.cpp

Vous pouvez récupérer tous les programmes en un seul tar.gz sur Telecharger String . Pour obtenir ce fichier, dans un butineur web, sauvez ce fichier en type 'texte'.


//
// Auteur : Al Dev
// Utilisez la classe string ou cette classe
//
// Pour prévenir les fuites de mémoire - une classe caractère qui gère les
// variables caractères.
// Préférez toujours l'utilisation de la classe string à char[] et char *.
//
//
// Pour compiler et tester ce programme, utilisez -
//              g++ String.cpp
#include "String.h"
//#include <sys/va_list.h> pour Format()
//#include <sys/varargs.h> pour Format()
// Variables globales....
//String *String::_global_String = NULL; // variable globale
list<String>                 String::explodeH;
String::String()
{
 debug_("In cstr()", "ok");
 sval = (char *) my_malloc(sizeof(char)* INITIAL_SIZE);
 _pString = NULL;
}
String::String(char *bb)
{
 unsigned long tmpii = strlen(bb);
 sval = (char *) my_malloc(sizeof(char)* tmpii);
 strncpy(sval, bb, tmpii);
 sval[tmpii] = '\0';
 //debug_("In cstr(char *bb) bb", bb);
 debug_("In cstr(char *bb) sval", sval);
 #ifdef DEBUG
 //fprintf(stderr, "\nAddress of sval=%x\n", & sval);
 //fprintf(stderr, "\nAddress of this-pointer=%x\n", this);
 #endif // DEBUG
 _pString = NULL;
}
String::String(char *bb, int start, int slength)
{
 unsigned long tmpii = strlen(bb);
 if (start> (int) tmpii || start < 0)
 {
 cerr << "\nString(char *, int, int) - start is  out of bounds!!\n" << endl;
 exit(1);
 }
 sval = (char *) my_malloc(sizeof(char)* slength);
 strncpy(sval, & bb[start], slength);
 sval[slength] = '\0';
 //debug_("In cstr(char *bb) bb", bb);
 debug_("In cstr(char *bb) sval", sval);
 #ifdef DEBUG
 //fprintf(stderr, "\nAddress of sval=%x\n", & sval);
 //fprintf(stderr, "\nAddress of this-pointer=%x\n", this);
 #endif // DEBUG
 _pString = NULL;
}
String::String(int bb)
{
 sval = (char *) my_malloc(NUMBER_LENGTH); // int avec 70 chiffres max
 sprintf(sval, "%d", bb);
 debug_("In cstr(int bb) sval", sval);
 _pString = NULL;
}
String::String(unsigned long bb)
{
 sval = (char *) my_malloc(NUMBER_LENGTH); // unsigned long avec 70 chiffres max
 sprintf(sval, "%lu", bb);
 debug_("In cstr(unsigned long bb) sval", sval);
 _pString = NULL;
}
String::String(long bb)
{
 sval = (char *) my_malloc(NUMBER_LENGTH); // long avec 70 chiffres max
 sprintf(sval, "%ld", bb);
 debug_("In cstr(long bb) sval", sval);
 _pString = NULL;
}
String::String(float bb)
{
 sval = (char *) my_malloc(NUMBER_LENGTH); // float avec 70 chiffres max
 sprintf(sval, "%f", bb);
 debug_("In cstr(float bb) sval", sval);
 _pString = NULL;
}
String::String(double bb)
{
 sval = (char *) my_malloc(NUMBER_LENGTH); // double avec 70 chiffres max
 sprintf(sval, "%f", bb);
 debug_("In cstr(double bb) sval", sval);
 _pString = NULL;
}
// Constructeur par recopie utilisé par l'opérateur +
String::String(const String & rhs)
{
 // Effectue une copie en profondeur à la place de la copie superficielle par défaut du compilateur
 debug_("In copy-cstr()", "ok");
 unsigned long tmpii = strlen(rhs.sval);
 sval = (char *) my_malloc(sizeof(char)* tmpii);
 strncpy(sval, rhs.sval, tmpii);
 sval[tmpii] = '\0';
 _pString = NULL;
}
// Cette fonction fournit une compatibilité avec le code Java
String::String(StringBuffer sb)
{
 debug_("In String(StringBuffer)", "ok");
 unsigned long tmpii = strlen(sb.sval);
 sval = (char *) my_malloc(sizeof(char)* tmpii);
 strncpy(sval, sb.sval, tmpii);
 sval[tmpii] = '\0';
 _pString = NULL;
}
// Utilisé par la classe StringBuffer. Utilise la variable dummy
// pour différentes signatures.
// La classe StringBuffer imite le StringBuffer de Java
String::String(int size, bool dummy)
{
 sval = (char *) my_malloc(sizeof(char)* size);
 debug_("In cstr(int size, bool dummy) sval", sval);
 #ifdef DEBUG
 //fprintf(stderr, "\nAddress of sval=%x\n", & sval);
 //fprintf(stderr, "\nAddress of this-pointer=%x\n", this);
 #endif // DEBUG
 _pString = NULL;
}
String::~String()
{
 debug_("In dstr sval", sval);
 #ifdef DEBUG
 //fprintf(stderr, "\nAddress of sval=%x\n", & sval);
 //fprintf(stderr, "\nAddress of this-pointer=%x\n", this);
 #endif // DEBUG
 my_free(sval);
 //delete [] sval;
 sval = NULL;
 delete _pString; _pString = NULL;
}
inline void String::_allocpString()
{
 // _pString will be deleted in destructor
 if (!_pString)  // if (_pString == NULL)
 _pString = new String(this->sval);
 else
 *_pString = this->sval;
}
// DOIT utiliser un pointeur-sur-pointeur **aa, sinon la mémoire utilisée
// par l'argument N'est PAS libérée !
/*
inline void String::_free_glob(String **aa)
{
 debug_("called _free_glob()", "ok" );
 if (*aa != NULL)  // (*aa != NULL)
 {
 debug_("*aa is not null", "ok");
 delete *aa;
 *aa = NULL;
 }
 //else
 debug_("*aa is null", "ok");
 //if (*aa == NULL)
 debug_("*aa set to null", "ok");
}
*/
// Imite le charAt de java.lang.String
char String::charAt(int where)
{
 verifyIndex(where);
 return (sval[where]);
}
// Imite la fonction getChars de java.lang.String
// sourceStart spécifie l'indice du début de la sous-chaîne
// et sourceEnd spécifie l'indice juste après la fin de la sous-chaîne désirée
// Ainsi la sous-chaîne contient les caractères de sourceStart jusqu'à
// (sourceEnd - 1). Le tableau qui va recevoir les caractères est target.
// targetStart est l'indice dans target à partir duquel la copie sera effectuée.
// Il convient de s'assurer que le tableau target est assez grand pour pouvoir contenir
// le nombre de caractères désiré.
// Par exemple  getChars(3, 6, aa, 0) sur "ABCDEFGHIJK" donne aa ="DEF"
void String::getChars(int sourceStart, int sourceEnd, char target[], int targetStart)
{
 verifyIndex(sourceStart);
 verifyIndex(sourceEnd);
 if (sourceEnd>= sourceStart)
 {
 strncpy(& target[targetStart], & sval[sourceStart], sourceEnd - sourceStart);
 target[targetStart + (sourceEnd - sourceStart)] = 0;
 }
 else
 {
 cerr << "\ngetChars() - SourceEnd is greater than SourceStart!!\n" << endl;
 exit(1);
 }
}
// Imite getChars de java.lang.String
// Retourne un tableau caractères contenant la chaîne entière
char* String::toCharArray()
{
 return (sval);
}
// Imite getBytes de java.lang.String
// Retourne un tableau caractères contenant la chaîne entière
char* String::getBytes()
{
 return (sval);
}
// Imite equals de java.lang.String
bool String::equals(String str2)  // voir aussi l'opérateur ==
{
 return ( _equalto(str2.sval));
}
// Imite equals de java.lang.String
bool String::equals(char *str2)  // voir aussi l'opérateur ==
{
 return ( _equalto(str2));
}
// Imite equalsIgnoreCase de java.lang.String
bool String::equalsIgnoreCase(String str2)
{
 String  aa, bb;
 aa = this->toLowerCase();
 bb = str2.toLowerCase();
 return ( aa._equalto(bb.sval) );
}
// Imite regionMatches de java.lang.String
// startIndex spécifie l'indice à partir duquel débute la région dans l'objet
// String invoquant la méthode. La chaîne est comparée à str2. L'indice à partir
// duquel la comparaison commencera dans str2 est spécifié par str2Index
// La longueur de la sous-chaîne comparée est numChars.
bool String::regionMatches(int startIndex, String str2, int str2StartIndex, int numChars)
{
 verifyIndex(startIndex);
 str2.verifyIndex(str2StartIndex);
 if (strncmp(& this->sval[startIndex], & str2.sval[str2StartIndex], numChars) == 0)
 return true;
 else
 return false;
}
// Imite regionMatches de java.lang.String
// Il s'agit de la version surchargée de regionMatches
// Si ignoreCase vaut true, la casse des caractères est ignorée, sinon
// la casse est significative (i.e. si ignoreCase vaut true alors ignore la
// casse et compare)
// startIndex spécifie l'indice à partir duquel débute la region dans l'objet
// String invoquant la méthode. La chaîne est comparée à str2. L'indice à partir
// duquel la comparaison commencera dans str2 est spécifié par str2Index
// La longueur de la sous-chaîne comparée est numChars.
bool String::regionMatches(bool ignoreCase, int startIndex, String str2, int str2StartIndex, int numChars)
{
 if (ignoreCase)  // if (ignoreCase == true)
 {
 verifyIndex(startIndex);
 str2.verifyIndex(str2StartIndex);
 String string1, string2;
 string1 = this->toLowerCase();
 string2 = str2.toLowerCase();
 if (strncmp(& string1.sval[startIndex], & string2.sval[str2StartIndex], numChars) == 0)
 return true;
 else
 return false;
 }
 else
 {
 return regionMatches(startIndex, str2, str2StartIndex, numChars);
 }
}
// Imite toLowerCase de java.lang.String
//       String  ss("sometest");
//       String  egg = ss.toLowerCase();
String String::toLowerCase()
{
 _allocpString();
 for (long tmpii = strlen(_pString->sval); tmpii>= 0; tmpii--)
 {
 _pString->sval[tmpii] = tolower(_pString->sval[tmpii]);
 }
 return *_pString;  // return the object now
}
// Imite toUpperCase de java.lang.String
//       String  ss("sometest");
//       String  egg = ss.toUpperCase();
String String::toUpperCase()
{
 _allocpString();
 for (long tmpii = strlen(_pString->sval); tmpii>= 0; tmpii--)
 {
 _pString->sval[tmpii] = toupper(_pString->sval[tmpii]);
 }
 return *_pString;  // return the object now
}
// Imite startsWith de java.lang.String
bool String::startsWith(String str2)
{
 if (!strncmp(this->sval, str2.sval, strlen(str2.sval) )) // if (strncmp() == 0)
 return true;
 else
 return false;
}
// Imite startsWith de java.lang.String
// Fonction surchargée
bool String::startsWith(char *str2)
{
 int lenstr2 = strlen(str2);
 if (!strncmp(this->sval, str2, lenstr2)) // if (strncmp() == 0)
 return true;
 else
 return false;
}
// Imite endsWith de java.lang.String
bool String::endsWith(String str2)
{
 // str2 doit être plus courte que la chaîne courante
 if (strlen(str2.sval)> strlen(sval))
 return false;
 if (!strncmp(& this->sval[strlen(sval) - strlen(str2.sval)], str2.sval, strlen(str2.sval) )) // if (strncmp() == 0)
 return true;
 else
 return false;
}
// Imite endsWith de java.lang.String
bool String::endsWith(char *str2)
{
 // str2 doit être plus courte que la chaîne courante
 if (strlen(str2)> strlen(sval))
 return false;
 if (!strncmp(& this->sval[strlen(sval) - strlen(str2)], str2, strlen(str2) ) ) // if (strncmp() == 0)
 return true;
 else
 return false;
}
// Imite compareTo de java.lang.String
// Pour les tris, vous devez savoir si l'un est plus petit, égal ou plus grand que l'autre.
// Une chaîne est plus petite qu'une autre si elle arrive avant l'autre dans l'ordre
// lexicographique. Un chaîne est plus grande qu'une autre si elle arrive après.
//  Négatif  --> la chaîne courante est plus petite que str2
//  Positif  --> la chaîne courante est plus grande que str2
//  Zero  --> les deux chaînes sont égales
int String::compareTo(String str2)
{
 int  flag = 0;
 // Compare les lettres dans la chaîne à chaque lettre de str2
 for (int tmpii = 0, tmpjj = strlen(sval), tmpkk = strlen(str2.sval); tmpii < tmpjj; tmpii++)
 {
 if (tmpii> tmpkk)
 break;
 if (sval[tmpii] == str2.sval[tmpii])
 flag = 0;
 else
 if (sval[tmpii]> str2.sval[tmpii])
 {
 flag = 1;
 break;
 }
 else // if (sval[tmpii] < str2.sval[tmpii])
 {
 flag = -1;
 break;
 }
 }
 return flag;
}
// Imite compareTo de java.lang.String
// Fonction surchargée de compareTo
int String::compareTo(char *str2)
{
 int  flag = 0;
 // Compare les lettres de la chaîne courante avec chaque lettre de str2
 for (int tmpii = 0, tmpjj = strlen(sval), tmpkk = strlen(str2); tmpii < tmpjj; tmpii++)
 {
 if (tmpii> tmpkk)
 break;
 if (sval[tmpii] == str2[tmpii])
 flag = 0;
 else
 if (sval[tmpii]> str2[tmpii])
 {
 flag = 1;
 break;
 }
 else // if (sval[tmpii] < str2[tmpii])
 {
 flag = -1;
 break;
 }
 }
 return flag;
}
// Imite compareToIgnoreCase de java.lang.String
int String::compareToIgnoreCase(String str2)
{
 String tmpaa = this->toLowerCase(),
 tmpbb = str2.toLowerCase();
 return tmpaa.compareTo(tmpbb);
}
// Imite compareToIgnoreCase de java.lang.String
// Version surchargée
int String::compareToIgnoreCase(char *str2)
{
 String tmpaa = this->toLowerCase(),
 tmpcc(str2), tmpbb = tmpcc.toLowerCase();
 return tmpaa.compareTo(tmpbb);
}
// Imite indexOf de java.lang.String
// Cherche la premiere occurrence d'un caractère ou d'une chaîne.
// Retourne l'indice à partir duquel le caractère ou la chaîne
// a été trouvé, ou -1 en cas d'échec.
int String::indexOf(char ch, int startIndex = 0)
{
 verifyIndex(startIndex);
 int ii = startIndex;
 for (; ii < (int) strlen(sval); ii++)
 {
 if (sval[ii] == ch)
 break;
 }
 if (ii == (int) strlen(sval))
 return -1;
 return ii;
}
// Imite indexOf de java.lang.String
// Version surchargée
int String::indexOf(char *str2, int startIndex = 0)
{
 verifyIndex(startIndex);
 char * tok;
 long res = -1;
 if ( !isNull() )
 {
 tok = strstr(sval + startIndex, str2);
 if (tok == NULL)
 res = -1;
 else
 res = (int) (tok - sval);
 }
 return res;
}
// Imite indexOf de java.lang.String
// Version surchargée
int String::indexOf(String str2, int startIndex = 0)
{
 verifyIndex(startIndex);
 char * tok;
 long res = -1;
 if ( !isNull() )
 {
 tok = strstr(sval + startIndex, str2.sval);
 if (tok == NULL)
 res = -1;
 else
 res = (int) (tok - sval);
 }
 return res;
}
// Imite lastIndexOf de java.lang.String
// Cherche pour la dernière occurrence d'un caractère ou d'une chaîne.
// Retourne l'indice à partir duquel le caractère ou la chaîne a été trouvé
// ou -1 en cas d'échec.
int String::lastIndexOf(char ch, int startIndex = 0)
{
 verifyIndex(startIndex);
 int ii;
 // Commence la recherche par le dernier caractère de la chaîne
 if (!startIndex) // if (startIndex == 0)
 ii = strlen(sval);
 else
 ii = startIndex;
 for (; ii> -1; ii--)
 {
 if (sval[ii] == ch)
 break;
 }
 if (!ii && sval[ii] != ch) // if (ii == 0)
 return -1;
 return ii;
}
// Imite lastIndexOf de java.lang.String
// Version surchargée
int String::lastIndexOf(char *str2, int startIndex = 0)
{
 verifyIndex(startIndex);
 char *tok = NULL;
 int res = -1;
 register char *tmpaa = strdup(sval);  // ici malloc
 if (!tmpaa) // tmpaa == NULL
 {
 cerr << "\nMemory alloc failed in strdup in lastIndexOf()\n" << endl;
 exit(-1);
 }
 if (!startIndex) // if (startIndex == 0)
 startIndex = strlen(sval);
 else
 tmpaa[startIndex+1] = 0;
 for (int ii = 0; ii <= startIndex; ii++)
 {
 tok = strstr(& tmpaa[ii], str2);
 if (tok == NULL)
 break;
 else
 {
 res = (int) (tok - tmpaa);
 debug_("res", res);
 ii = res; // saute vers l'endroit qui correspond (+1 dans la boucle for)
 }
 }
 free(tmpaa);
 debug_("res", res);
 debug_("indexOf", & sval[res]);
 return res;
}
// Imite lastIndexOf de java.lang.String
// Version surchargée
int String::lastIndexOf(String str2, int startIndex = 0)
{
 verifyIndex(startIndex);
 char *tok = NULL;
 int res = -1;
 register char *tmpaa = strdup(sval);  // ici malloc
 if (!tmpaa) // tmpaa == NULL
 {
 cerr << "\nMemory alloc failed in strdup in lastIndexOf()\n" << endl;
 exit(-1);
 }
 if (!startIndex) // if (startIndex == 0)
 startIndex = strlen(sval);
 else
 tmpaa[startIndex+1] = 0;
 for (int ii = 0; ii <= startIndex; ii++)
 {
 tok = strstr(& tmpaa[ii], str2.sval);
 if (tok == NULL)
 break;
 else
 {
 res = (int) (tok - tmpaa);
 debug_("res", res);
 ii = res; // saute vers l'endroit qui correspond (+1 dans la boucle for)
 }
 }
 free(tmpaa);
 debug_("res", res);
 debug_("indexOf", & sval[res]);
 return res;
}
// Imite substring de java.lang.String
// startIndex spécifie l'indice de début, et endIndex l'indice de fin.
// La chaîne retournée contient tous les caractères de l'indice de début
// jusqu'à l'indice de fin, mais sans l'inclure.
String String::substring(int startIndex, int endIndex = 0)
{
 String tmpstr = String(sval);
 tmpstr._substring(startIndex, endIndex);
 return tmpstr;
}
// Imite concat de java.lang.String
String String::concat(String str2)
{
 return (*this + str2);
}
// Imite concat de java.lang.String
// Version surchargée
String String::concat(char *str2)
{
 return (*this + str2);
}
// Imite replace de java.lang.String
// Remplace toutes les occurrences de la chaîne 'original' par
// 'replacement' dans 'sval'
String String::replace(char original, char replacement)
{
 // Par exemple -
 //              replace('A', 'B') dans sval = "des AAA et AAACC"
 //              retourne sval = "des BBB et BBBCC"
 //String *tmpstr = new String(sval); Utilise le constructeur de recopie par défaut
 String tmpstr(sval);
 for (int ii = 0, len = strlen(sval); ii < len; ii++)
 {
 if (tmpstr.sval[ii] == original)
 tmpstr.sval[ii] = replacement;
 }
 return tmpstr; // utilise le constructeur de recopie pour faire une copie
}
// Imite replace de java.lang.String
// Version surchargée
// Remplace toutes les occurrences de la chaîne 'original' par
// 'replacement' dans 'sval'
String String::replace(char *original, char *replacement)
{
 char *tok = NULL, *bb;
 register char *aa = strdup(sval);
 int lenrepl = strlen(replacement);
 // Alloue l'espace pour bb
 { // portée locale
 int tmpii = 0;
 for (int ii = 0; ;ii++)
 {
 tok = strstr(& aa[ii], original);
 if (tok == NULL)
 break;
 else
 {
 ii = ii + (int) (tok -aa);
 tmpii++;
 }
 }
 if (!tmpii) // tmpii == 0, pas de 'original' trouvé
 return (String(sval)); // retourne la chaîne originale
 tmpii = strlen(sval) + (tmpii * lenrepl) + 20;
 debug_("strstr tmpii", tmpii );
 bb = (char *) malloc(tmpii);
 memset(bb, 0, tmpii);
 }
 for (int res = -1; ;)
 {
 debug_("aa", aa);
 tok = strstr(aa, original);
 if (tok == NULL)
 {
 strcat(bb, aa);
 break;
 }
 else
 {
 res = (int) (tok - aa);
 strncat(bb, aa, res);
 strcat(bb, replacement);
 //bb[strlen(bb)] = 0;
 debug_("res", res );
 debug_("bb", bb );
 strcpy(aa, & aa[res+lenrepl]);
 }
 }
 debug_("bb", bb );
 free(aa);
 String tmpstr(bb);
 free(bb);
 return tmpstr;
}
/*
une autre méthode pour faire le remplacement mais lente...
String String::replace(char *original, char *replacement)
{
 // Par exemple -
 //              replace("AAA", "BB") avec sval = "des AAA et AAACC"
 //              retourne sval = "des BB et BBCC"
 String bb(this->before(original).sval);
 if (strlen(bb.sval) == 0)
 return String(sval); // retourne la chaîne originale
 bb += replacement;
 String tmpaa(this->sval), cc, dd;
 for (;;)
 {
 cc = tmpaa.after(original).sval;
 debug_("cc", cc.sval );
 if (!strlen(cc.sval)) // if (strlen(cc.sval) == 0)
 break;
 dd = cc.before(original).sval;
 if (strlen(dd.sval) == 0)
 {
 bb += cc;
 break;
 }
 else
 {
 bb += dd;
 bb += replacement;
 }
 tmpaa = cc;
 }
 debug_("bb.sval", bb.sval );
 return bb;
}
*/
// Imite replace de Java -  StringBuffer
String String::replace (int startIndex, int endIndex, String str)
{
 verifyIndex(startIndex);
 verifyIndex(endIndex);
 int tmpjj = strlen(str.sval);
 if (tmpjj == 0)
 return *this;
 int tmpii = endIndex-startIndex-1;
 if (tmpjj < tmpii) // la longueur de str est plus petite que les indices specifies.
 tmpii = tmpjj;
 debug_("sval", sval);
 debug_("str.sval", str.sval);
 strncpy(& sval[startIndex], str.sval, tmpii);
 sval[startIndex+tmpii] = 0;
 debug_("sval", sval);
 return *this;
}
// Imite trim de java.lang.String
String String::trim()
{
 //String *tmpstr = new String(sval);
 String tmpstr(sval);
 tmpstr._trim();
 debug_("tmpstr.sval", tmpstr.sval);
 return tmpstr; // utilise le constructeur par recopie pour faire une copie
}
// Imite insert de java.lang.String
String String::insert(int index, String str2)
{
 String tmpstr(this->insert(str2.sval, index).sval);
 debug_("tmpstr.sval", tmpstr.sval);
 return tmpstr;
}
// Imite insert de java.lang.String
String String::insert(int index, char ch)
{
 char aa[2];
 aa[0] = ch;
 aa[1] = 0;
 String tmpstr(this->insert(aa, index).sval);
 debug_("tmpstr.sval", tmpstr.sval);
 return tmpstr;
}
// Imite deleteCharAt de java.lang.String
String String::deleteCharAt(int loc)
{
 String tmpstr(sval);
 tmpstr._deleteCharAt(loc);
 return tmpstr;
}
// Imite delete de java.lang.String
// Note : -->le nom Java est "delete()", mais c'est un mot résérvé inutilisable en C++
// startIndex spécifie l'indice du premier caractère à enlever,
// et endIndex l'indice juste après le dernier caractère à supprimer.
// Ainsi, la sous-chaîne supprimée s'etend de startIndex à (endIndex - 1).
String String::deleteStr(int startIndex, int endIndex)
{
 // Par exemple -
 //      deleteStr(3,3) avec val = 'pokemon' retourne 'poon'
 String tmpstr(sval);
 tmpstr._deleteStr(startIndex, endIndex);
 return tmpstr;
}
// Imite reverse de java.lang.String
String String::reverse()
{
 // Par exemple :
 //              reverse() sur "12345" retourne "54321"
 String tmpstr(sval);
 tmpstr._reverse();
 return tmpstr;
}
// Imite valueOf de java.lang.String
String String::valueOf(char chars[], int startIndex, int numChars)
{
 verifyIndex(startIndex);
 int ii = strlen(chars);
 if (startIndex> ii)
 {
 cerr << "\nvalueOf() - startIndex greater than string length of"
 << "string passed" << endl;
 exit(0);
 }
 if ( (numChars+startIndex)> ii)
 {
 cerr << "\nvalueOf() - numChars exceeds the string length of"
 << "string passed" << endl;
 exit(0);
 }
 char *aa = strdup(chars);
 aa[startIndex + numChars] = 0;
 String tmpstr(& aa[startIndex]);
 free(aa);
 return tmpstr;
}
// Imite ensureCapacity de java.lang.String
// Utilisé par la classe StringBuffer.
// Pré-alloue la place pour un certain nombre de caractères.
// Utile si vous savez à l'avance que vous allez rajouter un grand nombre
// de petites chaînes à un StringBuffer
void String::ensureCapacity(int capacity)
{
 sval = (char *) my_realloc(sval, capacity);
 sval[0] = '\0';
 debug_("In ensureCapacity(int capacity) sval", sval);
}
// Imite setLength de java.lang.String
// Utilise par la classe StringBuffer.
void String::setLength(int len)
{
 sval = (char *) my_realloc(sval, len);
 sval[0] = '\0';
 debug_("In ensureCapacity(int len) sval", sval);
}
// Imite setCharAt de StringBuffer
void String::setCharAt(int where, char ch)
{
 verifyIndex(where);
 sval[where] = ch;
 debug_("in StringBuffer dstr()", "ok");
}
// ---- Fin des fonctions imitant java.lang.String -----
// Version surchargée, modifie directement l'objet
// La variable dummy donne une signature différente à la fonction.
void String::substring(int startIndex, int endIndex, bool dummy)
{
 this->_substring(startIndex, endIndex);
}
inline void String::_substring(int startIndex, int endIndex)
{
 verifyIndex(startIndex);
 verifyIndex(endIndex);
 if (!endIndex) // endIndex == 0
 strcpy(sval, & sval[startIndex] ) ;
 else
 {
 if (endIndex> startIndex)
 {
 strcpy(sval, & sval[startIndex] ) ;
 sval[endIndex -startIndex] = 0;
 }
 else
 {
 cerr << "\n_substring() - startIndex is greater than endIndex!!\n"
 << endl;
 exit(-1);
 }
 }
}
// Version surchargée, modifie directement l'objet
String String::deleteStr(int startIndex, int endIndex, bool dummy)
{
 this->_deleteStr(startIndex, endIndex);
 return *this;
}
inline void String::_deleteStr(int startIndex, int endIndex)
{
 verifyIndex(startIndex);
 verifyIndex(endIndex);
 // Par exemple -
 //      deleteStr(3,3) avec val = 'pokemon' retourne 'poon'
 char *tmpaa = strdup(sval); // ici malloc
 strcpy(& tmpaa[startIndex], & tmpaa[endIndex]);
 *this = tmpaa;
 free(tmpaa);
}
// Version surchargée, modifie directement l'objet
String String::deleteCharAt(int loc, bool dummy)
{
 this->_deleteCharAt(loc);
 return *this;
}
inline void String::_deleteCharAt(int loc)
{
 char *tmpaa = strdup(sval); // ici malloc
 strcpy(& tmpaa[loc], & tmpaa[loc+1]);
 *this = tmpaa;
 free(tmpaa);
}
// Retourne la chaîne avant regx. Trouve la première occurrence de regx.
String String::at(char *regx)
{
 char *tok = NULL;
 tok = strstr(sval, regx);
 if (tok == NULL)
 return(String(""));
 else
 {
 int res = (int) (tok - sval);
 char *lefttok = strdup(sval);
 memset(lefttok, 0, strlen(sval));
 strcpy(lefttok, & sval[res]);
 String tmpstr(lefttok);
 free(lefttok);
 return(tmpstr);
 }
}
// Retourne la chaîne avant regx. Trouve la première occurrence de regx.
String String::before(char *regx)
{
 char *tok = NULL;
 tok = strstr(sval, regx);
 if (tok == NULL)
 return(String(""));
 else
 {
 int res = (int) (tok - sval);
 char *lefttok = strdup(sval);
 lefttok[res] = 0;
 String tmpstr(lefttok);
 free(lefttok);
 return(tmpstr);
 }
}
// Retourne la chaîne après regx. Trouve la première occurrence de regx.
String String::after(char *regx)
{
 char *tok = NULL;
 tok = strstr(sval, regx);
 if (tok == NULL)
 return(String(""));
 else
 {
 int res = (int) (tok - sval);
 char *lefttok = strdup(sval);
 memset(lefttok, 0, strlen(sval));
 strcpy(lefttok, & sval[res + strlen(regx)]);
 String tmpstr(lefttok);
 free(lefttok);
 return(tmpstr);
 }
}
// Divise la chaîne et retourne une liste via le pointeur de tête
// de liste explodeH.
// Voir aussi token().
void String::explode(char *seperator)
{
 char *aa = NULL, *bb = NULL;
 aa = (char *) my_malloc(strlen(sval));
 for (bb = strtok(aa, seperator); bb != NULL; bb = strtok(NULL, seperator) )
 {
 String *tmp = new String(bb);
 String::explodeH.insert(String::explodeH.end(), *tmp);
 }
 my_free(aa);
 list<String>::iterator iter1; // voir include/g++/stl_list.h
 debug_("Before checking explode..", "ok");
 if (String::explodeH.empty() == true )
 {
 debug_("List is empty!!", "ok");
 }
 for (iter1 = String::explodeH.begin(); iter1 != String::explodeH.end(); iter1++)
 {
 if (iter1 == NULL)
 {
 debug_("Iterator iter1 is NULL!!", "ok" );
 break;
 }
 debug_("(*iter1).sval", (*iter1).sval);
 }
}
// Version surchargée de explode(). Retourne un tableau
// de chaînes et le nombre total dans la référence strcount
// Voir aussi token().
String *String::explode(int & strcount, char seperator = ' ')
{
 String aa(sval);
 aa.trim(true);
 strcount = 0;
 for (int ii = 0, jj = strlen(aa.sval); ii < jj; ii++)
 {
 if (aa.sval[ii] == seperator)
 strcount++;
 }
 String *tmpstr = new String[strcount+1];
 if (!strcount) // strcount == 0
 tmpstr[0] = aa.sval;
 else
 {
 for (int ii = 0; ii <= strcount; ii++)
 tmpstr[ii] = aa.token();
 }
 return tmpstr;
}
// Agrège les chaînes pointées par la tête de liste
// explodeH et retourne la classe String.
void String::implode(char *glue)
{
}
// Agrège les chaînes pointées par la tête de liste
// explodeH et retourne la classe String.
void String::join(char *glue)
{
 implode(glue);
}
// Répète la chaîne input n fois.
String String::repeat(char *input, unsigned int multiplier)
{
 // Pour exemple -
 // repeat("k", 4) retourne "kkkk"
 if (!input) // input == NULL
 {
 return (String(""));
 }
 char *aa = (char *) my_malloc(strlen(input) * multiplier);
 for (unsigned int tmpii = 0; tmpii < multiplier; tmpii++)
 {
 strcat(aa, input);
 }
 String tmpstr(aa);
 my_free(aa);
 return tmpstr;
}
// Renverse la chaîne.
// Version surchargée de reverse(). Modifie directement l'objet.
void String::reverse(bool dummy)
{
 this->_reverse();
}
inline void String::_reverse()
{
 // Par exemple -
 //              reverse() sur "12345" retourne "54321"
 char aa;
 unsigned long tot_len = strlen(sval);
 unsigned long midpoint = tot_len / 2;
 for (unsigned long tmpjj = 0; tmpjj < midpoint; tmpjj++)
 {
 aa = sval[tmpjj];  // variable temporaire de stockage
 sval[tmpjj] = sval[tot_len - tmpjj - 1];  // permute les valeurs
 sval[tot_len - tmpjj - 1] = aa; // permute les valeurs
 }
}
// Change certain caractères.
// Par exemple ("abcd", "ABC") change toutes les occurrences de chaque
// caractère de 'from' en le caractère correspondant dans 'to'
String String::tr(char *from, char *to)
{
 int lenfrom = strlen(from), lento = strlen(to);
 if (lento> lenfrom)
 lento = lenfrom; // choisit le min
 else
 if (lento < lenfrom)
 lenfrom = lento; // choisit le min
 debug_("lento", lento);
 register char *aa = strdup(sval);
 for (int ii = 0, jj = strlen(sval); ii < jj; ii++) // pour chaque caractère dans val
 {
 for (int kk = 0; kk < lento; kk++) // pour chaque caractère dans "from"
 {
 if (aa[ii] == from[kk])
 aa[ii] = to[kk];
 }
 }
 String tmpstr(aa);
 free(aa);
 return tmpstr;
}
// Centre le texte
String String::center(int padlength, char padchar = ' ')
{
 // Par exemple -
 //              center(10, '*') avec sval="aa" retourne "****aa****"
 //              center(10) avec sval="aa" retourne "    aa    "
 // Le résultat est une chaîne contenant 'padlength' caractères avec sval au milieu.
 int tmpii = sizeof(char) * (padlength + strlen(sval) + 10);
 char *aa = (char *) malloc(tmpii);
 memset(aa, 0, tmpii);
 for (int jj = 0, kk = (int) padlength/2; jj < kk; jj++)
 {
 aa[jj] = padchar;
 }
 strcat(aa, sval);
 for (int jj = strlen(aa), kk = jj + (int) padlength/2; jj < kk; jj++)
 {
 aa[jj] = padchar;
 }
 String tmpstr(aa);
 free(aa);
 return tmpstr;
}
// Formate la chaîne originale en plaçant <number> caractères <padchar>
// entre chaque ensemble de mots délimités par des blancs. Les blancs en début et
// en fin sont toujours supprimés. Si <number> est omis ou vaut 0, alors tous les
// espaces de la chaîne sont supprimés. Par défaut, <number> vaut 0 et padchar ' '.
String String::space(int number, char padchar = ' ')
{
 // Par exemple -
 //              space(3) avec sval = "Je ne sais pas"
 //                              retournera "Je   ne   sais   pas"
 //              space(1, '_') avec sval = "Un lieu profondement obscur"
 //                              retournera "Un_lieu_profondement_obscur"
 //              space() avec sval = "Je   sais     cela"
 //                              retournera "Jesaiscela"
 debug_("this->sval", this->sval );
 String tmpstr = this->trim().sval;
 debug_("tmpstr.sval", tmpstr.sval );
 // compte les espaces
 int spacecount = 0;
 for (int ii = 0, jj = strlen(tmpstr.sval); ii < jj; ii++)
 {
 if (tmpstr.sval[ii] == ' ')
 spacecount++;
 }
 debug_("spacecount", spacecount);
 char ee[2];
 ee[0] = padchar;
 ee[1] = 0;
 String bb = tmpstr.repeat(ee, spacecount);
 int tmpii = sizeof(char) * (strlen(tmpstr.sval) + (number * spacecount) + 20);
 char *aa = (char *) malloc(tmpii);
 memset(aa, 0, tmpii);
 for (int ii = 0, jj = strlen(tmpstr.sval); ii < jj; ii++)
 {
 if (tmpstr.sval[ii] == ' ')
 strcat(aa, bb.sval);
 else
 {
 ee[0] = sval[ii];
 strcat(aa, ee);
 }
 }
 tmpstr = aa;
 free(aa);
 return tmpstr;
}
// Le résultat est une chaîne comprenant tous les caractères compris
// entre <start> et <end> (inclus).
String String::xrange(char start, char end)
{
 // Par exemple -
 //      xrange('a', 'j') retourne val = "abcdefghij"
 //      xrange(1, 8) retourne val = "12345678"
 if (end < start)
 {
 cerr << "\nThe 'end' character is less than 'start' !!" << endl;
 return String("");
 }
 // Note : 'end' est plus grand que 'start' ! Et ajoute +1
 int tmpii = sizeof(char) * (end - start + 11);
 char *aa = (char *) malloc(tmpii);
 memset(aa, 0, tmpii);
 debug_("xrange tmpii", tmpii);
 for (int ii = start, jj = 0; ii <= end; ii++, jj++)
 {
 aa[jj] = ii;
 debug_("xrange aa[jj]", aa[jj] );
 }
 String tmpstr(aa);
 free(aa);
 return tmpstr;
}
// Supprime tous les caractères contenus dans <list>. Le caractère par défaut pour
// <list> est l'espace ' '.
String String::compress(char *list = " ")
{
 // Par exemple -
 //      compress("$,%") avec sval = "$1,934" retourne "1934"
 //      compress() avec sval = "appelez moi alavoor vasudevan" returns "appelezmoialavoorvasudevan"
 int lenlist = strlen(list);
 register char *aa = strdup(sval);
 for (int ii = 0, jj = strlen(sval); ii < jj; ii++) // pour chaque caractère de sval
 {
 for (int kk = 0; kk < lenlist; kk++) // pour chaque caractère de "from"
 {
 if (aa[ii] == list[kk])
 {
 strcpy(& aa[ii], & aa[ii+1]);
 }
 }
 }
 String tmpstr(aa);
 free(aa);
 return tmpstr;
}
// <newstr> est insérée dans sval à partir de <start>. <newstr> est
// complétée ou tronquée à <length> caractères. <length> est par défaut la
// longueur de la chaîne <newstr>
String String::insert(char *newstr, int start = 0, int lengthstr = 0, char padchar = ' ')
{
 // Par exemple -
 //      insert("quelquechose de nouveau", 8, 30, '*') avec sval = "vieille chose"
 //              retourne "vieille quelquechose de nouveau*******chose"
 int tmplen = sizeof(char) * strlen(sval) + strlen(newstr) + lengthstr + 10;
 char *tmpaa = (char *) malloc (tmplen);
 memset(tmpaa, 0, tmplen);
 if (!start) // start == 0
 {
 strcpy(tmpaa, newstr);
 strcat(tmpaa, this->sval);
 }
 else
 {
 strncpy(tmpaa, this->sval, start);
 strcat(tmpaa, newstr);
 strcat(tmpaa, & this->sval[start]);
 }
 String tmpstr(tmpaa);
 free(tmpaa);
 return tmpstr;
}
// Fonction insert surchargée
String String::insert(int index, String str2, bool dummy)
{
 *this =  this->insert(str2.sval, index).sval;
 //debug_("tmpstr.sval", tmpstr.sval);
 return *this;
}
// Fonction insert surchargée
String String::insert(int index, char ch, bool dummy)
{
 char aa[2];
 aa[0] = ch;
 aa[1] = 0;
 *this = this->insert(aa, index).sval;
 //debug_("tmpstr.sval", tmpstr.sval);
 return *this;
}
// Le résultat est une chaîne de <length> caractères composée des caractères les plus à gauches de sval.
// Méthode rapide pour justifier à gauche une chaîne.
String String::left(int slength = 0, char padchar = ' ')
{
 // Par exemple -
 //      left(15) avec sval = "Wig"       retourne "Wig            "
 //      left(4) avec  sval = "Wighat"    retourne "Wigh"
 //      left() avec   sval = "   Wighat" retourne "Wighat   "
 if (!slength) // slength == 0
 slength = strlen(sval);
 debug_("left() slength", slength);
 int tmpii = slength + 20;
 char *aa = (char *) malloc(tmpii);
 memset(aa, 0, tmpii);
 debug_("this->ltrim().sval ", this->ltrim().sval);
 strcpy(aa, this->ltrim().sval);
 debug_("left() aa", aa );
 int currlen = strlen(aa);
 if (currlen < slength)
 {
 // pad the string now
 char ee[2];
 ee[0] = padchar;
 ee[1] = 0;
 strcat(aa, this->repeat(ee, (unsigned int) (slength-currlen) ).sval);
 }
 else
 {
 aa[slength] = 0;
 }
 debug_("left() aa", aa );
 String tmpstr(aa);
 free(aa);
 return tmpstr;
}
// Le résultat est une chaîne de <length> caractères composée des caractères les plus à droite de sval.
// Méthode rapide pour justifier à droite un chaîne.
String String::right(int slength = 0, char padchar = ' ')
{
 // Par exemple -
 //      right(10) avec sval = "never to saying   " retourne " to saying"
 //      right(4) avec  sval = "Wighat"             retourne "ghat"
 //      right(8) avec  sval = "4.50"               retourne "    4.50"
 //      right() avec   sval = "  4.50     "        retourne "       4.50"
 if (!slength) // slength == 0
 slength = strlen(sval);
 debug_("right() slength", slength);
 int tmpii = slength + 20;
 char *aa = (char *) malloc(tmpii);
 memset(aa, 0, tmpii);
 int currlen = strlen(this->rtrim().sval);
 debug_("right() currlen", currlen );
 if (currlen < slength)
 {
 // pad the string now
 char ee[2];
 ee[0] = padchar;
 ee[1] = 0;
 strcpy(aa, this->repeat(ee, (unsigned int) (slength-currlen) ).sval);
 strcat(aa, this->rtrim().sval);
 debug_("right() aa", aa );
 }
 else
 {
 strcpy(aa, this->rtrim().sval);
 strcpy(aa, & aa[currlen-slength]);
 aa[slength] = 0;
 }
 debug_("right() aa", aa );
 String tmpstr(aa);
 free(aa);
 return tmpstr;
}
// <newstr> est superposée à sval en commençant à <start>. <newstr> est complétée
// ou tronquée à <length> caractères. Par défaut, la longueur <length> est la
// longueur de la chaîne newstr.
String String::overlay(char *newstr, int start = 0, int slength = 0, char padchar = ' ')
{
 // Par exemple -
 //      overlay("12345678", 4, 10, '*') sur sval = "oldthing is very bad"
 //              retourne "old12345678**ery bad"
 //      overlay("12345678", 4, 5, '*') sur sval = "oldthing is very bad"
 //              retourne "old12345ery bad"
 int len_newstr = strlen(newstr);
 if (!slength) // slength == 0
 slength = len_newstr;
 char *aa = (char *) malloc(slength + len_newstr + 10);
 aa[0] = 0;
 char ee[2];
 ee[0] = padchar;
 ee[1] = 0;
 if (len_newstr < slength)
 {
 // remplire maintenant
 strcpy(aa, newstr);
 strcat(aa, this->repeat(ee, (slength-len_newstr)).sval );
 }
 else
 {
 strcpy(aa, newstr);
 aa[slength] = 0;
 }
 // Maintenant recouvrir la chaîne
 String tmpstr(sval);
 debug_("tmpstr.sval", tmpstr.sval);
 for (int ii=start, jj=strlen(tmpstr.sval), kk=start+slength, mm=0;
 ii < jj; ii++, mm++)
 {
 if (ii == kk)
 break;
 if (mm == slength)
 break;
 tmpstr.sval[ii] = aa[mm];
 }
 free(aa);
 debug_("tmpstr.sval", tmpstr.sval);
 return tmpstr;
}
// Si la chaîne est littéralement égale à ou non égale à
// Si type vaut false alors ==
bool String::_equalto(const String & rhs, bool type = false)
{
 if (type == false) // test ==
 {
 if (strlen(rhs.sval) == strlen(sval))
 {
 if (!strncmp(rhs.sval, sval, strlen(sval))) //  == 0
 return true;
 else
 return false;
 }
 else
 return false;
 }
 else // test !=
 {
 if (strlen(rhs.sval) != strlen(sval))
 {
 if (!strncmp(rhs.sval, sval, strlen(sval))) //  == 0
 return true;
 else
 return false;
 }
 else
 return false;
 }
}
// Si la chaîne est littéralement égale à ou non égale à
// Si type vaut false alors ==
bool String::_equalto(const char *rhs, bool type = false)
{
 if (type == false) // test ==
 {
 if (strlen(rhs) == strlen(sval))
 {
 if (!strncmp(rhs, sval, strlen(sval))) //  == 0
 return true;
 else
 return false;
 }
 else
 return false;
 }
 else // test !=
 {
 if (strlen(rhs) != strlen(sval))
 {
 if (!strncmp(rhs, sval, strlen(sval))) //  == 0
 return true;
 else
 return false;
 }
 else
 return false;
 }
}
// Fonction synonyme de vacuum()
void String::clear()
{
 sval = (char *) my_realloc(sval, 10);
 sval[0] = '\0';
}
// Supprime tous les caractères 'ch' en fin de chaîne - voir aussi chop()
// Par exemple :
//      sval = "abcdef\n\n\n" alors chopall() = "abcdef"
//      sval = "abcdefffff" alors chopall('f') = "abcde"
void String::chopall(char ch='\n')
{
 unsigned long tmpii = strlen(sval) - 1 ;
 for (; tmpii>= 0; tmpii--)
 {
 if (sval[tmpii] == ch)
 sval[tmpii] = 0;
 else
 break;
 }
}
// Supprime le caractère de fin de la chaîne - voir aussi chopall()
// chop() est souvent utilisé pour supprimer le caractère de fin de ligne
void String::chop()
{
 sval[strlen(sval)-1] = 0;
}
// Version surchargée de trim(). Modifie directement l'objet.
void String::trim(bool dummy)
{
 this->_trim();
}
inline void String::_trim()
{
 this->rtrim(true);
 this->ltrim(true);
 debug_("this->sval", this->sval);
}
// Version surchargée de ltrim(). Modifie directement l'objet.
void String::ltrim(bool dummy)
{
 this->_ltrim();
}
inline void String::_ltrim()
{
 // Peut causer des problèmes dans my_realloc car
 // l'emplacement de bb peut être détruit !
 char *bb = sval;
 if (bb == NULL)
 return;
 while (isspace(*bb))
 bb++;
 debug_("bb", bb);
 if (bb != NULL && bb != sval)
 {
 debug_("doing string copy", "done");
 _str_cpy(bb); // cause des problèmes dans my_realloc et bb va être détruit !
 }
 else
 debug_("Not doing string copy", "done");
}
String String::ltrim()
{
 String tmpstr(sval);
 tmpstr._ltrim();
 return tmpstr;
}
// Version surchargée de rtrim(). Modifie directement l'objet.
void String::rtrim(bool dummy)
{
 this->_rtrim();
}
inline void String::_rtrim()
{
 for (long tmpii = strlen(sval) - 1 ; tmpii>= 0; tmpii--)
 {
 if ( isspace(sval[tmpii]) )
 sval[tmpii] = '\0';
 else
 break;
 }
}
String String::rtrim()
{
 String tmpstr(sval);
 tmpstr._rtrim();
 return tmpstr;
}
// Utilisé pour arrondir la partie frationnaire de réels.
// Arrondit les réels avec la précision souhaitée et stocke
// le résultat dans le champ sval de la chaîne.
// Retourne aussi le résultat comme un char *.
void String::roundf(float input_val, short precision)
{
 float   integ_flt, deci_flt;
 const   short MAX_PREC = 4;
 debug_("In roundf", "ok");
 if (precision> MAX_PREC) // précision maximale supportée
 precision = MAX_PREC;
 // récupère les parties entière et décimale du réel
 deci_flt = modff(input_val, & integ_flt);
 for (int tmpzz = 0; tmpzz < precision; tmpzz++)
 {
 debug_("deci_flt", deci_flt);
 deci_flt *= 10;
 }
 debug_("deci_flt", deci_flt);
 unsigned long deci_int = (unsigned long) ( rint(deci_flt) );
 sval = (char *) my_malloc(NUMBER_LENGTH); // float 70 chiffres max
 if (deci_int> 999) // (MAX_PREC) chiffres
 sprintf(sval, "%lu.%lu", (unsigned long) integ_flt, deci_int);
 else
 if (deci_int> 99) // (MAX_PREC - 1) chiffres
 sprintf(sval, "%lu.0%lu", (unsigned long) integ_flt, deci_int);
 else
 if (deci_int> 9) // (MAX_PREC - 2) chiffres
 sprintf(sval, "%lu.00%lu", (unsigned long) integ_flt, deci_int);
 else
 sprintf(sval, "%lu.00000%lu", (unsigned long) integ_flt, deci_int);
}
void String::roundd(double input_val, short precision)
{
 double  integ_flt, deci_flt;
 const   short MAX_PREC = 6;
 if (precision> MAX_PREC) // précision maximale supportée
 precision = MAX_PREC;
 debug_("In roundd", "ok");
 // récupère les parties entière et décimale du réel
 deci_flt = modf(input_val, & integ_flt);
 for (int tmpzz = 0; tmpzz < precision; tmpzz++)
 {
 debug_("deci_flt", deci_flt);
 deci_flt *= 10;
 }
 debug_("deci_flt", deci_flt);
 sval = (char *) my_malloc(NUMBER_LENGTH); // double 70 chiffres max
 unsigned long deci_int = (unsigned long) ( rint(deci_flt) );
 if (deci_int> 99999) // (MAX_PREC) chiffres
 sprintf(sval, "%lu.%lu", (unsigned long) integ_flt, deci_int);
 else
 if (deci_int> 9999) // (MAX_PREC - 1) chiffres
 sprintf(sval, "%lu.0%lu", (unsigned long) integ_flt, deci_int);
 else
 if (deci_int> 999) // (MAX_PREC - 2) chiffres
 sprintf(sval, "%lu.00%lu", (unsigned long) integ_flt, deci_int);
 else
 if (deci_int> 99) // (MAX_PREC - 3) chiffres
 sprintf(sval, "%lu.000%lu", (unsigned long) integ_flt, deci_int);
 else
 if (deci_int> 9) // (MAX_PREC - 4) chiffres
 sprintf(sval, "%lu.0000%lu", (unsigned long) integ_flt, deci_int);
 else // (MAX_PREC - 5) chiffres
 sprintf(sval, "%lu.00000%lu", (unsigned long) integ_flt, deci_int);
}
// Fournie seulement pour documenter
// Vous devriez utiliser la fonction indexOf()
bool String::contains(char *str2, int startIndex = 0)
{
 // Par exemple -
 //              if (indexOf("ohboy")> -1 )
 //                      cout << "\nString contient 'ohboy'" << endl;
 //              if (indexOf("ohboy") < 0 )
 //                      cout << "\nString NE contient PAS 'ohboy'" << endl;
 //              if (indexOf("ohboy", 4)> -1 )
 //                      cout << "\nString contient 'ohboy'" << endl;
 //              if (indexOf("ohboy", 4) < 0 )
 //                      cout << "\nString NE contient PAS 'ohboy'" << endl;
 cerr << "\nYou must use indexOf() function instead of contains()\n" << endl;
 exit(-1);
}
// Fonction synonyme de empty()
bool String::isNull()
{
 if (sval[0] == '\0')
 return true;
 else
 {
 if (sval == NULL)
 return true;
 else
 return false;
 }
}
// Les caractères blancs de début et de fin sont ignorés.
bool String::isInteger()
{
 String tmpstr(sval);
 tmpstr.trim(true);
 debug_("tmpstr.sval", tmpstr.sval );
 if ( strspn ( tmpstr.sval, "0123456789" ) != strlen(tmpstr.sval) )
 return ( false ) ;
 else
 return ( true ) ;
}
// Fonction surchargée
bool String::isInteger(int pos)
{
 verifyIndex(pos);
 return (isdigit(sval[pos]));
}
// Les caractères blancs de début et de fin sont ignorés.
bool String::isNumeric()
{
 String tmpstr(sval);
 tmpstr.trim(true);
 debug_("tmpstr.sval", tmpstr.sval );
 if ( strspn ( tmpstr.sval, "0123456789.+-e" ) != strlen(tmpstr.sval) )
 return ( false ) ;
 else
 return ( true ) ;
}
// Fonction surchargée
bool String::isNumeric(int pos)
{
 verifyIndex(pos);
 return (isdigit(sval[pos]));
}
bool String::isEmpty()
{
 if (strlen(sval) == 0)
 return true;
 else
 return false;
}
// Voir aussi explode()
//      Attention : l'objet String est modifié et ne contient plus le token renvoyé.
//                  Il est conseillé de sauvegarder la chaîne originale avant d'appeler
//                  cette fonction, comme par exemple ainsi :
//              String savestr = origstr;
//              String aa, bb, cc;
//              aa = origstr.token();
//              bb = origstr.token();
//              cc = origstr.token();
//
//  Cette méthode retourne le premier token non séparateur (par défaut espace) de la chaîne.
String String::token(char seperator = ' ')
{
 char ee[2];
 ee[0] = seperator;
 ee[1] = 0;
 char *res = strtok(sval, ee);
 if (!res) // if res == NULL
 {
 debug_("token", res);
 debug_("sval", sval);
 return(String(sval));
 }
 else
 {
 String tmpstr(res);
 // Utilise la longueur de la chaîne sval et pas celle de res
 // car strtok() a mis un NULL ('\0') sur l'emplacement et
 // aussi car strtok() ignore les blancs initiaux de sval
 strcpy(sval, & sval[strlen(sval)+1]);
 debug_("token", res);
 debug_("sval", sval);
 return tmpstr;
 }
}
String String::crypt(char *original, char *salt)
{
 return String("");
}
int String::toInteger()
{
 if ( strlen(sval) == 0 ) {
 cerr << "Cannot convert a zero length string "
 << " to a numeric" << endl ;
 abort() ;
 }
 if ( ! isInteger() ) {
 cerr << "Cannot convert string [" << sval
 << "] to an integer numeric string" << endl ;
 abort() ;
 }
 return ( atoi ( sval ) ) ;
}
long String::parseLong()
{
 if ( strlen(sval) == 0 ) {
 cerr << "Cannot convert a zero length string "
 << " to a numeric" << endl ;
 abort() ;
 }
 if ( ! isInteger() ) {
 cerr << "Cannot convert string [" << sval
 << "] to an integer numeric string" << endl ;
 abort() ;
 }
 return ( atol ( sval ) ) ;
}
double String::toDouble()
{
 if ( strlen(sval) == 0 ) {
 cerr << "Cannot convert a zero length string "
 << " to a numeric" << endl ;
 abort() ;
 }
 if ( ! isNumeric() ) {
 cerr << "Cannot convert string [" << sval
 << "] to a double numeric string" << endl ;
 abort() ;
 }
 double d = atof ( sval ) ;
 return ( d ) ;
}
String String::getline(FILE *infp = stdin)
{
 register char ch, *aa = NULL;
 register const short SZ = 100;
 // Valeur initiale de ii> SZ donc aa est de la mémoire allouée
 register int jj = 0;
 for (int ii = SZ+1; (ch = getc(infp)) != EOF; ii++, jj++)
 {
 if (ii> SZ)  // alloue la memoire en paquets de SZ pour la performance
 {
 aa = (char *) realloc(aa, jj + ii + 15);  // +15 par sécurité
 ii = 0;
 }
 if (ch == '\n')  // lit jusqu'à rencontrer une nouvelle ligne
 break;
 aa[jj] = ch;
 }
 aa[jj] = 0;
 _str_cpy(aa);  // met la valeur dans la chaîne
 free(aa);
 return *this;
}
/*
void String::Format(const char *fmt, ... )
{
 va_list iterator;
 va_start(iterator, fmt );
 va_end(iterator);
}
*/
// contrôle qu'un indice se trouve dans les limites
inline void String::verifyIndex(unsigned long index) const
{
 if (index < 0 || index>= strlen(sval) )
 {
 // throw "Index Out Of Bounds Exception";
 cerr << "Index Out Of Bounds Exception at ["
 << index << "] in:\n" << sval << endl;
 exit(1);
 }
}
// contrôle qu'un indice se trouve dans les limites
inline void String::verifyIndex(unsigned long index, char *aa) const
{
 if (!aa) // aa == NULL
 {
 cerr << "\nverifyIndex(long, char *) str null value\n" << endl;
 exit(-1);
 }
 if (index < 0 || index>= strlen(aa) )
 {
 cerr << "Index Out Of Bounds Exception at ["
 << index << "] in:\n" << aa << endl;
 exit(1);
 }
}
//////////////////////////////////////////////////////////
// Les fonctions privées commencent à partir d'ici...
//////////////////////////////////////////////////////////
void String::_str_cpy(char bb[])
{
 debug_("In _str_cpy bb", bb);
 if (bb == NULL)
 {
 sval[0] = '\0';
 return;
 }
 unsigned long tmpii = strlen(bb);
 if (tmpii == 0)
 {
 sval[0] = '\0';
 return;
 }
 debug_("In _str_cpy tmpii", tmpii);
 debug_("In _str_cpy sval", sval);
 sval = (char *) my_realloc(sval, tmpii);
 //sval = new char [tmpii + SAFE_MEM_2];
 debug_("In _str_cpy bb", bb);
 strncpy(sval, bb, tmpii);
 debug_("In _str_cpy sval", sval);
 sval[tmpii] = '\0';
 debug_("In _str_cpy sval", sval);
}
void String::_str_cpy(int bb)
{
 char tmpaa[100];
 sprintf(tmpaa, "%d", bb);
 _str_cpy(tmpaa);
}
void String::_str_cpy(unsigned long bb)
{
 char tmpaa[100];
 sprintf(tmpaa, "%ld", bb);
 _str_cpy(tmpaa);
}
void String::_str_cpy(float bb)
{
 char tmpaa[100];
 sprintf(tmpaa, "%f", bb);
 _str_cpy(tmpaa);
}
void String::_str_cat(char bb[])
{
 unsigned long tmpjj = strlen(bb), tmpii = strlen(sval);
 sval = (char *) my_realloc(sval, tmpii + tmpjj);
 debug_("sval in _str_cat() ", sval);
 strncat(sval, bb, tmpjj);
}
void String::_str_cat(int bb)
{
 char tmpaa[100];
 sprintf(tmpaa, "%d", bb);
 unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(sval);
 sval = (char *) my_realloc(sval, tmpii + tmpjj);
 strncat(sval, tmpaa, tmpjj);
}
void String::_str_cat(unsigned long bb)
{
 char tmpaa[100];
 sprintf(tmpaa, "%ld", bb);
 unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(sval);
 sval = (char *) my_realloc(sval, tmpii + tmpjj);
 strncat(sval, tmpaa, tmpjj);
}
void String::_str_cat(float bb)
{
 char tmpaa[100];
 sprintf(tmpaa, "%f", bb);
 unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(sval);
 sval = (char *) my_realloc(sval, tmpii + tmpjj);
 strncat(sval, tmpaa, tmpjj);
}
//////////////////////////////////////////////////////////
// Les opérateurs sont définis à partir d'ici...
//////////////////////////////////////////////////////////
String operator+ (const String & lhs, const String & rhs)
{
 /*******************************************************/
 // Note : pour concaténer deux chaînes, transtyper d'abord
 // en String comme ici :
 //aa = (String) "alkja " + " 99djd " ;
 /*******************************************************/
 String tmp(lhs);
 tmp._str_cat(rhs.sval);
 return(tmp);
 /*
 if (String::_global_String == NULL)
 {
 String::_global_String = new String;
 String::_global_String->_str_cpy(lhs.sval);
 String::_global_String->_str_cat(rhs.sval);
 //return *String::_global_String;
 return String(String::_global_String->val);
 }
 */
 /*
 else
 if (String::_global_String1 == NULL)
 {
 debug_("1)global", "ok" );
 String::_global_String1 = new String;
 String::_global_String1->_str_cpy(lhs.sval);
 String::_global_String1->_str_cat(rhs.sval);
 return *String::_global_String1;
 }
 */
 /*
 else
 {
 fprintf(stderr, "\nError: cannot alloc _global_String\n");
 exit(-1);
 }
 */
 /*
 String *aa = new String;
 aa->_str_cpy(lhs.sval);
 aa->_str_cat(rhs.sval);
 return *aa;
 */
}
String String::operator+ (const String & rhs)
{
 String tmp(*this);
 tmp._str_cat(rhs.sval);
 debug_("rhs.sval in operator+", rhs.sval );
 debug_("tmp.sval in operator+", tmp.sval );
 return (tmp);
}
// L'utilisation d'une référence accélèrera l'opérateur =
String& String:: operator= ( const String& rhs )
{
 if (& rhs == this)
 {
 debug_("Fatal Error: In operator(=). rhs is == to 'this pointer'!!", "ok" );
 return *this;
 }
 this->_str_cpy(rhs.sval);
 debug_("rhs value", rhs.sval );
 // Libere la memoire des variables globales
 //_free_glob(& String::_global_String);
 //if (String::_global_String == NULL)
 //fprintf(stderr, "\n_global_String is freed!\n");
 //return (String(*this));
 return *this;
}
// L'utilisation d'une référence accélèrera l'opérateur =
String& String::operator+= (const String & rhs)
{
 /*******************************************************/
 // Note : pour concaténer deux chaînes, transtyper d'abord
 // en String comme ici :
 //aa = (String) "cccc " + " dddd " ;
 /*******************************************************/
 if (& rhs == this)
 {
 debug_("Fatal error: In operator+= rhs is equals 'this' ptr", "ok");
 return *this;
 }
 this->_str_cat(rhs.sval);
 return *this;
 //return (String(*this));
}
bool String::operator== (const String & rhs)
{
 return(_equalto(rhs.sval));
}
bool String::operator== (const char *rhs)
{
 return(_equalto(rhs));
}
bool String::operator!= (const String & rhs)
{
 return(_equalto(rhs.sval, true));
}
bool String::operator!= (const char *rhs)
{
 return(_equalto(rhs, true));
}
char String::operator[] (unsigned long Index) const
{
 verifyIndex(Index);
 return sval[Index];
}
char & String::operator[] (unsigned long Index)
{
 verifyIndex(Index);
 return sval[Index];
}
istream & operator>> (istream & In, String & str2)
{
 // alloue la taille max de 2048 caractères
 static char aa[MAX_ISTREAM_SIZE];
 In>> aa;
 str2 = aa; // affecte aa à la référence
 return In; // retourne un istream
}
ostream & operator << (ostream & Out, const String & str2)
{
 Out << str2.sval;
 return Out;
}
////////////////////////////////////////////////////
//  Imite StringBuffer Object
//      MéThodes de StringBuffer
////////////////////////////////////////////////////
// Imite StringBuffer ; le constructeur par défaut
// (celui sans paramètre) réserve de la place pour 16
// caractères.
StringBuffer::StringBuffer()
 :String()   // appelle le constructeur de la classe de base sans paramètres
{
 debug_("in StringBuffer cstr()", "ok");
}
// Imite StringBuffer
StringBuffer::StringBuffer(int size)
 :String(size, true) // appelle le constructeur de la classe de base sans paramètres
{
 // String(size, true) -- ne pas l'appeler ici dans le corps de la
 // fonction mais durant la phase d'initialisation pour éviter un
 // appel supplémentaire du constructeur par défaut de la classe de
 // base et être plus rapide et plus efficace
 debug_("in StringBuffer cstr(int size)", "ok");
}
// Imite StringBuffer
// appelle le constructeur de la classe de base avec une chaîne en paramètre
StringBuffer::StringBuffer(String str)
 :String(str.val())  // appelle le constructeur de la classe de base
{
 // String(str.val()) -- ne pas l'appeler ici dans le corps de la
 // fonction mais durant la phase d'initialisation pour éviter un
 // appel supplémentaire du constructeur par défaut de la classe de
 // base et être plus rapide et plus efficace
 debug_("in StringBuffer cstr(String str)", "ok");
}
// Imite StringBuffer
StringBuffer::~StringBuffer()
{
 debug_("in StringBuffer dstr()", "ok");
}
// Imite la classe Float
// appelle le constructeur de la classe de base avec une chaîne en paramètre
Float::Float(String str)
 :String(str.val())  // appelle le constructeur de la classe de base
{
 // String(str.val()) -- ne pas l'appeler ici dans le corps de la
 // fonction mais durant la phase d'initialisation pour éviter un
 // appel supplémentaire du constructeur par défaut de la classe de
 // base et être plus rapide et plus efficace
 debug_("in Float cstr(String str)", "ok");
}
// Imite la classe Double
// appelle le constructeur de la classe de base avec une chaîne en paramètre
Double::Double(String str)
 :String(str.val())  // appelle le constructeur de la classe de base
{
 // String(str.val()) -- ne pas l'appeler ici dans le corps de la
 // fonction mais durant la phase d'initialisation pour éviter un
 // appel supplémentaire du constructeur par défaut de la classe de
 // base et être plus rapide et plus efficace
 debug_("in Double cstr(String str)", "ok");
}
// Imite la classe StringReader
// appelle le constructeur de la classe de base avec une chaîne en paramètre
StringReader::StringReader(String str)
 :String(str.val())  // appelle le constructeur de la classe de base
{
 // String(str.val()) -- ne pas l'appeler ici dans le corps de la
 // fonction mais durant la phase d'initialisation pour éviter un
 // appel supplémentaire du constructeur par défaut de la classe de
 // base et être plus rapide et plus efficace
 debug_("in StringReader cstr(String str)", "ok");
 _curpos = 0;
 _mark_pos = 0;
}
// Imite la méthode read de la classe StringReader
int StringReader::read()
{
 _curpos++;
 if (_curpos> strlen(sval) )
 return -1;
 return sval[_curpos-1];
}
// Lit des caractères dans une portion d'un tableau
// cbuf est le tampon destination, offset est le décalage indiquant où écrire
// les caractères, length est le nombre maximum de caractères à lire
// Retourne le nombre de caractères lus ou -1 en cas de fin du flux
int StringReader::read(char cbuf[], int offset, int length)
{
 if (_curpos> strlen(sval) - 1 )
 return -1;
 strncpy(& cbuf[offset], & sval[_curpos], length);
 _curpos += length;
 return length;
}
// Marque la position courante dans le flux. Les appels suivants
// à reset() repositionneront le flux à ce point.
// Le paramètre 'readAheadLimit' limite le nombre de caractères qui
// pourraient être lus tout en préservant la marque.
// Comme le flux d'entrée provient d'une chaîne, il n'y a pas de
//limite actuellement, donc l'argument est ignoré.
void StringReader::mark(int readAheadLimit)
{
 _mark_pos = _curpos;
}
// réinitialise le flux à la marque la plus récente, ou au début de
// la chaîne si aucun marque n'a été posée
void StringReader::reset()
{
 _curpos = _mark_pos;
}
// Passe des caractères. Cette méthode bloquera jusqu'a ce que des caractères soient
// disponibles, qu'une erreur arrive ou que la fin du flux soit atteinte.
// Paramètre ii : nombre de caractères à passer
// Retourne : le nombre courant de caractères passés
long StringReader::skip(long ii)
{
 long tmpjj = strlen(sval) - _curpos - 1;
 if (ii> tmpjj)
 ii = tmpjj;
 _curpos = ii;
 return ii;
}
// Imite la classe StringWriter
StringWriter::StringWriter()
{
 debug_("in StringWriter cstr()", "ok");
 char *aa = (char *) malloc(300);
 memset(aa, ' ', 299); // remplit avec des blancs
 aa[300] = 0;
 String((char *) aa);
 my_free(aa);
}
StringWriter::StringWriter(int bufferSize)
{
 debug_("in StringWriter cstr(int bufferSize)", "ok");
 char *aa = (char *) malloc(bufferSize);
 memset(aa, ' ', bufferSize-1); // remplit avec des blancs
 aa[bufferSize] = 0;
 String((char *) aa);
 my_free(aa);
}
void StringWriter::write(int bb)
{
 _str_cat(bb);
}
void StringWriter::write(char *bb)
{
 _str_cat(bb);
}
void StringWriter::write(String bb)
{
 _str_cat(bb.val());
}
void StringWriter::write(char *bb, int startIndex, int endIndex)
{
 char *aa = strdup(bb); // teste le null dans verifyIndex
 verifyIndex(startIndex, aa);
 verifyIndex(endIndex, aa);
 aa[endIndex] = 0;
 _str_cat(& aa[startIndex]);
}
void StringWriter::write(String str, int startIndex, int endIndex)
{
 write(str.val(), startIndex, endIndex);
}


Page suivante - Page précédente - Table des matières