Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

Atom.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 
00003 // This file is part of Vesta.
00004 
00005 // Vesta 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 // Vesta 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 Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Sun May 22 21:53:13 EDT 2005 by ken@xorian.net        
00020 //      modified on Thu Apr 21 09:24:42 EDT 2005 by irina.furman@intel.com
00021 //      modified on Mon Jul 29 14:49:45 EDT 2002 by kcschalk@shr.intel.com
00022 //      modified on Mon May  3 16:04:46 PDT 1999 by heydon
00023 
00024 #include <Basics.H>
00025 #include "Generics.H"
00026 #include "Atom.H"
00027 
00028 // The global atom table and the mutex that protects it
00029 static Basics::mutex mu;
00030 static TextStringTbl *tbl = 0;
00031 
00032 // The empty text to which the Atom() constructor initializes new Atom's
00033 static const Text EmptyTxt;
00034 
00035 // Module initialization ------------------------------------------------------
00036 
00037 class AtomInit {
00038   public:
00039     AtomInit() throw ();
00040 };
00041 static AtomInit init;
00042 
00043 AtomInit::AtomInit() throw ()
00044 {
00045     mu.lock();
00046     // allocate new table
00047     tbl = NEW_CONSTR(TextStringTbl, (/*sizeHint=*/ 100));
00048 
00049     // add empty string
00050     bool inTbl = tbl->Put(EmptyTxt, EmptyTxt.cchars()); assert(!inTbl);
00051     mu.unlock();
00052 }
00053 
00054 // StrCopy --------------------------------------------------------------------
00055 
00056 static const char *StrCopy(const char *str) throw ()
00057 // Returns a newly allocated copy of the null-terminated string "str".
00058 {
00059     int len = strlen(str) + 1;  // include +1 for null terminator
00060     char* res = NEW_PTRFREE_ARRAY(char, len);
00061     memcpy(res, str, len);
00062     return res;
00063 }
00064 
00065 static const char *StrCopy(const char *s, int len) throw ()
00066 /* Returns a newly-allocated, null-terminated copy of the "len" chars pointed
00067    to by "s"; it is an unchecked run-time error for any of those bytes to
00068    be the null character. */
00069 {
00070     char* res = NEW_PTRFREE_ARRAY(char, len+1);
00071     memcpy(res, s, len);
00072     res[len] = '\0';
00073     return res;
00074 }
00075 
00076 // assignment -----------------------------------------------------------------
00077 
00078 Atom& Atom::operator = (const char* str) throw ()
00079 {
00080     this->Init(str, /*cpy=*/ (void *)NULL);
00081     return *this;
00082 }
00083 
00084 Atom& Atom::operator = (const Text& t) throw ()
00085 {
00086     this->Init(t.cchars(), Text::GCImpl() ? (void *)1 : (void *)NULL);
00087     return *this;
00088 }
00089 
00090 Atom& Atom::operator = (const Atom& a) throw ()
00091 {
00092     // always simply copy the string pointer from another atom
00093     this->s = a.s;
00094     return *this;
00095 }
00096 
00097 // destructive concatenation --------------------------------------------------
00098 static const char *StrConcat(const char *str1, const char *str2,
00099   bool str2mutable) throw ()
00100 /* Return a newly allocated null-terminated string containing the
00101    concatenation of the null-terminated strings "str1" and "str2". In the
00102    event that either "str1" or "str2" is empty, simply return the other
00103    string. In that case, the corresponding "str?mutable" argument is
00104    consulted to see if the string needs to be copied first. */
00105 {
00106     // Note: null terminator is only included in second string
00107     int len1 = strlen(str1), len2 = strlen(str2);
00108     char *res;
00109     if (len1 == 0) {
00110         return (str2mutable ? StrCopy(str2, len2) : str2);
00111     } else if (len2 == 0) {
00112         return str1;
00113     } else {
00114         char *res = NEW_PTRFREE_ARRAY(char, len1 + len2 + 1);
00115         memcpy(res, str1, len1);
00116         memcpy(res + len1, str2, len2 + 1);
00117         return res;
00118     }
00119 }
00120 
00121 Atom& Atom::operator += (const char* str) throw ()
00122 {
00123     const char *catres = StrConcat(this->s, str, true);
00124     this->Init(catres, /*cpy=*/ (void *)NULL);
00125     return *this;
00126 }
00127 
00128 Atom& Atom::operator += (const Text& t) throw ()
00129 {
00130     const char *catres = StrConcat(this->s, t.cchars(), true);
00131     this->Init(catres, /*cpy=*/ (void *)NULL);
00132     return *this;
00133 }
00134 
00135 Atom& Atom::operator += (const Atom& a) throw ()
00136 {
00137     const char *catres = StrConcat(this->s, a.s, false);
00138     this->Init(catres, /*cpy=*/ (void *)NULL);
00139     return *this;
00140 }
00141 
00142 // Atom::Init -----------------------------------------------------------------
00143 
00144 void Atom::Init(const char* str, const void* cpy) throw ()
00145 {
00146     mu.lock();
00147     Text inTxt(str);
00148     if (!(tbl->Get(inTxt, /*OUT*/ this->s))) {
00149         this->s = (cpy == (void *)NULL) ? StrCopy(str) : str;
00150         bool inTbl = tbl->Put(inTxt, this->s); assert(!inTbl);
00151     }
00152     mu.unlock();
00153 }
00154 
00155 void Atom::Init(const char* bytes, int len) throw ()
00156 {
00157     const char *str = StrCopy(bytes, len);
00158     Text inTxt(str);
00159     mu.lock();
00160     if (!(tbl->Get(inTxt, /*OUT*/ this->s))) {
00161         this->s = str;
00162         bool inTbl = tbl->Put(inTxt, this->s); assert(!inTbl);
00163     }
00164     mu.unlock();
00165 }

Generated on Mon May 8 00:48:29 2006 for Vesta by  doxygen 1.4.2