Main Page   Modules   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages   Examples  

CTBcstringBase.cxx

Go to the documentation of this file.
00001 
00006 /*----------------------------------------------------------------------------*/
00007 /* C Tool Box: Designed and implemented by:                                   */
00008 /*    Walter F.J. Mueller   Gesellschaft fuer Schwerionenforschung (GSI)      */
00009 /*                          Planckstrasse 1, D-64291 Darmstadt, Germany       */
00010 /*                  Email:  W.F.J.Mueller@gsi.de                              */
00011 /*                  WWW:    http://www-kp3.gsi.de/www/kp3/people/mueller.html */
00012 /*------------------------------------------+---------------------------------*/
00013 
00014 #include <stdlib.h>
00015 #include <string.h>
00016 #include <ctype.h>
00017 #include <errno.h>
00018 #include <limits.h>
00019 #include <float.h>
00020 
00021 #include "CTB.hxx"
00022 #include "CTB_Trace.hxx"
00023 #include "CTBcstringBase.hxx"
00024 #include "CTBnum.hxx"
00025 
00031 //------------------------------------------+-----------------------------------
00033 
00034 void CTBcstringBase::Copy(char* c_dst, CTBint i_size,
00035                           const char* c_src)
00036 {
00037   CTB_Trace("CTBcstringBase::Copy(char*,CTBint,const char*)");
00038 
00039   if (c_src) {
00040     strncpy(c_dst,c_src,i_size-1);
00041     c_dst[i_size-1] = 0;
00042   } else {
00043     c_dst[0] = 0;
00044   }
00045   return;
00046 }
00047 
00048 //------------------------------------------+-----------------------------------
00050 
00051 void CTBcstringBase::Copy(char* c_dst, CTBint i_size,
00052                           const char* c_src, CTBint i_offset, CTBint i_length)
00053 {
00054   CTB_Trace("CTBcstringBase::Copy(char*,CTBint,const char*,CTBint,CTBint)");
00055 
00056   if (c_src) {
00057     CTBint i_lsrc = CTBmin(i_length,i_size-1);
00058     strncpy(c_dst,c_src+i_offset,i_lsrc);
00059     c_dst[i_lsrc] = 0;
00060   } else {
00061     c_dst[0] = 0;
00062   }
00063   return;
00064 }
00065 
00066 //------------------------------------------+-----------------------------------
00068 
00069 void CTBcstringBase::Append(char* c_dst, CTBint i_size, 
00070                             const char* c_src)
00071 {
00072   CTB_Trace("CTBcstringBase::Append(char*,CTBint,const char*)");
00073 
00074   if (c_src) {
00075     CTBint i_ldst = strlen(c_dst);
00076     strncpy(c_dst+i_ldst,c_src,i_size-i_ldst-1);
00077     c_dst[i_size-1] = 0;
00078   }
00079   return;
00080 }
00081 
00082 //------------------------------------------+-----------------------------------
00084 
00085 void CTBcstringBase::Append(char* c_dst, CTBint i_size,
00086                             const char* c_src, CTBint i_offset, CTBint i_length)
00087 {
00088   CTB_Trace("CTBcstringBase::Append(char*,CTBint,const char*,CTBint,CTBint)");
00089 
00090   if (c_src) {
00091     CTBint i_ldst = strlen(c_dst);
00092     CTBint i_lsrc;
00093 
00094     if (i_length < 0) i_length = strlen(c_src+i_offset);
00095     i_lsrc = CTBmin(i_size-i_ldst-1,i_length);
00096     strncpy(c_dst+i_ldst,c_src+i_offset,i_lsrc);
00097     c_dst[i_ldst+i_lsrc] = 0;
00098   }
00099   return;
00100 }
00101 
00102 //------------------------------------------+-----------------------------------
00104 
00105 void CTBcstringBase::Trim(char* c_dst, CTBint)
00106                                             // i_size currently not used ...
00107 {
00108   CTB_Trace("CTBcstringBase::Trim(char*,CTBint)");
00109 
00110   CTBint i_length = strlen(c_dst);
00111   char*  pc_cur;
00112   char*  pc_out = c_dst;
00113 
00114   if (i_length == 0) return;                // nothing to do
00115 
00116   pc_cur = c_dst + i_length -1;             // point to last character
00117   for ( ; i_length > 0; i_length--) {       // drop trailing white space
00118     if (!isspace(*pc_cur)) break;
00119     pc_cur--;
00120   }
00121   
00122   pc_cur = c_dst;
00123   for ( ; i_length > 0; i_length--) {       // drop leading white space
00124     if (!isspace(*pc_cur)) break;
00125     pc_cur++;
00126   }
00127 
00128   // pc_cur now points to the first non white character,
00129   // i_length holds the length of the trimmed string
00130 
00131   if (pc_cur == c_dst) {                    // no leading, only trailing ws
00132     c_dst[i_length] = 0;                    // just truncate
00133   } else {                                  // otherwise shift
00134     for ( ; i_length > 0; i_length--) *pc_out++ = *pc_cur++;
00135     *pc_out = 0;
00136   }
00137 
00138   return;
00139 }
00140 
00141 //------------------------------------------+-----------------------------------
00143 
00144 void CTBcstringBase::Toupper(char* c_dst, CTBint i_size)
00145 {
00146   CTB_Trace("CTBcstringBase::Toupper(char*,CTBint)");
00147 
00148   for (CTBint i = 0; i < i_size; i++) {
00149     char c = c_dst[i];
00150     if (c == 0) break;
00151     c_dst[i] = _toupper(c);
00152   }
00153   return;
00154 }
00155 
00156 //------------------------------------------+-----------------------------------
00158 
00159 void CTBcstringBase::Tolower(char* c_dst, CTBint i_size)
00160 {
00161   CTB_Trace("CTBcstringBase::Tolower(char*,CTBint)");
00162 
00163   for (CTBint i = 0; i < i_size; i++) {
00164     char c = c_dst[i];
00165     if (c == 0) break;
00166     c_dst[i] = _tolower(c);
00167   }
00168 }
00169 
00170 //------------------------------------------+-----------------------------------
00172 
00179 static const char* trim_to_buffer(const char* c_src, CTBint i_size,
00180                                   char* c_buf, CTBint i_bufsize)
00181 {
00182   if (i_size < 0) return c_src;             // if zero-terminated string
00183 
00184   const char* pc_cur = c_src + i_size -1;   // point to last character
00185 
00186   for ( ; i_size > 0; i_size--) {           // drop trailing white space
00187     if (!isspace(*pc_cur)) break;
00188     pc_cur--;
00189   }
00190   
00191   pc_cur = c_src;
00192   for ( ; i_size > 0; i_size--) {           // drop leading white space
00193     if (!isspace(*pc_cur)) break;
00194     pc_cur++;
00195   }
00196 
00197   // pc_cur now points to the first non white character,
00198   // i_size holds the length of the trimmed string
00199 
00200   if (i_size >= i_bufsize) return 0;        // indicate string too long
00201 
00202   strncpy(c_buf,pc_cur,i_size);             // copy trimmed string to buffer
00203   c_buf[i_size] = 0;                        // zero-terminate
00204   return c_buf;  
00205 }
00206 
00207 //------------------------------------------+-----------------------------------
00209 
00222 bool CTBcstringBase::Get(const char* c_src, CTBint i_size,
00223                          long& i_val, int i_base)
00224 {
00225   CTB_Trace("CTBcstringBase::Get(const char*,CTBint,long&,int)");
00226 
00227   char   c_buf[256];
00228   char*  pc_end;                            // NOTE: strtol endptr has no const
00229   char   c;
00230   long   i_tmp;
00231 
00232   if (c_src == 0 || i_size == 0) {          // null or empty string
00233     i_val = 0;                              // convert as 0
00234     return true;
00235   }
00236 
00237   c_src = trim_to_buffer(c_src,i_size,c_buf,256); // extract substring ...
00238   if (c_src == 0) return false;             // check for buffer size error
00239 
00240   errno = 0;
00241   i_tmp = strtol(c_src,&pc_end,i_base);
00242 
00243   if (errno != 0) return false;
00244   if (pc_end != 0) {                        // if left overs, check them  
00245     while ((c = *pc_end++)) {               // check rest
00246       if (!isspace(c)) return false;        // complain on any non white
00247     }
00248   }
00249   
00250   i_val = i_tmp;                            // if all o.k., assign value
00251   return true;                              // and return success
00252 }
00253   
00254 //------------------------------------------+-----------------------------------
00256  
00257 bool CTBcstringBase::Get(const char* c_src, CTBint i_size,
00258                          unsigned long& i_val, int i_base)
00259 {
00260   CTB_Trace("CTBcstringBase::Get(const char*,CTBint,unsigned long&,int)");
00261 
00262   char          c_buf[256];
00263   char*         pc_end;                     // NOTE: strtol endptr has no const
00264   char          c;
00265   unsigned long i_tmp;  
00266 
00267   if (c_src == 0 || i_size == 0) {          // null or empty string
00268     i_val = 0;                              // convert as 0
00269     return true;
00270   }
00271 
00272   c_src = trim_to_buffer(c_src,i_size,c_buf,256); // extract substring ...
00273   if (c_src == 0) return false;             // check for buffer size error
00274 
00275   errno = 0;
00276   i_tmp = strtoul(c_src,&pc_end,i_base);
00277 
00278   if (errno != 0) return false;
00279   if (pc_end != 0) {                        // if left overs, check them  
00280     while ((c = *pc_end++)) {               // check rest
00281       if (!isspace(c)) return false;        // complain on any non white
00282     }
00283   }
00284   
00285   i_val = i_tmp;                            // if all o.k., assign value
00286   return true;                              // and return success
00287 }
00288   
00289 //------------------------------------------+-----------------------------------
00291 
00292 bool CTBcstringBase::Get(const char* c_src, CTBint i_size,
00293                          int& i_val, int i_base)
00294 {
00295   CTB_Trace("CTBcstringBase::Get(const char*,CTBint,int&,int)");
00296 
00297   long i_tmp;
00298 
00299   if (!Get(c_src,i_size,i_tmp,i_base)) return false;
00300 
00301   if (i_tmp < INT_MIN || i_tmp > INT_MAX) return false;
00302   i_val = i_tmp;                            // if all o.k., assign value
00303   return true;                              // and return success
00304 }
00305   
00306 //------------------------------------------+-----------------------------------
00308 
00309 bool CTBcstringBase::Get(const char* c_src, CTBint i_size,
00310                          unsigned int& i_val, int i_base)
00311 {
00312   CTB_Trace("CTBcstringBase::Get(const char*,CTBint,unsigned int&,int)");
00313 
00314   unsigned long i_tmp;
00315 
00316   if (!Get(c_src,i_size,i_tmp,i_base)) return false;
00317 
00318   if (i_tmp > UINT_MAX) return false;
00319   i_val = i_tmp;                            // if all o.k., assign value
00320   return true;                              // and return success
00321 }
00322   
00323 //------------------------------------------+-----------------------------------
00325 
00326 bool CTBcstringBase::Get(const char* c_src, CTBint i_size, double& d_val)
00327 {
00328   CTB_Trace("CTBcstringBase::Get(const char*,CTBint,double&)");
00329 
00330   char    c_buf[256];
00331   char*   pc_end;                           // NOTE: strtol endptr has no const
00332   char    c;
00333   double  d_tmp;
00334 
00335   if (c_src == 0 || i_size == 0) {          // null or empty string
00336     d_val = 0.;                             // convert as 0
00337     return true;
00338   }
00339 
00340   c_src = trim_to_buffer(c_src,i_size,c_buf,256); // extract substring ...
00341   if (c_src == 0) return false;             // check for buffer size error
00342 
00343   errno = 0;
00344   d_tmp = strtod(c_src,&pc_end);
00345 
00346   if (errno != 0) return false;
00347   if (pc_end != 0) {                        // if left overs, check them  
00348     while ((c = *pc_end++)) {               // check rest
00349       if (!isspace(c)) return false;        // complain on any non white
00350     }
00351   }
00352   
00353   d_val = d_tmp;                            // if all o.k., assign value
00354   return true;                              // and return success
00355 }
00356   
00357 //------------------------------------------+-----------------------------------
00359 
00360 bool CTBcstringBase::Get(const char* c_src, CTBint i_size, float& f_val)
00361 {
00362   CTB_Trace("CTBcstringBase::Get(const char*,CTBint,float&)");
00363 
00364   double d_tmp;
00365 
00366   if (!Get(c_src,i_size,d_tmp)) return false;
00367 
00368   if (d_tmp < -FLT_MAX || d_tmp > FLT_MAX) return false;
00369   f_val = d_tmp;                            // if all o.k., assign value
00370   return true;                              // and return success
00371 }
00372   
00373 //------------------------------------------+-----------------------------------
00375 
00376 CTBint CTBcstringBase::Locate(const char* c_src, CTBint, char c_char)
00377                                             // i_size currently not used
00378 {
00379   CTB_Trace("CTBcstringBase::Locate(const char*,CTBint,char)");
00380 
00381   const char* pc_char = strchr(c_src,c_char);
00382   if (pc_char) return pc_char - c_src;      // if found, return offset
00383   return strlen(c_src);                     // else string length
00384 }
00385 
00386 //------------------------------------------+-----------------------------------
00388 
00389 int CTBcstringBase::NField(const char* c_src, CTBint,
00390                            const char* c_delim)
00391                                             // i_size currently not used
00392 {
00393   CTB_Trace("CTBcstringBase::NField(const char*,CTBint,const char*)");
00394   int     i_length = strlen(c_src);
00395 
00396   if (i_length == 0) return 0;              // an empty string has 0 fields
00397 
00398   if (!c_delim || c_delim[0] == 0) {        // if c_delim nul or empty
00399                                             // --> delimiter is any white space
00400     const char* pc_cur;
00401     int   i_cnt = 0;
00402 
00403     pc_cur = c_src + i_length -1;
00404     for ( ; i_length > 0; i_length--) {     // drop trailing white space
00405       if (!isspace(*pc_cur)) break;
00406       pc_cur--;
00407     }
00408     pc_cur = c_src;
00409     for ( ; i_length > 0; i_length--) {     // drop leading white space
00410       if (!isspace(*pc_cur)) break;
00411       pc_cur++;
00412     }
00413   
00414     if (i_length == 0) return 0;            // quit on blank string
00415 
00416     for ( ; i_length > 0 ; ) {              // loop over fields
00417       for ( ; i_length > 0; i_length--) {   // skip over one field 
00418         if (isspace(*pc_cur)) break;
00419         pc_cur++;
00420       }
00421       for ( ; i_length > 0; i_length--) {   // skip over one delimiter
00422         if (!isspace(*pc_cur)) break;
00423         pc_cur++;
00424       }
00425       i_cnt++;
00426     }
00427     return i_cnt;
00428   }
00429 
00430   if (c_delim[1] == 0) {                    // delimiter is a single character
00431     const char* pc_cur = c_src;
00432     int   i_cnt  = 1;
00433     char  c_del  = c_delim[0];
00434     for ( ; i_length > 0; i_length--) if (*pc_cur++ == c_del) i_cnt++;
00435     return i_cnt;
00436   } else {                                  // delimiter is character set
00437     const char* pc_cur = c_src;
00438     int   i_cnt  = 1;
00439     for ( ; i_length > 0; i_length--) if (InSet(*pc_cur++,c_delim)) i_cnt++;
00440     return i_cnt;
00441   }
00442   return 0;
00443 }
00444 
00445 //------------------------------------------+-----------------------------------
00447 
00448 bool CTBcstringBase::LocateField( const char* c_src, CTBint,
00449                                   CTBint& i_foffset, CTBint& i_flength,
00450                                   CTBint i_ind, const char* c_delim)
00451                                             // i_size currently not used
00452 {
00453   CTB_Trace("CTBcstringBase::LocateField(const char*,CTBint,CTBint&,CTBint&,CTBint,const char*)");
00454   int i_length = strlen(c_src);
00455 
00456   i_foffset  = i_length;                    // init output (in case of bailout)
00457   i_flength = 0;
00458 
00459   if (i_ind < 0) return false;              // bad index: return w/ no success
00460   
00461   if (!c_delim || c_delim[0] == 0) {        // if c_delim null or empty
00462                                             // than delimiter is any white space
00463     const char* pc_cur;
00464     const char* pc_beg;
00465 
00466     pc_cur = c_src + i_length -1;
00467     for ( ; i_length > 0; i_length--) {     // drop trailing white space
00468       if (!isspace(*pc_cur)) break;
00469       pc_cur--;
00470     }
00471     pc_cur = c_src;
00472     for ( ; i_length > 0; i_length--) {     // drop leading white space
00473       if (!isspace(*pc_cur)) break;
00474       pc_cur++;
00475     }
00476   
00477     for ( ; ; i_ind--) {                    // loop over fields
00478       pc_beg = pc_cur;
00479       for ( ; i_length > 0; i_length--) {   // skip over one field
00480         if (isspace(*pc_cur)) break;
00481         pc_cur++;
00482       }
00483       if (i_ind == 0) {                     // field found ? 
00484         i_foffset = pc_beg - c_src;
00485         i_flength = pc_cur - pc_beg;
00486         return true;
00487       }
00488       if (i_length == 0) return false;      // end of string ?
00489       for ( ; i_length > 0; i_length--) {   // skip over one delimiter
00490         if (!isspace(*pc_cur)) break;
00491         pc_cur++;
00492       }
00493     }
00494   }
00495 
00496   if (c_delim[1] == 0) {                    // delimiter is a single character
00497     const char*  pc_cur = c_src;
00498     const char*  pc_beg;
00499     char   c = c_delim[0];
00500 
00501     for ( ; ; i_ind--) {                    // loop over fields
00502       pc_beg = pc_cur;
00503       for ( ; i_length > 0; i_length--) {   // skip over one field
00504         if (*pc_cur == c) break;
00505         pc_cur++;
00506       }
00507       if (i_ind == 0) {                     // field found ?
00508         i_foffset = pc_beg - c_src;
00509         i_flength = pc_cur - pc_beg;
00510         return true;
00511       }
00512       if (i_length == 0) return false;      // end of string ?
00513       i_length--; pc_cur++;                 //skip over the delimiter char
00514     }
00515 
00516   } else {                                  // delimiter is character set
00517     const char* pc_cur = c_src;
00518     const char* pc_beg;
00519     for ( ; ; i_ind--) {                    // loop over fields 
00520       pc_beg = pc_cur;
00521       for ( ; i_length > 0; i_length--) {   // skip over one field
00522         if (InSet(*pc_cur,c_delim)) break;
00523         pc_cur++;
00524       }
00525       if (i_ind == 0) {                     // field found ?
00526         i_foffset = pc_beg - c_src;
00527         i_flength = pc_cur - pc_beg;
00528         return true;
00529       }
00530       if (i_length == 0) return false;      // end of string ?
00531       i_length--; pc_cur++;                 // skip over the delimiter chars
00532     }
00533   }
00534   
00535   return false;
00536 }
00537 
00538 //------------------------------------------+-----------------------------------
00540 
00541 bool CTBcstringBase::CopyField(char* c_dst, CTBint i_size,
00542                                const char* c_src, CTBint i_ind,
00543                                const char* c_delim)
00544 {
00545   CTB_Trace("CTBcstringBase::CopyField(const char*,CTBint,const char*,CTBint,const char*)");
00546   CTBint i_foffset;
00547   CTBint i_flength;
00548   bool   b_found = LocateField(c_src,-1,i_foffset,i_flength,i_ind,c_delim);
00549 
00550   if (b_found) {
00551     Copy(c_dst,i_size,c_src,i_foffset,i_flength);
00552   } else {
00553     c_dst[0] = 0;
00554   }
00555   return b_found;
00556 }
00557 
00558 //------------------------------------------+-----------------------------------
00560 
00561 bool CTBcstringBase::GetLine(char* c_dst, CTBint i_size, istream& is)
00562 {
00563   CTB_Trace("CTBcstringBase::GetLine(const char*,CTBint,istream&)");
00564 
00565   if (c_dst == 0 || i_size == 0) return false;  // bad destination ?
00566   c_dst[0] = 0;                             // clear string
00567   if (!is) return false;                    // bad stream
00568   
00569   is.getline(c_dst,i_size);
00570   return !is.fail();
00571 }
00572 
00573 //------------------------------------------+-----------------------------------
00575 
00576 bool CTBcstringBase::FromStream(char* c_dst, CTBint i_size, istream& is)
00577 {
00578   CTB_Trace("CTBcstringBase::FromStream(const char*,CTBint,istream&)");
00579   int i_width = is.width();
00580 
00581   if (c_dst == 0 || i_size == 0) return false;  // bad destination ?
00582   c_dst[0] = 0;                             // clear string
00583   if (!is) return false;                    // bad stream
00584   
00585   if (i_width == 0) {                       // if no width defined
00586     i_width = i_size;                       // use string size
00587   } else {
00588     if (i_width > i_size) i_width = i_size; // else limit to string size
00589   }
00590   is >> setw(i_width) >> c_dst;
00591 
00592   return !is.fail();
00593 }
00594 // Note: reading a field larger than the string size does not put the
00595 //       stream into error state !!???
00596 
00597 #if (defined(CTB__OutLine) || defined(CTBcstringBase__OutLine))
00598 #define inline
00599 #include "CTBcstringBase.icc"
00600 #undef  inline
00601 #endif
00602 
00603 // Notes:
00604 // 1. re-evaluate usage if i_size
00605 // 2. re-check Get
00606 // 3. add Get's for other types
00607 // 4. GET ALL CALLS, especially Copy and Append, protected agains
00608 //    i_offset larger than length (jumping over terminating zero...)
00609 // 5. Check, whether all functions are tolerant against null string args...
00610 //

Generated at Fri Oct 24 18:11:28 2003 for CTBbase by doxygen1.2.9-20010812 written by Dimitri van Heesch, © 1997-2001