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

TextGC.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 Apr 17 22:50:33 EDT 2005 by ken@xorian.net        
00020 //      modified on Sun Jul 28 11:32:19 EDT 2002 by lken@remote.xorian.net
00021 //      modified on Fri Jan  3 19:05:26 PST 1997 by heydon 
00022 
00023 /* This is the Text implementation that *is* linked with a garbage
00024    collector. Hence, none of its methods deallocates any memory. */
00025 
00026 #include "Basics.H"
00027 #include "Text.H"
00028 
00029 #include "TextCommon.C"
00030 
00031 bool Text::GCImpl() throw () { return true; }
00032 
00033 /* This is an implementation of the Text interface that relies for its
00034    correctness on being linked with a garbage collector. When one text is
00035    assigned from another the underlying string pointer is copied, rather than
00036    the bytes of the string itself. Conversly, when a (char *) is incorporated
00037    into a Text, it's bytes must be copied, since those bytes aren't guaranteed
00038    to reside on the heap (and hence, to be under the control of the
00039    collector). */
00040 
00041 static const char *StrConcat(const char *str1, const char *str2,
00042   bool str1mutable, bool str2mutable) throw ()
00043 /* Return a newly allocated null-terminated string containing the
00044    concatenation of the null-terminated strings "str1" and "str2". In the
00045    event that either "str1" or "str2" is empty, simply return the other
00046    string. In that case, the corresponding "str?mutable" argument is
00047    consulted to see if the string needs to be copied first. */
00048 {
00049     // Note: null terminator is only included in second string
00050     int len1 = strlen(str1), len2 = strlen(str2);
00051     char *res;
00052     if (len1 == 0) {
00053         return (str2mutable ? StrCopy(str2, len2) : str2);
00054     } else if (len2 == 0) {
00055         return (str1mutable ? StrCopy(str1, len1) : str1);
00056     } else {
00057         char *res = NEW_PTRFREE_ARRAY(char, len1 + len2 + 1);
00058         memcpy(res, str1, len1);
00059         memcpy(res + len1, str2, len2 + 1);
00060         return res;
00061     }
00062 }
00063 
00064 // constructor from Text
00065 Text::Text(const Text& t) throw ()
00066 {
00067     this->s = t.s;
00068 }
00069 
00070 // keep a global cache of one-char texts
00071 char *CharTexts[256] = { (char *)NULL, };
00072 
00073 Text::Text(const char c) throw ()
00074 {
00075   // If we say c < 256, the GNU compiler complains that the comparison
00076   // is always 1.
00077   assert(0 <= c && (c * sizeof(CharTexts[0])) < sizeof(CharTexts));
00078 
00079     if (CharTexts[c] == NULL) {
00080         char *temp = NEW_PTRFREE_ARRAY(char, 2);
00081         temp[0] = c; temp[1] = '\0';
00082         CharTexts[c] = temp;
00083     }
00084     this->s = CharTexts[c];
00085 }
00086 
00087 // destructor
00088 Text::~Text() throw () { /* SKIP */ }
00089 
00090 // assignment
00091 Text& Text::operator = (const char* str) throw ()
00092 {
00093     this->s = StrCopy(str);
00094     return *this;
00095 }
00096 
00097 Text& Text::operator = (const Text& t) throw ()
00098 {
00099     this->s = t.s;
00100     return *this;
00101 }
00102 
00103 // comparison
00104 bool operator == (const Text& t1, const Text& t2) throw ()
00105 {
00106     bool res;
00107     if (t1.s == t2.s) return true;
00108     if (res = (strcmp(t1.s, t2.s) == 0)) {
00109         // This is a benevolent side-effect on the argument "t2",
00110         // so we cast away the fact that it is "const".
00111         ((Text&) t2).s = t1.s;
00112     }
00113     return res;
00114 }
00115 
00116 bool operator != (const Text& t1, const Text& t2) throw ()
00117 {
00118     bool res;
00119     if (t1.s == t2.s) return false;
00120     if (!(res = (strcmp(t1.s, t2.s) != 0))) {
00121         // This is a benevolent side-effect on the argument "t2",
00122         // so we cast away the fact that it is "const".
00123         ((Text&) t2).s = t1.s;
00124     }
00125     return res;
00126 }
00127 
00128 // concatenation
00129 Text operator + (const Text& t1, const Text& t2) throw ()
00130 {
00131     return Text(StrConcat(t1.s, t2.s, false, false), /*copy=*/ (void*)1);
00132 }
00133 
00134 Text operator + (const char* str, const Text& t) throw ()
00135 {
00136     return Text(StrConcat(str, t.s, true, false), /*copy=*/ (void*)1);
00137 }
00138 
00139 Text operator + (const Text& t, const char* str) throw ()
00140 {
00141     return Text(StrConcat(t.s, str, false, true), /*copy=*/ (void*)1);
00142 }
00143 
00144 // append
00145 Text& Text::operator += (const char* str) throw ()
00146 {
00147     this->s = StrConcat(this->s, str, false, true);
00148     return *this;
00149 }
00150 
00151 Text& Text::operator += (const Text& t) throw ()
00152 {
00153     this->s = StrConcat(this->s, t.s, false, false);
00154     return *this;
00155 }

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