OString.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 #include <eyedbconfig.h>
00025 
00026 #include <ctype.h>
00027 #ifdef HAVE_SYS_TYPES_H
00028 #include <sys/types.h>
00029 #endif
00030 #ifdef HAVE_REGEX_H
00031 #include <regex.h>
00032 #elif defined(HAVE_LIBGEN_H)
00033 #include <libgen.h>
00034 #else
00035 #error No regular expression implementation available on this platform
00036 #endif
00037 
00038 #include <eyedb/syscls.h>
00039 #include <eyedblib/strutils.h>
00040 
00041 using namespace std;
00042 
00043 //
00044 // Constants
00045 //
00046 
00047 namespace eyedb {
00048 
00049   //
00050   // OString user methods
00051   //
00052 
00053   OString *
00054   OString::ostring(Database * db)
00055   {
00056     return new OString(db);
00057   }
00058 
00059   OString *
00060   OString::ostring(Database * db, const char * s)
00061   {
00062     OString * os = new OString(db);
00063 
00064     os->assign(s);
00065 
00066     return os;
00067   }
00068 
00069   OString *
00070   OString::ostring(Database * db, const char * s, int len)
00071   {
00072     OString * os = new OString(db);
00073 
00074     os->assign(s, len);
00075 
00076     return os;
00077   }
00078 
00079   OString *
00080   OString::ostring(Database * db, const char * s, int offset, int len)
00081   {
00082 
00083     OString * os = new OString(db);
00084 
00085     os->assign(s, offset, len);
00086 
00087     return os;
00088 
00089   }
00090 
00091   OString *
00092   OString::ostring(Database * db, const OString & s)
00093   {
00094     OString * os = new OString(db);
00095 
00096     os->setS(s.getS());
00097 
00098     return os;
00099   }
00100 
00101   OString *
00102   OString::ostring(Database * db, char s)
00103   {
00104     std::string is = str_convert(s);
00105 
00106     OString * os = new OString(db);
00107     os->setS(is.c_str());
00108   
00109     return os;
00110   }
00111 
00112   OString *
00113   OString::ostring(Database * db, int s)
00114   {
00115     std::string is = str_convert(s);
00116 
00117     OString * os = new OString(db);
00118     os->setS(is.c_str());
00119   
00120     return os;
00121   }
00122 
00123   OString *
00124   OString::ostring(Database * db, double s)
00125   {
00126     std::string is = str_convert(s);
00127 
00128     OString * os = new OString(db);
00129     os->setS(is.c_str());
00130   
00131     return os;
00132   }
00133 
00134   char *
00135   OString::substr(const char * s, int offset, int len)
00136   {
00137     char * s_copy = 0;
00138 
00139     int s_len = strlen(s);
00140     if( offset >= s_len 
00141         || offset < 0 
00142         || len < 0 )
00143       {
00144         return 0;
00145       }
00146 
00147     if( offset + len > s_len )
00148       {
00149         len = s_len - offset;
00150       }
00151 
00152     s_copy = new char[len + 1];
00153 
00154     strncpy( s_copy, s + offset, len);
00155     s_copy[len] = '\0';
00156    
00157     return s_copy;
00158   }
00159 
00160   char *
00161   OString::toLower(const char * s)
00162   {
00163     char * s2 = new char[strlen(s) + 1];
00164     char * p = s2;
00165 
00166     while (*s++)
00167       *p++ = (char)tolower( *s);
00168 
00169     *p = '\0';
00170 
00171     return s2;
00172   }
00173 
00174   char *
00175   OString::toUpper(const char * s)
00176   {
00177     char * s2 = new char[strlen(s) + 1];
00178     char * p = s2;
00179 
00180     while (*s++)
00181       *p++ = (char)toupper( *s);
00182 
00183     *p = '\0';
00184 
00185     return s2;
00186   }
00187 
00188   char *
00189   OString::rtrim(const char * s)
00190   {
00191     const char * s_rtrimmed = s + strlen(s) - 1;
00192 
00193     while (s_rtrimmed >= s 
00194            && ((*s_rtrimmed=='\n') || (*s_rtrimmed=='\r') || (*s_rtrimmed=='\t') || (*s_rtrimmed=='\v')))
00195       s_rtrimmed--;
00196 
00197     int return_value_size = s_rtrimmed - s + 1;
00198     char * return_value = new char[return_value_size + 1];
00199     strncpy(return_value, s, return_value_size);
00200     return_value[return_value_size] = '\0';
00201 
00202     return return_value;
00203   }
00204 
00205   char *
00206   OString::ltrim(const char * s)
00207   {
00208     const char * s_ltrimmed = s + strspn(s, "\n\r\t\v ");
00209 
00210     char * return_value = new char[strlen(s_ltrimmed + 1)];
00211     strcpy(return_value, s_ltrimmed);
00212 
00213     return return_value;
00214   }
00215 
00216   Status
00217   OString::setChar(char c, int offset)
00218   {
00219     return setS(offset, c); 
00220   }
00221 
00222   char
00223   OString::getChar(int offset) const
00224   {
00225     return getS(offset);
00226   }
00227 
00228   OString &
00229   OString::append(const char * s)
00230   {
00231     std::string is(getS());
00232 
00233     is += s;
00234 
00235     setS(is.c_str());
00236 
00237     return *this;
00238   }
00239 
00240   OString &
00241   OString::append(const char * s, int len)
00242   { 
00243     return append(s, 0 , len);
00244   }
00245 
00246   OString &
00247   OString::append(const char * s, int offset, int len)
00248   {
00249     char * sub = OString::substr(s, offset, len);
00250 
00251     if( sub != 0 )
00252       {
00253         append(sub);
00254         delete sub;
00255       }
00256 
00257     return *this;
00258   }
00259 
00260   OString &
00261   OString::prepend(const char * s)
00262   {
00263     std::string is(s);
00264 
00265     is += getS();
00266 
00267     setS(is.c_str());
00268 
00269     return *this;
00270   }
00271 
00272   OString &
00273   OString::prepend(const char * s, int len)
00274   {
00275     return prepend(s, 0, len);
00276   }
00277 
00278   OString &
00279   OString::prepend(const char * s, int offset, int len)
00280   {
00281     char * sub = OString::substr(s, offset, len);
00282 
00283     if( sub != 0 )
00284       {
00285         prepend(sub);
00286         delete sub;
00287       }
00288 
00289     return *this;
00290   }
00291 
00292   OString &
00293   OString::insert(int offset, const char * s)
00294   {
00295     return insert(offset, s, 0, strlen(s));
00296   }
00297 
00298   OString &
00299   OString::insert(int offset, const char * s, int len)
00300   {
00301     return insert(offset, s, 0, len);
00302   }
00303 
00304   OString &
00305   OString::insert(int offset, const char * s, int offset2, int len)
00306   {
00307     const char * this_s = getS().c_str();
00308 
00309     // check arguments
00310     if( offset < 0 
00311         || offset2 < 0
00312         || len <= 0 )
00313       {
00314         return *this;
00315       }
00316 
00317     // insert
00318     char * inserted_s = new char[strlen(this_s) + strlen(s) + 1];
00319     inserted_s[0] = '\0';
00320   
00321     strncat(inserted_s, this_s, offset);
00322     strncat(inserted_s, s + offset2, len);
00323     strcat(inserted_s, this_s + offset);
00324 
00325     setS(inserted_s);
00326   
00327     delete inserted_s;
00328 
00329     return *this;
00330   }
00331 
00332   OString *
00333   OString::concat(Database * db, const char * s1, const char * s2)
00334   {
00335     OString * os = OString::ostring(db, s1);
00336 
00337     os->append(s2);
00338 
00339     return os;
00340   }
00341 
00342   int
00343   OString::first(const char * s) const
00344   {
00345     return find(s, 0);
00346   }
00347 
00348   int
00349   OString::last(const char * s) const
00350   {
00351     /* not implemented */
00352     cerr << "Not implemented" << endl;
00353     return 0;
00354   }
00355 
00356   int
00357   OString::find(const char * s, int offset) const
00358   {
00359     const char * this_s = getS().c_str();
00360   
00361     if (offset > strlen(this_s) || offset < 0 || !*s)
00362       {
00363         return -1;
00364       }
00365 
00366     int find_offset = -1;
00367 
00368     char * match = (char *)strstr(this_s + offset, s);
00369     if( match != 0)
00370       {
00371         find_offset = match - this_s;
00372       }
00373 
00374     return find_offset;
00375   }
00376 
00378   OString *
00379   OString::substr(int offset, int len) const
00380   {
00381     OString * os = OString::ostring(0, getS().c_str(), offset, len);
00382 
00383     return os;
00384   }
00385 
00387   OString *
00388   OString::substr(const char * regexp, int offset) const
00389   {
00390     // check argument
00391     const char * regexp_subject = getS().c_str();
00392 
00393     if( offset > strlen(regexp_subject) 
00394         || offset < 0)
00395       {
00396         return OString::ostring(0);
00397       }
00398   
00399       
00400     // Apply the regular expresion pattern
00401 #ifdef HAVE_REGCOMP
00402     regex_t * compiled_regexp = (regex_t *)malloc(sizeof(regex_t));
00403 
00404     int reg_status = regcomp(compiled_regexp, regexp, REG_EXTENDED);
00405     if ( reg_status != 0)
00406       {
00407         free(compiled_regexp);
00408         return OString::ostring(0);      
00409       }
00410 
00411     regmatch_t match[1];
00412     reg_status = regexec((regex_t *)compiled_regexp, regexp_subject + offset, 1, match, 0);
00413     if ( reg_status != 0)
00414       {
00415         free(compiled_regexp);
00416         return OString::ostring(0);      
00417       }
00418   
00419     const char * start_match = regexp_subject + offset + match[0].rm_so;
00420     const char * end_match = regexp_subject + offset + match[0].rm_eo;
00421 #elif defined(HAVE_REGCMP)
00422     char * compiled_regexp = regcmp(regexp, (char *)0);
00423 
00424     if(compiled_regexp == 0) 
00425       {
00426         return OString::ostring(0);
00427       }
00428 
00429     const char * end_match = regex(compiled_regexp, regexp_subject + offset);
00430     const char * start_match = __loc1;
00431 #endif
00432 
00433     free(compiled_regexp);
00434 
00435     // return the matched string
00436     OString * os = 0;
00437     if( end_match )
00438       {
00439         os = OString::ostring(0, start_match, 0, end_match - start_match); 
00440       }
00441     else
00442       {
00443         os = OString::ostring(0);
00444       }
00445 
00446     return os;
00447 
00448   }
00449 
00450   OString &
00451   OString::erase(int offset, int len)
00452   {
00453     // check arguments
00454     const char * this_s = getS().c_str();
00455 
00456     int this_len = strlen(this_s);
00457     if( offset > this_len
00458         || offset < 0
00459         || len <= 0 )
00460       {
00461         return *this;
00462       }
00463 
00464     if( offset + len > this_len )
00465       {
00466         len = this_len - offset;
00467       }
00468 
00469     // erase = 1/substr
00470 
00471     char * erased_string = new char[this_len + 1];
00472   
00473     strncpy(erased_string, this_s, offset);
00474     strcpy(erased_string + offset, this_s + offset + len);
00475   
00476     setS(erased_string);
00477 
00478     delete erased_string;
00479 
00480     return *this;
00481   }
00482 
00483   OString &
00484   OString::replace(int offset, int len, const char * s)
00485   {
00486     return replace(offset, len, s, 0, strlen(s));
00487   }
00488 
00489   OString &
00490   OString::replace(int offset, int len, const char * s, int len2)
00491   {
00492     return replace(offset, len, s, 0, len2);
00493   }
00494 
00495   OString &
00496   OString::replace(int offset, int len, const char * s, int offset2, int len2)
00497   {
00498     // check arguments
00499     const char * this_s = getS().c_str();
00500 
00501     int this_len = strlen(this_s);
00502     int s_len = strlen(s);
00503 
00504     if( offset > this_len
00505         || offset < 0
00506         || len <= 0 
00507         || offset2 > s_len
00508         || offset2 < 0
00509         || len2 <= 0 )
00510       {
00511         return *this;
00512       }
00513 
00514     if( offset + len > this_len )
00515       {
00516         len = this_len - offset;
00517       }
00518 
00519 
00520     // replace
00521 
00522     char * replaced_string = new char[this_len + s_len + 1];
00523     replaced_string[0] = '\0';
00524   
00525     strncat(replaced_string, this_s, offset);
00526     strncat(replaced_string, s + offset2, len2);
00527     strcat(replaced_string, this_s + offset + len);
00528   
00529     setS(replaced_string);
00530 
00531     delete [] replaced_string;
00532 
00533     return *this;
00534   }
00535 
00536 
00537   OString &
00538   OString::replace(const char * s1, const char * s2)
00539   {
00540     const char * this_s = getS().c_str();
00541     int s1_len = strlen(s1);
00542   
00543 
00544     // EV 27/08/02 : added ``+ 1''
00545     char * replaced_string = new char[strlen(this_s) * ( strlen(s2) + 1 ) + 1];
00546     replaced_string[0] = '\0';
00547 
00548     int current_offset = 0;
00549     int previous_offset = 0;
00550     while( (current_offset = find(s1, previous_offset)) >= 0 )
00551       {
00552         strncat(replaced_string, this_s + previous_offset, current_offset - previous_offset);
00553         strcat(replaced_string, s2);
00554 
00555         previous_offset = current_offset + s1_len;
00556       }
00557 
00558   
00559     if( previous_offset < strlen(this_s) )
00560       {
00561         strcat(replaced_string, this_s + previous_offset);
00562       }
00563 
00564     setS(replaced_string);
00565 
00566     // EV 27/08/02 : added ``[]''
00567     delete [] replaced_string;
00568 
00569     return *this;
00570   }
00571 
00572   OString &
00573   OString::assign(const char * s)
00574   {
00575     setS(s);
00576 
00577     return *this;
00578   }
00579 
00580   OString &
00581   OString::assign(const char * s, int len)
00582   {
00583     char * sub = OString::substr(s, 0, len);
00584   
00585     if( sub != 0 )
00586       {
00587         setS(sub);
00588         delete sub;
00589       }
00590 
00591     return *this;
00592   }
00593 
00594   OString &
00595   OString::assign(const char * s, int offset, int len)
00596   {
00597     char * sub = OString::substr(s, offset, len);
00598   
00599     if( sub != 0 )
00600       {
00601         setS(sub);
00602         delete sub;
00603       }
00604 
00605     return *this;
00606   }
00607 
00608   Status
00609   OString::reset()
00610   {
00611     return setS("");
00612   }
00613 
00614   OString &
00615   OString::toLower()
00616   {
00617     char * s2 = toLower(getS().c_str());
00618     setS(s2);
00619     delete s2;
00620 
00621     return *this;
00622   }
00623 
00624   OString &
00625   OString::toUpper()
00626   {
00627     char * s2 = toUpper(getS().c_str());
00628     setS(s2);
00629     delete s2;
00630 
00631     return *this;
00632   }
00633 
00634   OString &
00635   OString::rtrim()
00636   {  
00637     char * s2 = rtrim(getS().c_str());
00638     setS(s2);
00639     delete s2;
00640  
00641     return *this;
00642   }
00643 
00644   OString & 
00645   OString::ltrim()
00646   {
00647     char * s2 = ltrim(getS().c_str());
00648     setS(s2);
00649     delete s2;
00650 
00651     return *this;
00652   }
00653 
00654   int
00655   OString::compare(const char * s) const
00656   {
00657     return strcmp(getS().c_str(), s);
00658   }
00659 
00660   int
00661   OString::compare(const char * s, int to) const
00662   {
00663     return strncmp(getS().c_str(), s, to);
00664   }
00665 
00666   int
00667   OString::compare(const char * s, int from, int to) const
00668   {  
00669     const char * this_s = getS().c_str();
00670 
00671     if(from >= strlen(s)
00672        || from >= strlen(this_s) )
00673       {
00674         return 0;
00675       }
00676 
00677     return strncmp(this_s + from, s + from, to);
00678   }
00679 
00680   Bool
00681   OString::is_null() const
00682   {
00683     return ( (length() == 0) ? True : False);
00684   }
00685 
00686 
00687   Bool
00688   OString::match(const char * regexp) const
00689   {
00690     const char * regexp_subject = getS().c_str();
00691 
00692 #ifdef HAVE_REGCOMP
00693     regex_t * compiled_regexp = (regex_t *)malloc(sizeof(regex_t));
00694 
00695     int reg_status = regcomp(compiled_regexp, regexp, REG_EXTENDED);
00696     if ( reg_status != 0)
00697       {
00698         free(compiled_regexp);
00699         return False;      
00700       }
00701 
00702     regmatch_t match[1];
00703     reg_status = regexec((regex_t *)compiled_regexp, regexp_subject, 1, match, 0);
00704     if ( reg_status != 0)
00705       {
00706         free(compiled_regexp);
00707         return False;      
00708       }
00709   
00710     const char * start_match = regexp_subject + match[0].rm_so;
00711     const char * end_match = regexp_subject + match[0].rm_eo;
00712 #elif defined(HAVE_REGCMP)
00713     char * compiled_regexp = regcmp(regexp, (char *)0);
00714 
00715     if(compiled_regexp == 0)
00716       {
00717         return False;
00718       }
00719 
00720     char * end_match = regex(compiled_regexp, regexp_subject);
00721     char * start_match = __loc1;
00722 #endif
00723 
00724     free(compiled_regexp);
00725 
00726     if( (regexp_subject + strlen(regexp_subject)) == end_match 
00727         && regexp_subject ==  start_match)
00728       {
00729         return True;
00730       }
00731     else
00732       {
00733         return False;
00734       }
00735   }
00736 
00737   int
00738   OString::length() const
00739   {  
00740     return strlen(getS().c_str());
00741   }
00742 
00743   char **
00744   OString::split(const char * separator, int & nb_pieces) const
00745   {
00746     //get a copy of the string
00747     char * s_copy = strdup(getS().c_str());
00748 
00749     // break the copy into tokens
00750     nb_pieces = 1;
00751 
00752     int separator_len = strlen(separator);
00753 
00754     int previous_offset = 0;
00755     int current_offset = 0;
00756     while( (current_offset = find(separator, previous_offset)) >= 0 )
00757       {
00758         s_copy[current_offset] = '\0';
00759 
00760         ++nb_pieces;
00761         previous_offset = current_offset + separator_len;
00762       }
00763 
00764     // create and fill an array with the tokens
00765     typedef char * token;
00766     token * return_value = new token[nb_pieces];
00767 
00768     char * cursor = s_copy;
00769     for(int i=0; i < nb_pieces; ++i)
00770       {
00771         int token_len = strlen(cursor);
00772       
00773         char * current_token = new char[token_len + 1];
00774         strcpy(current_token, cursor);
00775         return_value[i] = current_token;          
00776 
00777         // advance cursor
00778         cursor += token_len + separator_len;
00779       }
00780 
00781     // return
00782     free(s_copy);
00783 
00784     return return_value;
00785   }
00786 
00787   char **
00788   OString::regexp_split(const char * regexp_separator, int & nb_pieces) const
00789   {
00790     //get a copy of the string
00791     char * s_copy = strdup(getS().c_str());
00792 
00793     // prepare the regular expression
00794 #ifdef HAVE_REGCOMP
00795     regex_t * compiled_separator = (regex_t *)malloc(sizeof(regex_t));
00796 
00797     int reg_status = regcomp(compiled_separator, regexp_separator, REG_EXTENDED);
00798     if ( reg_status != 0)
00799       {
00800         free(compiled_separator);
00801         return 0;      
00802       }
00803 #elif defined(HAVE_REGCMP)
00804     char * compiled_separator = regcmp(regexp_separator, (char*)0);
00805     if( compiled_separator == 0 )
00806       {
00807         return 0;
00808       }
00809 #endif
00810 
00811     // break the copy into tokens
00812     // and put them into an array
00813     nb_pieces = 0;
00814 
00815     typedef char * token;
00816     token * return_value = new token[strlen(s_copy)]; // strlen(s_copy) > nb_pieces
00817 
00818     char * cursor1 = s_copy;
00819     char * cursor2 = s_copy;
00820  
00821 #ifdef HAVE_REGEXEC
00822     regmatch_t match[1];
00823     while( regexec( compiled_separator, cursor1, 1, match, 0) == 0)
00824 #elif defined(HAVE_REGEX)
00825     while( (cursor2 = regex(compiled_separator, cursor1)) != 0 )
00826 #endif
00827       // NB: the #ifdef and the loop body are breaked out this way 
00828       // to save automatic indentation under emacs
00829       {
00830 #ifdef HAVE_REGEXEC
00831         char * separator = cursor1 + match[0].rm_so;
00832         char * cursor2 = cursor1 + match[0].rm_eo;
00833 #elif defined(HAVE_REGEX)
00834         char * separator = __loc1;
00835 #endif
00836 
00837         int separator_len = cursor2 - separator;
00838       
00839         int token_len = separator - cursor1;
00840         char * current_token = new char[ token_len + 1];
00841         current_token[0] = '\0';
00842         strncat(current_token, cursor1, token_len);
00843         return_value[nb_pieces] = current_token;
00844      
00845       
00846         ++nb_pieces;
00847         cursor1 = cursor2;
00848       }
00849 
00850     // add the last token
00851     char * current_token = new char[ strlen(cursor1) + 1];
00852     strcpy(current_token, cursor1);
00853     return_value[nb_pieces] = current_token;
00854     ++nb_pieces;
00855  
00856 
00857     // return
00858     free(s_copy);
00859     free(compiled_separator);
00860 
00861     return return_value;
00862 
00863   }
00864 }
00865     

Generated on Mon Dec 22 18:16:06 2008 for eyedb by  doxygen 1.5.3