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

String.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 // Lamp : Open source game middleware
00003 // Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
00004 //
00005 // This library 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 // This library 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 this library; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //------------------------------------------------------------------------------
00019 
00020 /** @file
00021  * 文字列実装
00022  * @author Junpee
00023  */
00024 
00025 #include "LampBasic.h"
00026 #include "Core/Primitive/String.h"
00027 #include "Core/System/StringMethod.h"
00028 
00029 namespace Lamp{
00030 
00031 //------------------------------------------------------------------------------
00032 // ユーティリティ関数
00033 //------------------------------------------------------------------------------
00034 /**
00035  * 新しい文字列の作成
00036  * @param length 文字列長
00037  * @return 文字列
00038  */
00039 inline static char* newString(int length){
00040     char* returnString = new char[sizeof(int) + length + 1];
00041     // リファレンスカウンタに1を設定
00042     *(int*)returnString = 1;
00043     returnString += sizeof(int);
00044     return returnString;
00045 }
00046 //------------------------------------------------------------------------------
00047 /**
00048  * 文字列の解放
00049  * @param string 解放する文字列
00050  * @return リファレンスカウンタ
00051  */
00052 inline static int releaseString(char** string){
00053     if((*string) != NULL){
00054         // リファレンスカウンタデクリメント
00055         int* refCount = (int*)((*string) - sizeof(int));
00056         (*refCount) -= 1;
00057         int returnCount = *refCount;
00058         if(returnCount == 0){ delete[] refCount; }
00059         (*string) = NULL;
00060         return returnCount;
00061     }
00062     return 0;
00063 }
00064 //------------------------------------------------------------------------------
00065 /**
00066  * リファレンスカウンタの追加
00067  * @param string リファレンスを追加する文字列
00068  * @return リファレンスカウンタ
00069  */
00070 inline static int addReferenceCounter(char* string){
00071     // リファレンスカウンタをインクリメント
00072     int* counterAddress = (int*)(string - sizeof(int));
00073     *counterAddress += 1;
00074     return *counterAddress;
00075 }
00076 //------------------------------------------------------------------------------
00077 /**
00078  * リファレンスカウンタの取得
00079  * @param string リファレンスカウンタを取得する文字列
00080  * @return リファレンスカウンタ
00081  */
00082 inline static int getReferenceCounter(char* string){
00083     return *(int*)(string - sizeof(int));
00084 }
00085 //------------------------------------------------------------------------------
00086 // 文字列の構築、破棄
00087 //------------------------------------------------------------------------------
00088 // コンストラクタ
00089 String::String() : string_(NULL), size_(0){
00090 }
00091 //------------------------------------------------------------------------------
00092 // コンストラクタ
00093 String::String(const char* initString){
00094     if(initString == NULL){
00095         string_ = NULL;
00096         size_ = 0;
00097         return;
00098     }
00099     size_ = (int)StdStrlen(initString);
00100     Assert(size_ >= 0);
00101     if(size_ == 0){
00102         string_ = NULL;
00103         return;
00104     }
00105     string_ = newString(size_);
00106     StdStrcpy(string_, initString);
00107 }
00108 //------------------------------------------------------------------------------
00109 // コピーコンストラクタ
00110 String::String(const String& copy){
00111     size_ = copy.getSize();
00112     Assert(size_ >= 0);
00113     if(size_ == 0){
00114         string_ = NULL;
00115         return;
00116     }
00117     string_ = copy.string_;
00118     addReferenceCounter(string_);
00119 }
00120 //------------------------------------------------------------------------------
00121 // 内部使用コンストラクタ
00122 String::String(char* initString, int initLength){
00123     Assert(initString != NULL);
00124     Assert(initLength >= 0);
00125     string_ = initString;
00126     size_ = initLength;
00127 }
00128 //------------------------------------------------------------------------------
00129 // 代入演算子
00130 String& String::operator =(const String& copy){
00131     // 自分自身ならリターン
00132     if(this == &copy){ return *this; }
00133     releaseString(&string_);
00134     size_ = copy.getSize();
00135     Assert(size_ >= 0);
00136     if(size_ == 0){
00137         string_ = NULL;
00138         return *this;
00139     }
00140     string_ = copy.string_;
00141     addReferenceCounter(string_);
00142     return *this;
00143 }
00144 //------------------------------------------------------------------------------
00145 // 代入演算子
00146 String& String::operator =(const char* copy){
00147     releaseString(&string_);
00148     if(copy == NULL){
00149         string_ = NULL;
00150         size_ = 0;
00151         return *this;
00152     }
00153     size_ = (int)StdStrlen(copy);
00154     Assert(size_ >= 0);
00155     if(size_ == 0){
00156         string_ = NULL;
00157         return *this;
00158     }
00159     string_ = newString(size_);
00160     StdStrcpy(string_, copy);
00161     return *this;
00162 }
00163 //------------------------------------------------------------------------------
00164 // デストラクタ
00165 String::~String(){
00166     releaseString(&string_);
00167 }
00168 //------------------------------------------------------------------------------
00169 // 文字列の情報を取得する
00170 //------------------------------------------------------------------------------
00171 // 文字数を返す
00172 int String::getCharacterCount() const{
00173     return (int)StdMbslen(getBytes());
00174 }
00175 //------------------------------------------------------------------------------
00176 // 部分文字列の取得
00177 String String::getSubstring(int beginIndex) const{
00178     if(beginIndex == 0){ return *this; }
00179     Assert(beginIndex >= 0);
00180     Assert((beginIndex <= size_));
00181     // 空文字列になる
00182     if(beginIndex == size_){ return String(); }
00183     int newLength = size_ - beginIndex;
00184     char* newArray = newString(newLength);
00185     StdStrcpy(newArray, string_ + beginIndex);
00186     return String(newArray, newLength);
00187 }
00188 //------------------------------------------------------------------------------
00189 // 部分文字列の取得
00190 String String::getSubstring(int beginIndex, int endIndex) const{
00191     Assert(beginIndex >= 0);
00192     Assert(endIndex >= 0);
00193     Assert((endIndex <= size_));
00194     Assert((beginIndex <= endIndex));
00195     // 空文字列になる
00196     if(beginIndex == endIndex){ return String(); }
00197     int newLength = endIndex - beginIndex;
00198     char* newArray = newString(newLength);
00199     for(int i = 0; i < newLength; i++){
00200         newArray[i] = string_[i + beginIndex];
00201     }
00202     newArray[newLength] = '\0';
00203     return String(newArray, newLength);
00204 }
00205 //------------------------------------------------------------------------------
00206 // 大文字化した文字列の取得
00207 String String::getUpperCase() const{
00208     // コピーを作成する必要がある
00209     String returnString(this->getBytes());
00210     if(returnString.getSize() == 0){ return returnString; }
00211     StdStrupr(returnString.string_);
00212     return returnString;
00213 }
00214 //------------------------------------------------------------------------------
00215 // 小文字化した文字列の取得
00216 String String::getLowerCase() const{
00217     // コピーを作成する必要がある
00218     String returnString(this->getBytes());
00219     if(returnString.getSize() == 0){ return returnString; }
00220     StdStrlwr(returnString.string_);
00221     return returnString;
00222 }
00223 //------------------------------------------------------------------------------
00224 // ハッシュコードの取得
00225 u_int String::getHashCode() const{
00226     u_int hashCode = 0;
00227     if(size_ == 0){ return hashCode; }
00228     const char* position = getBytes();
00229     for(int i = 0;i < size_;i++){
00230         hashCode = hashCode * 31 + position[i];
00231     }
00232     return hashCode;
00233 }
00234 //------------------------------------------------------------------------------
00235 // 文字列をパースする
00236 //------------------------------------------------------------------------------
00237 // charへのパース
00238 bool String::parseChar(char* value) const{
00239     Assert(value != NULL);
00240     int scanValue;
00241     int scanCount = StdSscanf(string_, "%d", &scanValue);
00242     if((scanCount == 1) &&
00243         (scanValue <= Limit::charMax) && (scanValue >= Limit::charMin)){
00244         *value = (char)scanValue;
00245         return true;
00246     }
00247     return false;
00248 }
00249 //------------------------------------------------------------------------------
00250 // u_charへのパース
00251 bool String::parseUChar(u_char* value) const{
00252     Assert(value != NULL);
00253     int scanValue;
00254     int scanCount = StdSscanf(string_, "%d", &scanValue);
00255     if((scanCount == 1) &&
00256         (scanValue <= Limit::uCharMax) && (scanValue >= Limit::uCharMin)){
00257         *value = (u_char)scanValue;
00258         return true;
00259     }
00260     return false;
00261 }
00262 //------------------------------------------------------------------------------
00263 // shortへのパース
00264 bool String::parseShort(short* value) const{
00265     Assert(value != NULL);
00266     int scanValue;
00267     int scanCount = StdSscanf(string_, "%d", &scanValue);
00268     if((scanCount == 1) &&
00269         (scanValue <= Limit::shortMax) && (scanValue >= Limit::shortMin)){
00270         *value = (short)scanValue;
00271         return true;
00272     }
00273     return false;
00274 }
00275 //------------------------------------------------------------------------------
00276 // u_shortへのパース
00277 bool String::parseUShort(u_short* value) const{
00278     Assert(value != NULL);
00279     int scanValue;
00280     int scanCount = StdSscanf(string_, "%d", &scanValue);
00281     if((scanCount == 1) &&
00282         (scanValue <= Limit::uShortMax) && (scanValue >= Limit::uShortMin)){
00283         *value = (u_short)scanValue;
00284         return true;
00285     }
00286     return false;
00287 }
00288 //------------------------------------------------------------------------------
00289 // intへのパース
00290 bool String::parseInt(int* value) const{
00291     Assert(value != NULL);
00292     int scanCount = StdSscanf(string_, "%d", value);
00293     if(scanCount == 1){ return true; }
00294     return false;
00295 }
00296 //------------------------------------------------------------------------------
00297 // u_intへのパース
00298 bool String::parseUInt(u_int* value) const{
00299     Assert(value != NULL);
00300     int scanCount = StdSscanf(string_, "%u", value);
00301     if(scanCount == 1){ return true; }
00302     return false;
00303 }
00304 //------------------------------------------------------------------------------
00305 // floatへのパース
00306 bool String::parseFloat(float* value) const{
00307     Assert(value != NULL);
00308     int scanCount = StdSscanf(string_, "%f", value);
00309     if(scanCount == 1){ return true; }
00310     return false;
00311 }
00312 //------------------------------------------------------------------------------
00313 // doubleへのパース
00314 bool String::parseDouble(double* value) const{
00315     Assert(value != NULL);
00316     int scanCount = StdSscanf(string_, "%lf", value);
00317     if(scanCount == 1){ return true; }
00318     return false;
00319 }
00320 //------------------------------------------------------------------------------
00321 // 文字列を変更する
00322 //------------------------------------------------------------------------------
00323 // 文字列の追加
00324 String& String::append(const String& appendString){
00325     int appendLength = appendString.getSize();
00326     if(appendLength == 0){ return *this; }
00327     int newLength = size_ + appendLength;
00328     char* newArray = newString(newLength);
00329     if(size_ != 0){ std::memcpy(newArray, string_, size_); }
00330     std::memcpy(newArray + size_, appendString.getBytes(), appendLength);
00331     newArray[newLength] = '\0';
00332     releaseString(&string_);
00333     string_ = newArray;
00334     size_ = newLength;
00335     return *this;
00336 }
00337 //------------------------------------------------------------------------------
00338 // 文字列の追加
00339 String& String::append(const char* appendString){
00340     Assert(appendString != NULL);
00341     int appendLength = (int)StdStrlen(appendString);
00342     if(appendLength == 0){ return *this; }
00343     int newLength = size_ + appendLength;
00344     char* newArray = newString(newLength);
00345     if(size_ != 0){ std::memcpy(newArray, string_, size_); }
00346     std::memcpy(newArray + size_, appendString, appendLength);
00347     newArray[newLength] = '\0';
00348     releaseString(&string_);
00349     string_ = newArray;
00350     size_ = newLength;
00351     return *this;
00352 }
00353 //------------------------------------------------------------------------------
00354 // フォーマット
00355 String& String::format(const char* formatString, ...){
00356     Assert(formatString != NULL);
00357     releaseString(&string_);
00358     // フォーマット文字列が空文字列
00359     if(formatString[0] == '\0'){
00360         string_ = NULL;
00361         size_ = 0;
00362         return *this;
00363     }
00364     int allocateSize = formatDefaultLength;
00365     va_list args;
00366     va_start(args, formatString);
00367     while(true){
00368         int maxLength = allocateSize - sizeof(int) - 1;
00369         string_ = newString(maxLength);
00370         int result = StdVsnprintf(string_, maxLength, formatString, args);
00371         if(result != -1){
00372             size_ = result;
00373             if(size_ == 0){
00374                 releaseString(&string_);
00375             }else{
00376                 // _vsntprintfの指定長丁度だとNULL終端されないので
00377                 string_[size_] = '\0';
00378             }
00379             break;
00380         }
00381         allocateSize *= 2;
00382         releaseString(&string_);
00383     }
00384     va_end(args);
00385     return *this;
00386 }
00387 //------------------------------------------------------------------------------
00388 // 文字列を比較する
00389 //------------------------------------------------------------------------------
00390 // 文字列の辞書式比較
00391 int String::compareTo(const String& compareString) const{
00392     return StdStrcmp(getBytes(), compareString.getBytes());
00393 }
00394 //------------------------------------------------------------------------------
00395 // 文字列の辞書式比較
00396 int String::compareTo(const char* compareString) const{
00397     Assert(compareString != NULL);
00398     return StdStrcmp(getBytes(), compareString);
00399 }
00400 //------------------------------------------------------------------------------
00401 // 大文字、小文字を無視した文字列の辞書式比較
00402 int String::compareToIgnoreCase(const String& compareString) const{
00403     String source = this->getLowerCase();
00404     String destination = compareString.getLowerCase();
00405     return StdStrcmp(source.getBytes(), destination.getBytes());
00406 }
00407 //------------------------------------------------------------------------------
00408 // 文字列の比較
00409 bool String::equals(const String& compareString) const{
00410     return (StdStrcmp(getBytes(), compareString.getBytes()) == 0);
00411 }
00412 //------------------------------------------------------------------------------
00413 // 文字列の比較
00414 bool String::equals(const char* compareString) const{
00415     Assert(compareString != NULL);
00416     return (StdStrcmp(getBytes(), compareString) == 0);
00417 }
00418 //------------------------------------------------------------------------------
00419 // 大文字、小文字を無視した文字列の比較
00420 bool String::equalsIsIgnoreCase(const String& compareString) const{
00421     String source = this->getLowerCase();
00422     String destination = compareString.getLowerCase();
00423     return (StdStrcmp(source.getBytes(), destination.getBytes()) == 0);
00424 }
00425 //------------------------------------------------------------------------------
00426 // 指定した文字列で始まるかどうか
00427 bool String::startsWith(const String& prefix) const{
00428     return (StdStrncmp(getBytes(), prefix.getBytes(), prefix.getSize()) == 0);
00429 }
00430 //------------------------------------------------------------------------------
00431 // 指定した文字列で始まるかどうか
00432 bool String::startsWith(const char* prefix) const{
00433     Assert(prefix != NULL);
00434     return (StdStrncmp(getBytes(), prefix, StdStrlen(prefix)) == 0);
00435 }
00436 //------------------------------------------------------------------------------
00437 // 指定した文字列で終わるかどうか
00438 bool String::endsWith(const String& suffix) const{
00439     int index = size_ - suffix.getSize();
00440     if(index < 0){ return false; }
00441     return (StdStrncmp(getBytes() + index,
00442         suffix.getBytes(), suffix.getSize()) == 0);
00443 }
00444 //------------------------------------------------------------------------------
00445 // 指定した文字列で終わるかどうか
00446 bool String::endsWith(const char* suffix) const{
00447     Assert(suffix != NULL);
00448     int suffixLength = (int)StdStrlen(suffix);
00449     int index = size_ - suffixLength;
00450     if(index < 0){ return false; }
00451     return (StdStrncmp(getBytes() + index, suffix, suffixLength) == 0);
00452 }
00453 //------------------------------------------------------------------------------
00454 // 指定された文字が最初に出現する位置のインデックスを取得
00455 int String::getIndexOf(const char searchChar) const{
00456     char* indexPointer = StdStrchr(getBytes(), searchChar);
00457     if(indexPointer == NULL){ return -1; }
00458     return (int)(indexPointer - getBytes());
00459 }
00460 //------------------------------------------------------------------------------
00461 // 指定された文字列が最初に出現する位置のインデックスを取得
00462 int String::getIndexOf(const char* searchString) const{
00463     Assert(searchString != NULL);
00464     char* indexPointer = StdStrstr(getBytes(), searchString);
00465     if(indexPointer == NULL){ return -1; }
00466     return (int)(indexPointer - getBytes());
00467 }
00468 //------------------------------------------------------------------------------
00469 // 指定された文字列が最初に出現する位置のインデックスを取得
00470 int String::getIndexOf(const String& searchString) const{
00471     char* indexPointer = StdStrstr(getBytes(), searchString.getBytes());
00472     if(indexPointer == NULL){ return -1; }
00473     return (int)(indexPointer - getBytes());
00474 }
00475 //------------------------------------------------------------------------------
00476 // 指定された文字が最後に出現する位置のインデックスを取得
00477 int String::getLastIndexOf(const char searchChar) const{
00478     char* indexPointer = StdStrrchr(getBytes(), searchChar);
00479     if(indexPointer == NULL){ return -1; }
00480     return (int)(indexPointer - getBytes());
00481 }
00482 //------------------------------------------------------------------------------
00483 // 指定された文字列が最後に出現する位置のインデックスを取得
00484 int String::getLastIndexOf(const char* searchString) const{
00485     Assert(searchString != NULL);
00486     if(StdStrlen(searchString) == 0){ return size_; }
00487     const char* indexPointer = NULL;
00488     const char* target = getBytes();
00489     while(true){
00490         target = StdStrstr(target, searchString);
00491         if(target == NULL){ break; }
00492         indexPointer = target;
00493         target++;
00494     }
00495     if(indexPointer == NULL){ return -1; }
00496     return (int)(indexPointer - getBytes());
00497 }
00498 //------------------------------------------------------------------------------
00499 // 指定された文字列が最後に出現する位置のインデックスを取得
00500 int String::getLastIndexOf(const String& searchString) const{
00501     if(searchString.getSize() == 0){ return size_; }
00502     const char* search = searchString.getBytes();
00503     const char* indexPointer = NULL;
00504     const char* target = getBytes();
00505     while(true){
00506         target = StdStrstr(target, search);
00507         if(target == NULL){ break; }
00508         indexPointer = target;
00509         target++;
00510     }
00511     if(indexPointer == NULL){ return -1; }
00512     return (int)(indexPointer - getBytes());
00513 }
00514 //------------------------------------------------------------------------------
00515 #ifdef _DEBUG
00516 // デバッグ用文字列情報出力
00517 void String::debugPrint(){
00518     DebugOut("[%2d] %s\n", getReferenceCounter(string_), string_);
00519 }
00520 #endif// End of _DEBUG
00521 //------------------------------------------------------------------------------
00522 } // End of namespace Lamp
00523 //------------------------------------------------------------------------------
00524 // 文字列の連結
00525 const Lamp::String operator+(
00526     const Lamp::String& leftString, const Lamp::String& rightString){
00527     Lamp::String returnString(leftString);
00528     returnString.append(rightString);
00529     return returnString;
00530 }
00531 //------------------------------------------------------------------------------

Generated on Wed Mar 16 10:29:36 2005 for Lamp by doxygen 1.3.2