Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

PsString.cxx

Go to the documentation of this file.
00001 /*
00002  * This file is part of openMask © INRIA, CNRS, Universite de Rennes 1 1993-2002, thereinafter the Software
00003  * 
00004  * The Software has been developped within the Siames Project. 
00005  * INRIA, the University of Rennes 1 and CNRS jointly hold intellectual property rights
00006  * 
00007  * The Software has been registered with the Agence pour la Protection des
00008  * Programmes (APP) under registration number IDDN.FR.001.510008.00.S.P.2001.000.41200
00009  *  
00010  * This file may be distributed under the terms of the Q Public License
00011  * version 1.0 as defined by Trolltech AS of Norway and appearing in the file
00012  * LICENSE.QPL included in the packaging of this file.
00013  *
00014  * Licensees holding valid specific licenses issued by INRIA, CNRS or Université de Rennes 1 
00015  * for the software may use this file in accordance with that specific license
00016  *
00017  */
00018 #include <PsString.h>
00019 #include <string>
00020 
00021 #include <ctype.h> //pour la fonction qui vire les blancs
00022 #include <PsPolator.h>
00023 #include "PsController.h"
00024 #include "PsOutgoingSynchronisationMessage.h"
00025 #include "PsIncomingSynchronisationMessage.h"
00026 
00027 #ifdef _MOME
00028 #include <PsnSharedMemoryManager.h>
00029 #include <PsMomeController.h>
00030 #include <PsnMemoryElementDescriptor.h>
00031 #endif
00032 #ifdef _USESSTREAM
00033 #include <sstream>
00034 #else
00035 #include <strstream>
00036 #endif
00037 // Constructors and destructors  **********************************
00038 
00039 PsString::PsString ( const string & aString)
00040 {
00041    _CString = NULL; // Nettoyage de la mémoire
00042    _nbCarac = strlen( aString.c_str() ) ;
00043    assert (_nbCarac == aString.length ()) ;
00044    alloue( _nbCarac );
00045    // On vérifie que le nombre de caractères est différent de 0
00046    if (_nbCarac != 0)
00047       {
00048        strcpy(_CString, aString.c_str());
00049        assert (_CString [_nbCarac] == '\0') ;
00050     }
00051    else
00052       {
00053          _CString[0] = '\0';
00054       }
00055 }
00056 
00057 
00058 PsString::PsString (const char *Chn)
00059 {     
00060    //cerr<<"PsString : constructeur par recopie d'un char *"<<endl;
00061    if (Chn == NULL)
00062     {
00063       cerr << "PsString::PsString(const char*) : " << endl;
00064       PsController::error("La chaine fournie est un pointeur NULL");
00065     }
00066   _CString = NULL; // Nettoyage de la mémoire
00067   _nbCarac = strlen(Chn);
00068   alloue(_nbCarac);
00069   // On vérifie que le nombre de caractères est différent de 0
00070   if (_nbCarac != 0)
00071     {
00072       // On ne copie que si nbCarac != 0
00073       strcpy(_CString, Chn);
00074     }
00075   else
00076     {
00077       _CString[0] = '\0';
00078     }
00079   //cerr<<_CString<<endl;
00080   //cerr<<"PsString::recopie terminée pour "<<_CString<<endl;
00081 }
00082 
00083 
00084 PsString::PsString (const PsString &Chn)
00085 {
00086    //cerr<<"PsString::PsString (const PsString &Chn)"<<endl;
00087   _CString = NULL; // Nettoyage de la mémoire
00088   _nbCarac = Chn.getStringLength();
00089   alloue(_nbCarac);
00090   if (_nbCarac != 0)
00091     {
00092       // On ne copie que si nbCarac != 0
00093        strcpy (_CString, Chn._CString);
00094     }
00095   else
00096     {
00097       _CString[0] = '\0';
00098     }
00099   //cerr<<Chn<<endl<<*this<<endl;
00100 }
00101 
00102 PsString::PsString (const char Carac)
00103 {
00104    cerr<<"PsString : construction from a char: "<<Carac<<endl;
00105   _CString = NULL; // Nettoyage de la mémoire
00106   _nbCarac = 1;
00107   alloue(_nbCarac);
00108   // On copie la caractère et la fin de chaîne
00109   _CString[0]= Carac;
00110   _CString[1]= '\0';
00111 }
00112 
00113 PsString::~PsString ()
00114 {
00115    //cerr<<"PsString::~PsString"<<endl;
00116   // Si la chaîne a été allouée, on la désalloue
00117   if (_CString != NULL)
00118     {
00119        delete [] _CString;
00120     }
00121   //cerr<<"PsString::~PsString fini"<<endl;
00122   //gereVarClasse (Delete);
00123 }
00124 
00125 PsPolatorNT * PsString::createPolator (void) {
00126   return  (PsPolatorNT *) new PsPolator<PsString>();
00127 }
00128 // Recherche dans la chaîne de caractères **********************
00129 
00130 int PsString::getSubString(const int debut, const int nbCarac,
00131                              PsString& sousChaine) const
00132 {
00133    //assert ( _nbCarac == _tailleMem - 1) ;
00134 
00135    // Nombre de caractères à copier
00136    int nbMin;
00137    
00138    // On vérifie que l'indice de début est bien dans la chaîne
00139    if ( (debut >= _nbCarac) || (debut < 0) )
00140       {
00141       cerr << "WARNING : PsString::getSubString() :" << endl;
00142       cerr << "Indice de début de sous-chaîne (" << debut
00143            << ") sort de la chaîne de taille ("
00144            << _nbCarac << ")" << endl;
00145       // On n'a pas copié de caractères
00146       return 0;
00147     }
00148 
00149   // On regarde s'il veut tout le reste de la chaîne
00150   if (nbCarac <= 0)
00151     {
00152       // On va copier tous les autres caractères
00153       nbMin = _nbCarac-debut;
00154     }
00155   // On détermine le nombre de caractère à fournir en regardant
00156   // la limite de fin de chaîne
00157   else if ( (_nbCarac-debut) < nbCarac)
00158     {
00159       nbMin = _nbCarac-debut;
00160     }
00161   else
00162     {
00163       nbMin = nbCarac;
00164     }
00165   
00166   // On vérifie qu'il y a assez de place dans sousChaine
00167   if (sousChaine._tailleMem <= nbMin)
00168     {
00169       // On alloue la place suffisante nbMin+1
00170       sousChaine.alloue(nbMin);
00171     }
00172 
00173   // On fait la copie (pas de vérification à cet endroit-là)
00174   strncpy(sousChaine._CString, _CString+debut, nbMin);
00175 
00176   // On ajoute la fin de chaîne
00177   sousChaine._CString[nbMin]= '\0';
00178   sousChaine._nbCarac= nbMin;
00179 
00180   // On renvoie le nombre de caractères copîés
00181   return nbMin;
00182 }
00183 
00184 // PsType * PsString::cloner (void) const {
00185 //    return (new PsString (*this)) ;
00186 // }
00187 
00188 int 
00189 PsString::getSubStringIndex (const PsString &cherche) const
00190 {
00191   if (cherche._nbCarac == 0)
00192     {
00193       cerr << "WARNING : PsString::getSubStringIndex() :"
00194            << "Taille de la sous-chaîne recherchée nulle" << endl;
00195       return -1;
00196     }
00197 
00198   char *ptrDebut = strstr(_CString, cherche._CString);
00199   // A-t-on trouvé la chaîne ?
00200   if (ptrDebut == NULL)
00201     {
00202       // Pas trouvé
00203       return -1;
00204     }
00205   else
00206     {
00207       // On a trouvé
00208       return (ptrDebut - _CString);
00209     }
00210 }
00211 
00212 int
00213 PsString::findCaracter (char Carac) const
00214 {
00215   char *ptrDebut = strchr(_CString, Carac);
00216   // A-t-on trouvé la chaîne ?
00217   if (ptrDebut == NULL)
00218     {
00219       // Pas trouvé
00220       return -1;
00221     }
00222   else
00223     {
00224       // On a trouvé
00225       return (ptrDebut - _CString);
00226     }
00227 }
00228 
00229 // Opérateurs unaires ******************************************
00230 char PsString::operator[] (int i) const
00231 {
00232   if ( (i<0) || (i>=_nbCarac) )
00233     {
00234       cerr << "PsString::operator[]: index (" << i << ") hors limite" << endl;
00235       PsController::error("");
00236       // Pour la compilation
00237       return 0;
00238     }
00239   else
00240     {
00241       return _CString[i];
00242     }
00243 }
00244 
00245 PsString& PsString::operator = (const PsString &Source)
00246 {
00247    //cerr<<"PsString::operator = "<<*this<<";"<<Source<<endl;
00248   // On vérifie que ce ne sont pas les mêmes chaînes,
00249   // sinon c'est fini
00250   if (_CString != Source._CString)
00251     {
00252       // Si on n'a pas la capacité de recevoir 
00253       if (getCapacity() < Source._nbCarac)
00254         {
00255           alloue(Source._nbCarac);
00256         }
00257       // On fait la copie
00258       _nbCarac = Source._nbCarac;
00259       strcpy(_CString, Source._CString);
00260     }
00261   // On a terminé, on se renvoie
00262   return *this;
00263 }
00264 
00265 
00266 
00267 
00268 // PsType & PsString::operator = (const PsType &Source)
00269 // {
00270 //   //cout << "PsString::operator = (const PsType &Source)" << endl;
00271 
00272 //   // Le cast des PsType doit exister vers les PsString, d'où :
00273 //   //operator = (*((PsString *)&Source));
00274 
00275 //   // On utilise l'insertion du type vers le flux
00276 //   strstream fluxTmp;
00277 //   fluxTmp << Source;
00278 
00279 //   // On extrait la PsString du flux
00280 //   *this = fluxTmp.str();
00281 
00282 //   // On l'affecte à notre chaîne
00283 //   //*this = temp;
00284 
00285 //   return *this;
00286 // }
00287 
00288 PsString & PsString::operator + (const PsType &Source)
00289 {
00290    //cerr << "PsString::operator + (const PsType &Source)" << endl;
00291    
00292    //first insert the type in a string
00293 #ifdef _USESSTREAM
00294    ostringstream fluxTmp;
00295    fluxTmp << Source ;
00296 #else
00297    strstream fluxTmp;
00298    fluxTmp << Source <<'\0' ;
00299 #endif
00300    
00301    //then constructuct a string corresponding to this
00302    string temp( getCString() ) ;
00303    
00304    // append the two stings and copy the result into this
00305    *this = temp + fluxTmp.str() ;
00306    
00307    //cerr << "PsString::operator + (const PsType &Source) done " << endl;
00308    return *this;
00309 }
00310 
00311 PsString & PsString::operator + (const string & source)
00312 {   
00313    //then constructuct a string corresponding to this
00314    string temp( getCString() ) ;
00315    
00316    // append the two stings and copy the result into this
00317    *this = temp + source ;
00318    
00319    //cerr << "PsString::operator + (const PsType &Source) done " << endl;
00320    return *this;
00321 }
00322 
00323 
00324 // Gestion des flux ********************************************
00325 void PsString::pack(PsOutgoingSynchronisationMessage & out) const 
00326 {
00327    out<<_nbCarac<<_CString;
00328 }
00329 
00330 void PsString::unpack(PsIncomingSynchronisationMessage & in)
00331 {
00332    in>> _nbCarac ;
00333    if (_tailleMem <= _nbCarac)
00334       {
00335          // Allocate the necessary memory
00336          alloue(_nbCarac);
00337       }
00338    in>>_CString ;
00339 }
00340 
00341 // Gestion des flux ********************************************
00342 void PsString::pack(ostream & out) const 
00343 {
00344    out<<_nbCarac<<" "<<_CString<<" ";
00345 }
00346 
00347 void PsString::unpack(istream & in)
00348 {
00349    in>> _nbCarac ;
00350    if (_tailleMem <= _nbCarac)
00351       {
00352          // Allocate the necessary memory
00353          alloue(_nbCarac);
00354       }
00355    in.get (_CString, _nbCarac +1 ) ;
00356 }
00357 
00358 void PsString::extract (istream & in)
00359 {
00360    //It is impossible to correctly extract an inserted stream because the inserted stream could have whitespaces
00361    string result ;
00362    in >> result ;
00363    alloue (result.size() + 1 ) ;
00364    strcpy (_CString, const_cast<char *>(result.c_str()) );
00365 }
00366 
00367 void PsString::insertInStream (ostream & out) const
00368 {
00369   // insert the string
00370   out << _CString;
00371 }
00372 
00373 /************************************ operator << */
00374 PsString & PsString::operator <<(separator f) 
00375 {
00376    PsString espace(" ");
00377    *this=*this+espace;
00378    return *this;
00379 }
00380 
00381 PsString & sep(PsString & oChaine) 
00382 {
00383    return (oChaine);
00384 }
00385 
00386 PsString & PsString::operator << (const char * f) {
00387    PsString tmp(f);
00388    *this<<tmp;
00389    return (*this);
00390 }
00391 
00392 
00393 PsString & PsString::operator << (const PsFlowable & f) {
00394 #ifdef _USESSTREAM
00395    ostringstream myos ;
00396    myos << f ;
00397    *this = (*this) +  myos.str() ;
00398 #else
00399    char tampon[LG_MAX_BUFFER];
00400    ostrstream myos(tampon,LG_MAX_BUFFER);
00401    myos<<f;
00402    int i = myos.pcount() ;
00403    PsString * chaineTemp;
00404    if (myos.fail()||(i>=LG_MAX_BUFFER)) {
00405       int tailleTampon=LG_MAX_BUFFER;
00406       char * biggerTampon;
00407       ostrstream * biggeros;
00408       do {
00409          tailleTampon=tailleTampon*2;
00410          biggerTampon=new char[tailleTampon];
00411          biggeros=new ostrstream(biggerTampon,tailleTampon);
00412          *biggeros<<f;
00413          i = biggeros->pcount() ;
00414       } 
00415       while(biggeros->fail()||(i>=tailleTampon));
00416       biggerTampon[i] = '\0' ;
00417       chaineTemp=new PsString(biggerTampon);
00418       delete [] biggerTampon;
00419       delete biggeros;
00420    }
00421    else {
00422      tampon[i]='\0' ;
00423      chaineTemp=new PsString(tampon);
00424    }
00425    *this=*this+*chaineTemp; 
00426    delete chaineTemp;
00427 #endif
00428    return(*this);
00429 }
00430 
00431 PsString & PsString::operator >> (PsFlowable & f) {
00432    char * nouvelleChaine;
00433    int indiceDebutSuite;
00434 #ifdef _USESSTREAM
00435    istringstream myis(_CString);
00436 #else
00437    istrstream myis(_CString,_tailleMem);
00438 #endif
00439    myis>>f;
00440    if(myis.fail()) {
00441 #ifdef _DEBUGPVMMESS
00442       cerr<<"Impossible extraction"
00443           <<endl
00444           <<"The 2 main causes of this error are : you are trying to extract stuff from a string that wasn't inserted, but iether hand constructed in the string or not inserted at all"
00445           <<endl
00446       throw PsUserException ("PsString::operator>>: extraction impossible");
00447 #endif    
00448    }
00449    indiceDebutSuite=myis.tellg();//si il y a une suite, elle va commencer à indiceDebutSuite
00450    //on supprime les séparateurs
00451    while(isspace(_CString[indiceDebutSuite])&&(_CString[indiceDebutSuite]!='\0')) {
00452       indiceDebutSuite++;
00453    };
00454    nouvelleChaine=new char[_tailleMem-indiceDebutSuite];
00455    strcpy(nouvelleChaine,_CString+indiceDebutSuite);
00456    if (_CString != NULL) delete [] _CString;
00457    _CString=nouvelleChaine;
00458    _nbCarac=strlen(_CString);
00459    _tailleMem=_tailleMem-indiceDebutSuite;
00460    return (*this);
00461 }  
00462 
00463 
00464 // Accesseurs en lecture ****************************************
00465 
00466 int PsString::getStringLength() const
00467 {
00468    //assert ( _nbCarac == _tailleMem - 1) ;
00469    return _nbCarac;
00470 }
00471 
00472 int PsString::getCapacity() const
00473 {
00474   //assert ( _nbCarac == _tailleMem - 1) ;
00475    return _tailleMem-1;
00476 }
00477 
00478 const char* PsString::getCString() const
00479 {
00480   //assert ( _nbCarac == _tailleMem - 1) ;
00481    return _CString;
00482 }
00483 
00484 // Opérateurs amis *********************************************
00485 
00486 bool operator > (const PsString &Source1, const PsString &Source2)
00487 {
00488   return (strcmp(Source1._CString, Source2._CString)> 0);
00489 }
00490 
00491 bool operator < (const PsString &Source1, const PsString &Source2)
00492 {
00493    //      cout<<"operator < (const PsString , const PsString)"<<endl;
00494    //      cout<<"_"<<Source1._CString<<"_"<<Source2._CString<<"_"<<endl;
00495   return (strcmp(Source1._CString, Source2._CString)< 0);
00496 }
00497 
00498 bool operator >= (const PsString &Source1, const PsString &Source2)
00499 {
00500   return (!(Source1 < Source2));
00501 }
00502 
00503 bool operator <= (const PsString &Source1, const PsString &Source2)
00504 {
00505   return (!(Source1 > Source2));
00506 }
00507 
00508 bool operator != (const PsString &Source1, const PsString &Source2)
00509 {
00510    //   cout<<"operator != (const PsString , const PsString)"<<endl;
00511    //   cout<<"_"<<Source1._CString<<"_"<<Source2._CString<<endl;
00512   return (strcmp(Source1._CString, Source2._CString));
00513 }
00514 
00515 
00516 
00517 bool operator == (const PsString &Source1, const PsString &Source2)
00518 {
00519   return (!(Source1 != Source2));
00520 }
00521 
00522 
00523 
00524 PsString PsString::operator ++ (int i) {
00525    PsString retour (*this);
00526    ++(*this);
00527    return retour;
00528 }
00529 
00530 PsString & PsString::operator ++ () {
00531    char * nouvelleChaine;
00532    char zero('0');
00533    char neuf('9');
00534    if ((_nbCarac==0)||
00535        ((zero>_CString[_nbCarac-1])||(_CString[_nbCarac-1]>=neuf))) {
00536       //on a besoin d'écrire une case plus loin
00537       if(_tailleMem<=_nbCarac+1) {
00538          //on a potentiellement besoin de réallouer de la place 
00539          _tailleMem=_nbCarac+2;
00540          nouvelleChaine=new char[_tailleMem];
00541          if (!nouvelleChaine) {
00542             PsController::error("ERROR : Impossible d'allouer de la mémoire pour ++");
00543          }
00544          strcpy(nouvelleChaine,_CString);
00545          if (_CString!=NULL) {
00546             delete [] _CString;
00547          }
00548          _CString=nouvelleChaine;
00549       }
00550       if(_CString[_nbCarac-1]!=neuf) {
00551          _CString[_nbCarac]=zero;
00552          _CString[_nbCarac+1]='\0';
00553          _nbCarac++;
00554       }
00555       else {//le dernier caractère est 9
00556          int indicePremierPasNeuf=_nbCarac-1; 
00557          do {
00558             _CString[indicePremierPasNeuf]=zero;
00559             indicePremierPasNeuf--;
00560          }
00561          while (_CString[indicePremierPasNeuf]==neuf);
00562          if ( (_CString[indicePremierPasNeuf]>=zero)&&(_CString[indicePremierPasNeuf]<neuf))
00563             {
00564                _CString[indicePremierPasNeuf]++;
00565             }
00566          else {
00567             _CString[indicePremierPasNeuf+1]='1';
00568             _CString[_nbCarac]=zero;
00569             _CString[_nbCarac+1]='\0';
00570             _nbCarac++;
00571          } 
00572       }
00573    }
00574    else {
00575       _CString[_nbCarac-1]=_CString[_nbCarac-1]+1;
00576    }
00577    return *this;
00578 }
00579 
00580 PsString & PsString::operator -- () {
00581 
00582   char nouvelleChaine[20];
00583   char zero('0');
00584   char neuf('9');
00585   int nbNum ;
00586   int nombreTemps =0 ;
00587   int i,nb ;
00588   int puissance = 1;
00589 
00590   // cas chaine vide
00591   if (_nbCarac==0) 
00592     return *this ;
00593 
00594   // cas ou il n'y as pas de caractere numerique en fin de chaine  
00595   if ((zero>_CString[_nbCarac-1])||(_CString[_nbCarac-1]>neuf))
00596     return *this ;
00597     
00598   // bon cas
00599   if ((zero<_CString[_nbCarac-1])&&(_CString[_nbCarac-1]<=neuf))
00600     {
00601       // cas si un chiffre entre 1 et 9
00602       // +1, meme nombre de caractere
00603       _CString[_nbCarac-1]--;
00604       return *this ;
00605     }
00606   // on est dans le cas zero
00607   // conbien de caractere numerique ?
00608   // on sait que le dernier en est un
00609   nbNum = 1 ;
00610   while ( (zero<=_CString[_nbCarac-1-nbNum])&&(_CString[_nbCarac-1-nbNum]<=neuf) )
00611     nbNum++;
00612   
00613   if ((nbNum==1)&&(_CString[_nbCarac-1]==zero))
00614     {
00615       _nbCarac--;
00616       _CString[_nbCarac]='\0';
00617       return *this ; 
00618     }
00619   
00620   for(i=0;i<nbNum;i++)
00621     {
00622       nombreTemps =  (_CString[_nbCarac-1-i]-zero)*puissance + nombreTemps ;
00623       puissance = puissance *10 ;
00624     }
00625     
00626   nombreTemps--;
00627   nb=0;
00628   while (nombreTemps!=0)
00629     {
00630       // on rentre les chiffres a l'envers dans une chaine temporaire
00631       int val = nombreTemps % 10 ;
00632       nombreTemps = nombreTemps / 10 ;
00633       nouvelleChaine[nb] = zero + val ;
00634       nb++;
00635     }
00636     
00637   for(int j=1;j<=nb;j++)
00638     _CString[_nbCarac-nbNum+j-1] = nouvelleChaine[nb-j] ;
00639   
00640   //cout << "  _nbCarac : " <<  _nbCarac << endl ;
00641   //cout << "nb : " << nb << endl ; 
00642   //cout << "nbNum : " << nbNum << endl ;
00643   _nbCarac = _nbCarac - nbNum + nb ;
00644   _CString[_nbCarac] = '\0' ;
00645   
00646   return *this ;
00647 }
00648 
00649 // Méthode privée ************************************************
00650 
00651 // Fonction privée d'allocation d'espace mémoire pour la chaîne stockée.
00652 // Renvoie un pointeur char* ou interrompt le programme si l'allocation
00653 // échoue.
00654 void PsString::alloue(const int length)
00655 {
00656    // Make sure length is correct
00657   //   assert (length >= 0 );
00658 
00659    // Si la chaîne était déjà allouée, on libère
00660    if (_CString!=NULL) 
00661       {
00662          delete [] _CString;    
00663          _CString = NULL ;
00664       }
00665    
00666    // On prévoit le caractère de fin de chaîne
00667    _tailleMem = length + 1;
00668    // On alloue la chaîne
00669 #ifdef _MOME
00670    //si la chaine se trouve dans la mémoire partagée, il faut allouer le tampon dans la mémoire partagée
00671   PsnSharedMemoryManager * myMemory = PsMomeController::whichSharedMemoryManager(this);
00672   HeapStackTop newAllocationContext(myMemory) ;
00673 #endif
00674   _CString = new char[_tailleMem];
00675   // Si l'allocation ne s'est pas bien passée
00676   if (!_CString)
00677     {
00678       PsController::error("ERROR : PsString::alloue() : Echec de l'allocation");
00679     }
00680   //cerr<<"Allocation d'une chaine dans la méméoire  à "<<(void *)_CString<<endl;
00681 }
00682 

logo OpenMask

Documentation generated on Mon Nov 25 15:25:02 2002

Generated with doxygen 1.2.12 by Dimitri van Heesch ,   1997-2001