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

CTBstring.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 <string.h>
00015 #include <ctype.h>
00016 
00017 #include "CTB.hxx"
00018 #include "CTB_Trace.hxx"
00019 #include "CTBosFill.hxx"
00020 #include "CTBstring.hxx"
00021 #include "CTBnum.hxx"
00022 #include "CTBcstringBase.hxx"
00023 
00029 //------------------------------------------+-----------------------------------
00031 
00035 static CTBint string_length(const char* c_str) 
00036 {
00037   return c_str ? strlen(c_str) : 0;
00038 }
00039 
00040 //------------------------------------------+-----------------------------------
00042 
00050 static CTBint string_length(const char* c_str, CTBint i_max) 
00051 {
00052   CTBint i_len = 0;
00053 
00054   while(i_max-- > 0 && *c_str++) i_len++;   // isn't C wonderful ...
00055 
00056   return i_len;
00057 }
00058 
00059 //------------------------------------------+-----------------------------------
00061 
00062 CTBstring::CTBstring(const CTBstring& rhs)
00063   : m_sbuf(rhs.m_sbuf),
00064     mi_offset(rhs.mi_offset),
00065     mi_length(rhs.mi_length)
00066 {
00067   CTB_Trace("CTBstring(const CTBstring&)");
00068 }
00069 
00070 //------------------------------------------+-----------------------------------
00072 
00073 CTBstring::CTBstring(const CTBstring& rhs, CTBint i_length)
00074   : m_sbuf(rhs.m_sbuf),
00075     mi_offset(rhs.mi_offset),
00076     mi_length(CTBmin(CTBmax(0,i_length),rhs.Length()))
00077 {
00078   CTB_Trace("CTBstring(const CTBstring&, CTBint)");
00079 }
00080 
00081 //------------------------------------------+-----------------------------------
00083 
00084 CTBstring::CTBstring(const CTBstring& rhs, CTBint i_offset, CTBint i_length)
00085   : m_sbuf(rhs.m_sbuf),
00086     mi_offset(0),
00087     mi_length(0)
00088 {
00089   CTB_Trace("CTBstring(const CTBstring&, CTBint, CTBint)");
00090   CTBint i_doff = CTBmin(CTBmax(0,i_offset),rhs.Length());
00091 
00092   mi_offset = rhs.mi_offset + i_doff;
00093   mi_length = CTBmin(CTBmax(0,i_length),rhs.Length()-i_doff);
00094 }
00095 
00096 //------------------------------------------+-----------------------------------
00098 
00099 CTBstring::CTBstring(const char* c_rhs)
00100   : m_sbuf(),                               // init as empty
00101     mi_offset(0),
00102     mi_length(0)
00103 {
00104   CTB_Trace("CTBstring(const char*)");
00105   NewString(c_rhs,string_length(c_rhs));
00106 }
00107 
00108 //------------------------------------------+-----------------------------------
00110 
00111 CTBstring::CTBstring(const char* c_rhs, CTBint i_length)
00112   : m_sbuf(),                               // init as empty
00113     mi_offset(0),
00114     mi_length(0)
00115 {
00116   CTB_Trace("CTBstring(const char*, CTBint)");
00117   NewString(c_rhs,string_length(c_rhs,i_length));
00118 }
00119 
00120 //------------------------------------------+-----------------------------------
00122 
00123 void CTBstring::Copy(const CTBstring& rhs)
00124 {
00125   CTB_Trace("CTBstring::Copy(const CTBstring&)");
00126 
00127   m_sbuf    = rhs.m_sbuf;
00128   mi_offset = rhs.mi_offset;
00129   mi_length = rhs.mi_length;
00130   return;
00131 }
00132 
00133 //------------------------------------------+-----------------------------------
00135 
00136 void CTBstring::Copy(const char* c_rhs)
00137 {
00138   CTB_Trace("CTBstring::Copy(const char*)");
00139   NewString(c_rhs,string_length(c_rhs));
00140   return;
00141 }
00142 
00143 //------------------------------------------+-----------------------------------
00145 
00146 void CTBstring::Copy(char c_rhs)
00147 {
00148   CTB_Trace("CTBstring::Copy(char)");
00149   char  text[1];
00150 
00151   text[0] = c_rhs;
00152   NewString(text,c_rhs ? 1 : 0);            // protect against null character 
00153   return;
00154 }
00155 
00156 //------------------------------------------+-----------------------------------
00158 
00159 void CTBstring::Append(const CTBstring& rhs)
00160 {
00161   CTB_Trace("CTBstring::Append(const CTBstring&)");
00162   AppendData(rhs.Data(),rhs.Length());
00163   return;
00164 }
00165 
00166 //------------------------------------------+-----------------------------------
00168 
00169 void CTBstring::Append(const char* c_rhs)
00170 {
00171   CTB_Trace("CTBstring::Append(const char*)");
00172   AppendData(c_rhs,string_length(c_rhs));
00173   return;
00174 }
00175 
00176 //------------------------------------------+-----------------------------------
00178 
00179 void CTBstring::Append(const char* c_rhs, CTBint i_length)
00180 {
00181   CTB_Trace("CTBstring::Append(const char*, CTBint)");
00182   AppendData(c_rhs,string_length(c_rhs,i_length));
00183   return;
00184 }
00185 
00186 //------------------------------------------+-----------------------------------
00188 
00189 void CTBstring::Append(char c_rhs)
00190 {
00191   CTB_Trace("CTBstring::Append(char)");
00192 
00193   if (c_rhs != 0) {                         // protect against null char
00194 
00195     if (mi_offset == 0 &&                   // direct append possible ?
00196         mi_length+2 <= m_sbuf.Size() &&
00197         m_sbuf.IsUnique()) {
00198       m_sbuf[mi_length] = c_rhs;
00199       mi_length        += 1;
00200       m_sbuf[mi_length] = 0;
00201 
00202     } else {                                // otherwise call generic method
00203       char text[1];
00204       text[0] = c_rhs;
00205       AppendData(text,1);
00206     }
00207   }
00208   return;
00209 } 
00210 
00211 //------------------------------------------+-----------------------------------
00213 
00219 int CTBstring::Compare(const CTBstring& rhs) const
00220 {
00221   CTB_Trace("CTBstring::Compare(const CTBstring&)");
00222   CTBint i_len = CTBmin(Length(),rhs.Length());     // minimal common length
00223   CTBint i_dif = strncmp(Data(),rhs.Data(),i_len);  // compare over min com lgt
00224 
00225   if (i_dif == 0 && Length() != rhs.Length())    // if that's equal
00226     i_dif = (Length() < rhs.Length()) ? 1 : -1;  // make longer > smaller
00227   
00228   return i_dif;
00229 }
00230 
00231 //------------------------------------------+-----------------------------------
00233 
00239 int CTBstring::Compare(const char* c_rhs) const
00240 {
00241   CTB_Trace("CTBstring::Compare(const char*)");
00242   CTBint i_rhslen = string_length(c_rhs);
00243   CTBint i_len    = CTBmin(Length(),i_rhslen); // minimal common length
00244   CTBint i_dif    = strncmp(Data(),c_rhs,i_len); // compare over min. com lgt
00245 
00246   if (i_dif == 0 && Length() != i_rhslen)   // if that's equal
00247     i_dif = (Length() < i_rhslen) ? 1 : -1; // make longer > smaller
00248   return i_dif;
00249 }
00250 
00251 //------------------------------------------+-----------------------------------
00253 
00259 int CTBstring::CompareCaseBlind(const CTBstring& rhs) const
00260 {
00261   CTB_Trace("CTBstring::CompareCaseBlind(const CTBstring&)");
00262   CTBint i_len      = CTBmin(Length(),rhs.Length()); // minimal common length
00263   const char* c_lhs = Data();
00264   const char* c_rhs = rhs.Data();
00265   int i_dif         = 0;
00266   
00267   for (CTBint i = 0; i < i_len; i++) {
00268     i_dif = tolower(*c_lhs++) - tolower(*c_rhs++);
00269     if (i_dif != 0) break;
00270   }
00271   return i_dif;
00272 }
00273 
00274 //------------------------------------------+-----------------------------------
00276 
00282 int CTBstring::CompareCaseBlind(const char* c_rhs) const
00283 {
00284   CTB_Trace("CTBstring::CompareCaseBlind(const char*)");
00285   CTBint i_rhslen   = string_length(c_rhs);
00286   CTBint i_len      = CTBmin(Length(),i_rhslen); // minimal common length
00287   const char* c_lhs = Data();
00288   int i_dif         = 0;
00289   
00290   for (CTBint i = 0; i < i_len; i++) {
00291     i_dif = tolower(*c_lhs++) - tolower(*c_rhs++);
00292     if (i_dif != 0) break;
00293   }
00294   return i_dif;
00295 }
00296 
00297 //------------------------------------------+-----------------------------------
00299 
00306 bool CTBstring::IsWhite() const
00307 {
00308   CTB_Trace("CTBstring::IsWhite()");
00309   if (mi_length > 0) {
00310     const char* p = Data();
00311     for (CTBint i = 0; i < mi_length; i++) if (!(isspace(*p++))) return false;
00312   }
00313   return true;
00314 }
00315 
00316 //------------------------------------------+-----------------------------------
00318 
00322 bool CTBstring::IsUpperCase() const
00323 {
00324   CTB_Trace("CTBstring::IsUpperCase()");
00325   if (mi_length > 0) {
00326     const char* p = Data();
00327     for (CTBint i = 0; i < mi_length; i++) {
00328       char c = *p++;
00329       if (isalpha(c) && !(isupper(c))) return false;
00330     }
00331   }
00332   return true;
00333 }
00334 
00335 //------------------------------------------+-----------------------------------
00337 
00341 bool CTBstring::IsLowerCase() const
00342 {
00343   CTB_Trace("CTBstring::IsLowerCase()");
00344   if (mi_length > 0) {
00345     const char* p = Data();
00346     for (CTBint i = 0; i < mi_length; i++) {
00347       char c = *p++;
00348       if (isalpha(c) && !(islower(c))) return false;
00349     }
00350   }
00351   return true;
00352 }
00353 
00354 //------------------------------------------+-----------------------------------
00356 
00360 void CTBstring::TrimWhite()
00361 {
00362   CTB_Trace("CTBstring::TrimWhite()");
00363 
00364   while (mi_length > 0) {                   // trim head
00365     if (!(isspace(m_sbuf[mi_offset]))) break;
00366     mi_offset += 1;
00367     mi_length -= 1;
00368   }
00369   while (mi_length > 0) {                   // trim tail
00370     if (!(isspace(m_sbuf[mi_offset+mi_length-1]))) break;
00371     mi_length -= 1;
00372   }
00373   return;
00374 }
00375 
00376 //------------------------------------------+-----------------------------------
00378 
00384 void CTBstring::CollapseWhite()
00385 {
00386   CTB_Trace("CTBstring::CollapseWhite()");
00387 
00388   if (Length() == 0) return;                // if null or empty, quit
00389   Unshare();                                // ensure not shared or substring
00390 
00391   char* pc_src = &m_sbuf[0];                // read pointer
00392   char* pc_dst = &m_sbuf[0];                // write pointer
00393   bool  b_skip = false;                     // true if next whte to be skipped
00394 
00395   for (CTBint i = 0; i < mi_length; i++) {  // loop over string
00396     char c = *pc_src++;
00397     if (isspace(c)) {                       // if white space character
00398       if (!b_skip) *pc_dst++ = ' ';         // write one blank
00399       b_skip = true;
00400     } else {                                // otherwise copy character
00401       *pc_dst++ = c;
00402       b_skip   = false;
00403     }
00404   }
00405   mi_length = pc_dst - &m_sbuf[0];          // set new string length
00406   return;
00407 }
00408 
00409 //------------------------------------------+-----------------------------------
00411 
00412 void CTBstring::ToUpperCase()
00413 {
00414   CTB_Trace("CTBstring::ToUpperCase()");
00415 
00416   if (Length() == 0) return;                // if null or empty, quit
00417   Unshare();                                // ensure not shared or substring
00418 
00419   for (CTBint i = 0; i < mi_length; i++) m_sbuf[i] = toupper(m_sbuf[i]);
00420 
00421   return;
00422 }
00423 
00424 //------------------------------------------+-----------------------------------
00426 
00427 void CTBstring::ToLowerCase()
00428 {
00429   CTB_Trace("CTBstring::ToLowerCase()");
00430 
00431   if (Length() == 0) return;                // if null or empty, quit
00432   Unshare();                                // ensure not shared or substring
00433 
00434   for (CTBint i = 0; i < mi_length; i++) m_sbuf[i] = tolower(m_sbuf[i]);
00435 
00436   return;
00437 }
00438 
00439 //------------------------------------------+-----------------------------------
00441 
00442 bool CTBstring::Get(long& i_val, int i_base) const
00443 {
00444   CTB_Trace("CTBstring::Get(long&,int)");
00445   CTBint i_size = (mi_length > 0 && Data()[mi_length] == 0) ? -1 : mi_length;
00446 
00447   return CTBcstringBase::Get(Data(),i_size,i_val,i_base);
00448 }
00449 
00450 //------------------------------------------+-----------------------------------
00452 
00453 bool CTBstring::Get(unsigned long& i_val, int i_base) const
00454 {
00455   CTB_Trace("CTBstring::Get(unsigned long&,int)");
00456   CTBint i_size = (mi_length > 0 && Data()[mi_length] == 0) ? -1 : mi_length;
00457 
00458   return CTBcstringBase::Get(Data(),i_size,i_val,i_base);
00459 }
00460 
00461 //------------------------------------------+-----------------------------------
00463 
00464 bool CTBstring::Get(int& i_val, int i_base) const
00465 {
00466   CTB_Trace("CTBstring::Get(int&,int)");
00467   CTBint i_size = (mi_length > 0 && Data()[mi_length] == 0) ? -1 : mi_length;
00468 
00469   return CTBcstringBase::Get(Data(),i_size,i_val,i_base);
00470 }
00471 
00472 //------------------------------------------+-----------------------------------
00474 
00475 bool CTBstring::Get(unsigned int& i_val, int i_base) const
00476 {
00477   CTB_Trace("CTBstring::Get(unsigned int&,int)");
00478   CTBint i_size = (mi_length > 0 && Data()[mi_length] == 0) ? -1 : mi_length;
00479 
00480   return CTBcstringBase::Get(Data(),i_size,i_val,i_base);
00481 }
00482 
00483 //------------------------------------------+-----------------------------------
00485 
00486 bool CTBstring::Get(double& d_val) const
00487 {
00488   CTB_Trace("CTBstring::Get(double&)");
00489   CTBint i_size = (mi_length > 0 && Data()[mi_length] == 0) ? -1 : mi_length;
00490 
00491   return CTBcstringBase::Get(Data(),i_size,d_val);
00492 }
00493 
00494 //------------------------------------------+-----------------------------------
00496 
00497 bool CTBstring::Get(float& f_val) const
00498 {
00499   CTB_Trace("CTBstring::Get(float&)");
00500   CTBint i_size = (mi_length > 0 && Data()[mi_length] == 0) ? -1 : mi_length;
00501 
00502   return CTBcstringBase::Get(Data(),i_size,f_val);
00503 }
00504 
00505 //------------------------------------------+-----------------------------------
00507 
00515 CTBint CTBstring::FindCharacter(const char* c_set, CTBint i_offset) const
00516 {
00517   return FindCharacter(c_set,string_length(c_set),i_offset);
00518 }
00519 
00520 //------------------------------------------+-----------------------------------
00522 
00523 CTBstring CTBstring::Escape() const
00524 {
00525   CTB_Trace("CTBstring::Escape()");
00526 
00527   if (Length() > 0 && FindCharacter("\f\n\r\t\v\\") != Length()) {
00528     CTBstring    res;
00529     const char*  p = Data();
00530 
00531     for (CTBint i = 0; i < mi_length; i++) {
00532       char c = *p++;
00533       switch (c) {
00534       case '\f':
00535         res += "\\f";
00536         break;
00537       case '\n':
00538         res += "\\n";
00539         break;
00540       case '\r':
00541         res += "\\r";
00542         break;
00543       case '\t':
00544         res += "\\t";
00545         break;
00546       case '\v':
00547         res += "\\v";
00548         break;
00549       case '\\':
00550         res += "\\";
00551         break;
00552       default:
00553         res += c;
00554         break;
00555       }      
00556     }
00557     return res;
00558   }
00559   return *this;
00560 }
00561 
00562 //------------------------------------------+-----------------------------------
00564 
00565 CTBstring CTBstring::Unescape() const
00566 {
00567   CTB_Trace("CTBstring::Unscape()");
00568 
00569   if (Length() > 0 && FindCharacter('\\') != Length()) {
00570     CTBstring    res;
00571     const char*  p = Data();
00572 
00573     for (CTBint i = 0; i < mi_length; i++) {
00574       char c = *p++;
00575 
00576       if (c == '\\' && i+1 < mi_length) {
00577         char c1 = *p++;
00578         i += 1;
00579 
00580         switch (c1) {
00581 
00582         case 'f':
00583           res += '\f';
00584           break;
00585         case 'n':
00586           res += '\n';
00587           break;
00588         case 'r':
00589           res += '\r';
00590           break;
00591         case 't':
00592           res += '\t';
00593           break;
00594         case 'v':
00595           res += '\v';
00596           break;
00597         case '\\':
00598           res += '\\';
00599           break;
00600 
00601         case '\n':                          // simply eat a \ followed by \n
00602           break;
00603 
00604         default:                            // passthrough all unknown's
00605           res += c;
00606           res += c1;
00607           break;
00608         }
00609 
00610       } else {                              // if no \ found, just pass
00611         res += c;
00612       }
00613     }
00614     return res;
00615   }
00616   return *this;
00617 }
00618 
00619 //------------------------------------------+-----------------------------------
00621 
00625 bool CTBstring::GetLine(istream& is)
00626 {
00627   CTB_Trace("CTBstring::GetLine(istream&)");
00628   char  buf[1024];
00629   
00630   if (!is) return false;
00631 
00632   buf[0] = 0;
00633   is.getline(buf,1024);
00634   
00635   if (is.good() || (is.gcount() > 0 && is.eof())) {
00636     *this = buf;
00637     return true;
00638   }
00639   return false;
00640 }
00641 
00642 //------------------------------------------+-----------------------------------
00644 
00645 void CTBstring::Dump(int i_indent, ostream& os, const char* p_text) const
00646 {
00647   CTBosFill bl(i_indent);
00648   
00649   os << bl << "--CTBstring ";
00650   if (p_text) os << p_text;
00651   os << " @ " << this << endl;
00652   m_sbuf.Dump(i_indent+2,os,"m_sbuf");
00653   os << bl << "    mi_offset:     " << mi_offset << endl;
00654   os << bl << "    mi_length:     " << mi_length << endl;
00655   return;
00656 }
00657 
00658 //------------------------------------------+-----------------------------------
00660 
00664 char CTBstring::operator[](CTBint i_ind) const
00665 {
00666   CTB_Trace("CTBstring::operator[](CTBint)");
00667 
00668   if (i_ind < 0 && i_ind >= Length()) return 0;   // return 0 if out-of-range 
00669   return Data()[i_ind];    
00670 }
00671 
00672 //------------------------------------------+-----------------------------------
00674 
00681 CTBstring::operator const char*() const
00682 {
00683   CTB_Trace("CTBstring::operator const char*()");
00684 
00685   if (m_sbuf.IsNull()) return "";
00686 
00687   ((CTBstring*) this) -> Terminate();
00688   return Data();
00689 }
00690 
00691 // Note:
00692 //  1. Even though the const char* conversion does not change the value of
00693 //     the string it might force a change of it's internal representation.
00694 //     This happens for substrings, which have to be converted to a null
00695 //     terminated format.
00696 //
00697 //     Therefore, there is a conflict between logical and physical const-ness.
00698 //     The const char* clearly has to be a const member function to be useful,
00699 //     but it has to be able to change the object !
00700 //
00701 //     The confict is resolved here by doing the `dirt work' in a separate
00702 //     member function Terminate(), which is not const, which is called by
00703 //     simply casting away the const....
00704 
00705 //------------------------------------------+-----------------------------------
00711 CTBstring operator+(const CTBstring& lhs, const CTBstring& rhs)
00712 {
00713   CTB_Trace("operator+(const CTBstring&, const CTBstring&)");
00714   CTBstring res;
00715 
00716   res.NewString(lhs.Data(),lhs.Length(),rhs.Data(),rhs.Length());
00717   return res;
00718 }
00719 
00720 //------------------------------------------+-----------------------------------
00726 CTBstring operator+(const CTBstring& lhs, const char* c_rhs)
00727 {
00728   CTB_Trace("operator+(const CTBstring&, const char*)");
00729   CTBstring res;
00730 
00731   res.NewString(lhs.Data(),lhs.Length(),c_rhs,string_length(c_rhs));
00732   return res;  
00733 }
00734 
00735 //------------------------------------------+-----------------------------------
00741 CTBstring operator+(const char* c_lhs, const CTBstring& rhs)
00742 {
00743   CTB_Trace("operator+(const char*, const CTBstring&)");
00744   CTBstring res;
00745 
00746   res.NewString(c_lhs,string_length(c_lhs),rhs.Data(),rhs.Length());
00747   return res;  
00748 }
00749 
00750 //------------------------------------------+-----------------------------------
00756 ostream& operator<<(ostream& os, const CTBstring& rhs)
00757 {
00759   if (rhs.Length() > 0) os.write(rhs.Data(),rhs.Length());
00760   return os;
00761 }
00762 
00763 //------------------------------------------+-----------------------------------
00765 
00766 const CTBstring& CTBstring::NullString()
00767 {
00768   static const CTBstring nullstring;
00769   return nullstring;
00770 }
00771 
00772 //------------------------------------------+-----------------------------------
00774 
00775 const CTBstring& CTBstring::EmptyString()
00776 {
00777   static const CTBstring emptystring("");
00778   return emptystring;
00779 }
00780 
00781 //------------------------------------------+-----------------------------------
00783 
00784 void CTBstring::Unshare()
00785 {
00786   CTB_Trace("CTBstring::Unshare()");
00787   if (mi_offset > 0 ||                      // is substring
00788       m_sbuf.IsShared()) {                  // or shared
00789     CTBstring lhs(*this);
00790     NewString(lhs.Data(),lhs.Length());     // recreate
00791   }
00792   return;
00793 }
00794 
00795 //------------------------------------------+-----------------------------------
00797 
00804 void CTBstring::EnsureUnsharedCapacity(CTBint i_capacity)
00805 {
00806   CTB_Trace("CTBstring::EnsureUnsharedCapacity(CTBint)");
00807   CTBint i_size = i_capacity + 1;           // take care of trailing null char
00808 
00809   i_size = i_size + 7;
00810   i_size = i_size - (i_size & 7);           // round up so that mod(8) = 0
00811 
00812   if (m_sbuf.IsShared()) {                  // if buffer shared
00813     m_sbuf.Resize(i_size);                  // resize will create a new one !
00814   } else {
00815     CTBint i_oldsize = m_sbuf.Size();
00816     if (i_oldsize < i_size) {               // buffer too small ?
00817       CTBint i_incsize = (i_oldsize <= 512) ? i_oldsize : i_oldsize/2;
00818       CTBint i_newsize = CTBmax(i_size,i_oldsize+i_incsize);
00819       m_sbuf.Resize(i_newsize);
00820     }
00821   }
00822   return;
00823 }
00824 
00825 //------------------------------------------+-----------------------------------
00827 
00834 void CTBstring::NewString(const char* c_str, CTBint i_len)
00835 {
00836   CTB_Trace("CTBstring::NewString(const char*, CTBint)");
00837 
00838   if (c_str) {                              // if non-null string
00839     EnsureUnsharedCapacity(i_len);
00840     if (i_len > 0) strncpy(&m_sbuf[0],c_str,i_len);
00841     m_sbuf[i_len] = 0;
00842     mi_length     = i_len;
00843     mi_offset     = 0;
00844 
00845   } else {                                  // if null string
00846     m_sbuf.Release();
00847     mi_length = 0;
00848     mi_offset = 0;
00849   }
00850   
00851   return;
00852 }
00853 
00854 //------------------------------------------+-----------------------------------
00856 
00864 void CTBstring::NewString(const char* c_str1, CTBint i_len1,
00865                           const char* c_str2, CTBint i_len2)
00866 {
00867   CTB_Trace("CTBstring::NewString(const char*, CTBint, const char*, CTBint)");
00868 
00869   if (c_str1 || c_str2) {                   // at least one non-null string
00870     CTBint i_length = i_len1 + i_len2;
00871 
00872     EnsureUnsharedCapacity(i_length);
00873     if (i_len1 > 0) strncpy(&m_sbuf[0],c_str1,i_len1);
00874     if (i_len2 > 0) strncpy(&m_sbuf[i_len1],c_str2,i_len2);
00875     m_sbuf[i_length] = 0;
00876     mi_length        = i_length;
00877     mi_offset        = 0;
00878 
00879   } else {                                  // both input string are null
00880     m_sbuf.Release();
00881     mi_length = 0;
00882     mi_offset = 0;
00883   }
00884   
00885   return;
00886 }
00887 
00888 //------------------------------------------+-----------------------------------
00890 
00891 void CTBstring::AppendData(const char* c_str, CTBint i_len)
00892 {
00893   CTB_Trace("CTBstring::AppendData(const char*, CTBint");
00894 
00895   if (i_len > 0) {                          // no action on zero length string
00896     CTBint i_oldlen = mi_length;
00897     CTBint i_newlen = i_oldlen + i_len;
00898 
00899     if (mi_offset == 0 &&                   // is no substring
00900         i_newlen+1 <= m_sbuf.Size() &&      // buffer large enough
00901         m_sbuf.IsUnique() ) {               // and not shared
00902       strncpy(&m_sbuf[mi_length],c_str,i_len);
00903       m_sbuf[i_newlen] = 0;
00904       mi_length        = i_newlen;
00905 
00906     } else {
00907       CTBstring lhs(*this, true);
00908       CTBint    i_newcap = CTBmax(2*i_oldlen, i_newlen);
00909       
00910       EnsureUnsharedCapacity(i_newcap);
00911       if (i_oldlen > 0) strncpy(&m_sbuf[0],lhs.Data(),i_oldlen);
00912       strncpy(&m_sbuf[i_oldlen],c_str,i_len);
00913       m_sbuf[i_newlen] = 0;
00914       mi_length        = i_newlen;
00915       mi_offset        = 0;
00916     }
00917   }
00918 
00919   return;
00920 }
00921 
00922 //------------------------------------------+-----------------------------------
00924 
00925 void CTBstring::Terminate()
00926 {
00927   CTB_Trace("CTBstring::Terminate()");
00928 
00929   if (m_sbuf.IsNull()) return;
00930 
00931   if (Data()[Length()] != 0) {              // string not terminated ?
00932     if (m_sbuf.IsUnique()) {                // if buffer not shared
00933       m_sbuf[mi_offset+mi_length] = 0;      // just terminate string
00934     } else {                                // if shared
00935       NewString(Data(),Length());           // recreate it
00936     }
00937   }
00938   return;
00939 }
00940 
00941 //------------------------------------------+-----------------------------------
00943 
00951 CTBint CTBstring::FindCharacter(const char* c_set, CTBint i_len, 
00952                                 CTBint i_offset) const
00953 {
00954   CTB_Trace("CTBstring::FindCharacter(const char*, CTBint, CTBint)");
00955 
00956   if (mi_length > 0 && i_offset < mi_length && i_len > 0) {
00957     CTBint      i_off   = CTBmax(0,i_offset);
00958 
00959     for (CTBint i = i_off; i < mi_length; i++) {
00960       char c = m_sbuf[mi_offset+i];
00961 
00962       for (CTBint j = 0; j < i_len; j++) {
00963         if (c == c_set[j]) return i;
00964       }
00965     }
00966   }
00967   return mi_length;
00968 }

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