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

Character.cc

Go to the documentation of this file.
00001 /*
00002  * Character.cc
00003  *
00004  * Smalltalk like class library for C++
00005  * Character wrapper.
00006  *
00007  * Copyright (c) 2003-5 Milan Cermak
00008  */
00009 /*
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  */
00024 #include <stlib/Character.h>
00025 #include <stlib/Association.h>
00026 #include <stlib/Dictionary.h>
00027 #include <stlib/Integer.h>
00028 #include <stlib/String.h>
00029 #include <stlib/Stream.h>
00030 #include <stlib/Visitor.h>
00031 
00032 #include <ctype.h>
00033 
00034 Dictionary *Character::character_store = nil;
00035 
00036 Character::Character(unsigned long val)
00037 {
00038     _value = val;
00039 }
00040 
00041 /* Class-accessing protocol */
00042 String *Character::className(void) const
00043 {
00044     return new String("Character");
00045 }
00046 
00047 Dictionary *Character::characterStore(void)
00048 {
00049     if (character_store == nil)
00050         character_store = new Dictionary(128);
00051     return character_store;
00052 }
00053 
00054 /* Class-constants protocol */
00055 Character *Character::cr(void)
00056 {
00057     return value('\r');
00058 }
00059 
00060 Character *Character::lf(void)
00061 {
00062     return value('\n');
00063 }
00064 
00065 Character *Character::space(void)
00066 {
00067     return value(32);
00068 }
00069 
00070 Character *Character::tab(void)
00071 {
00072     return value('\t');
00073 }
00074 
00075 /* Instance creation protocol */
00076 Character *Character::value(unsigned long val)
00077 {
00078     return Character::value(Integer::value(val));
00079 }
00080 
00081 Character *Character::value(Integer *val)
00082 {
00083     /* Can't use Dictionary>>#at:ifAbsent: method 'cause it raises exception
00084        that may need to construct more Characters. */
00085     Character *chr;
00086     int index = characterStore()->findKeyOrNil(val);
00087     if (characterStore()->isEmptyAt(index)) {
00088         /* Need to construct new one */
00089         chr = new Character(val->asUnsignedLong());
00090         characterStore()->atNewIndexPut(index, new Association(val, chr));
00091     } else {
00092         /* OK now. Sure it's there. */
00093         Association *assoc = dynamic_cast<Association *>(characterStore()->privAtIndex(index));
00094         chr = dynamic_cast<Character *>(assoc->value());
00095     }
00096     return chr;
00097 }
00098 
00099 /* Accessing protocol */
00100 int Character::byteSize(void)
00101 {
00102     if (_value < 256) return 1;
00103     if (_value < 65536) return 2;
00104     return 4;
00105 }
00106 
00107 int Character::digitValue(void)
00108 {
00109     int code = asInteger();
00110     int val = code - '0';
00111     if (val <= 9) return val;
00112     val = code - 'A';
00113     if (val >= 0 && val < 26) return val + 10;
00114     val = code - 'a';
00115     if (val >= 0 && val < 26) return val + 10;
00116     return -1;
00117 }
00118 
00119 /* Comparing protocol */
00120 long Character::hash(void) const
00121 {
00122     return (long) _value;
00123 }
00124 
00125 bool Character::isEqual(const Object *object) const
00126 {
00127     if (object == nil) return false;
00128 
00129     return object->isCharacter() &&
00130            _value == ((Character *) object)->_value;
00131 }
00132 
00133 bool Character::isEqual(char cChar) const
00134 {
00135     return _value == cChar;
00136 }
00137 
00138 /* Converting protocol */
00139 unsigned long Character::asInteger(void)
00140 {
00141     return _value;
00142 }
00143 
00144 Character *Character::asLowercase(void)
00145 {
00146     return value(tolower(_value));
00147 }
00148 
00149 Character *Character::asUppercase(void)
00150 {
00151     return value(toupper(_value));
00152 }
00153 
00154 /* Printing protocol */
00155 void Character::printOn(Stream *stream) const
00156 {
00157     stream->nextPut('\'');
00158     stream->nextPut(_value);
00159     stream->nextPutAll("\' /* ");
00160     stream->nextPutAll(String::format("0x%02X", _value));
00161     stream->nextPutAll(" */");
00162 }
00163 
00164 /* Testing protocol */
00165 bool Character::isCharacter(void) const
00166 {
00167     return true;
00168 }
00169 
00170 bool Character::isSeparator(void) const
00171 {
00172     return isspace(_value);
00173 }
00174 
00175 bool Character::isVowel(void) const
00176 {
00177     char upperCase = toupper(_value);
00178     return upperCase == 'A' || upperCase == 'E' || upperCase == 'I' ||
00179            upperCase == 'Y' || upperCase == 'O' || upperCase == 'U';
00180 }
00181 
00182 bool Character::isDigit(void) const
00183 {
00184     return isdigit(_value);
00185 }
00186 
00187 bool Character::isLowercase(void) const
00188 {
00189     return islower(_value);
00190 }
00191 
00192 bool Character::isUppercase(void) const
00193 {
00194     return isupper(_value);
00195 }
00196 
00197 /* Visiting protocol */
00198 void Character::visitBy(Visitor *visitor)
00199 {
00200     visitor->visitCharacter(this);
00201 }

Generated on Mon Nov 27 09:47:54 2006 for Smalltalk like C++ Class Library by  doxygen 1.4.2