Created
November 17, 2011 06:19
-
-
Save maraigue/1372506 to your computer and use it in GitHub Desktop.
fundoshi.hpp: すでにconstな文字列が確保されているメモリ上の領域に対し、その部分文字列を、メモリを共有したまま別の文字列のごとく扱うためのクラス ※要:C++11(C++0x)対応コンパイラ / こちらもどうぞ https://github.com/maraigue/fundoshi.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _FUNDOSHI_CPP_ | |
#define _FUNDOSHI_CPP_ | |
#include "fundoshi.hpp" | |
namespace fundoshi{ | |
template <class CharType> | |
size_t strlen(const CharType * str){ | |
size_t result = 0; | |
while(*str != 0){ | |
str++; | |
result++; | |
} | |
return result; | |
} | |
FOR_TWO_FUNDOSHI_STRING_TYPES(X, Y) int compare(const X & str1, const Y & str2){ | |
size_t min_length = (str1.length() < str2.length() ? str1.length() : str2.length()); | |
for(size_t i = 0; i < min_length; i++){ | |
if(str1[i] < str2[i]){ | |
return -1; | |
}else if(str1[i] > str2[i]){ | |
return 1; | |
} | |
} | |
// if all characters are compared | |
if(str1.length() < str2.length()){ | |
return -1; | |
}else if(str1.length() > str2.length()){ | |
return 1; | |
} | |
return 0; | |
} | |
// ---------- basic_string ---------- | |
template <class CharType> | |
basic_string<CharType>::basic_string(const CharType * newstr){ | |
buffer = newstr; | |
buffer_length = strlen(buffer); | |
} | |
template <class CharType> | |
basic_string<CharType>::basic_string(const std::basic_string<CharType> & newstr){ | |
buffer = newstr.c_str(); | |
buffer_length = newstr.length(); | |
} | |
template <class CharType> | |
const CharType * basic_string<CharType>::c_str(void) const{ | |
return buffer; | |
} | |
template <class CharType> | |
size_t basic_string<CharType>::length(void) const{ | |
return buffer_length; | |
} | |
template <class CharType> | |
CharType basic_string<CharType>::operator [](size_t pos) const{ | |
return buffer[pos]; | |
} | |
// ---------- allocated_basic_string ---------- | |
template <class CharType> | |
allocated_basic_string<CharType>::allocated_basic_string(){ | |
pmemory = memory_ptr_type(new std::basic_string<CharType>); | |
} | |
template <class CharType> | |
allocated_basic_string<CharType>::allocated_basic_string(const CharType * newstr, size_t newstr_length){ | |
pmemory = memory_ptr_type(new std::basic_string<CharType>(newstr, newstr_length)); | |
} | |
template <class CharType> | |
allocated_basic_string<CharType>::allocated_basic_string(const CharType * newstr){ | |
pmemory = memory_ptr_type(new std::basic_string<CharType>(newstr)); | |
} | |
template <class CharType> | |
allocated_basic_string<CharType>::allocated_basic_string(const std::basic_string<CharType> & newstr){ | |
pmemory = memory_ptr_type(new std::basic_string<CharType>(newstr)); | |
} | |
template <class CharType> | |
const CharType * allocated_basic_string<CharType>::c_str(void) const{ | |
return pmemory->c_str(); | |
} | |
template <class CharType> | |
size_t allocated_basic_string<CharType>::length(void) const{ | |
return pmemory->length(); | |
} | |
template <class CharType> | |
CharType allocated_basic_string<CharType>::operator [](size_t pos) const{ | |
return (*pmemory)[pos]; | |
} | |
}; | |
FOR_FUNDOSHI_STRING_TYPE(X) std::ostream& operator <<(std::ostream & os, const X & str){ | |
for(size_t i = 0; i < str.length(); i++){ | |
os << str[i]; | |
} | |
return os; | |
} | |
#endif // _FUNDOSHI_CPP_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _FUNDOSHI_HPP_ | |
#define _FUNDOSHI_HPP_ | |
#include <string> | |
#include <cstring> | |
#include <boost/shared_ptr.hpp> | |
#define FOR_FUNDOSHI_STRING_TYPE(x) \ | |
template <class x, class DUMMY = typename x::is_fundoshi_string> | |
#define FOR_TWO_FUNDOSHI_STRING_TYPES(x, y) \ | |
template <class x, class y, \ | |
class DUMMY1 = typename x::is_fundoshi_string, class DUMMY2 = typename y::is_fundoshi_string> | |
// すでにconstな文字列が確保されているメモリ上の領域に対し、 | |
// その部分文字列を、メモリを共有したまま別の文字列のごとく扱うためのクラス。 | |
// 名前の由来は「人のふんどしで相撲を取る」より。 | |
// | |
// 例えば、x = std::string("abcde"); y = x.substr(1, 3); のように部分文字列を | |
// 取得してもよいのだが、その場合新たなstringインスタンスが生成されてしまう。 | |
// そうする必要がない場合、y = fundoshi::string(&(x[1]), 3); とすることで、 | |
// 文字列のメモリをxと共有したまま、yにxの部分文字列を表現させることができる。 | |
// | |
// APIはC++標準のstring(basic_string)に似せてあります。が最小限の内容しか実装していません。 | |
namespace fundoshi{ | |
template <class CharType> | |
size_t strlen(const CharType * str); | |
FOR_TWO_FUNDOSHI_STRING_TYPES(X, Y) int compare(const X & str1, const Y & str2); | |
// ---------- basic_string ---------- | |
template <class CharType> | |
class basic_string{ | |
private: | |
const CharType * buffer; | |
size_t buffer_length; | |
public: | |
struct is_fundoshi_string{}; // dummy | |
basic_string() : buffer(NULL), buffer_length(0) {} | |
basic_string(const CharType * newstr, size_t newstr_length) : buffer(newstr), buffer_length(newstr_length) {} | |
basic_string(const CharType * newstr); | |
basic_string(const std::basic_string<CharType> & newstr); | |
const CharType * c_str(void) const; | |
size_t length(void) const; | |
CharType operator [](size_t pos) const; | |
FOR_FUNDOSHI_STRING_TYPE(X) bool operator ==(const X & other) const { | |
return compare(*this, other) == 0; } | |
FOR_FUNDOSHI_STRING_TYPE(X) bool operator < (const X & other) const { | |
return compare(*this, other) < 0; } | |
FOR_FUNDOSHI_STRING_TYPE(X) bool operator <=(const X & other) const { | |
return compare(*this, other) <= 0; } | |
FOR_FUNDOSHI_STRING_TYPE(X) bool operator > (const X & other) const { | |
return compare(*this, other) > 0; } | |
FOR_FUNDOSHI_STRING_TYPE(X) bool operator >=(const X & other) const { | |
return compare(*this, other) >= 0; } | |
}; | |
typedef basic_string<char> string; | |
typedef basic_string<wchar_t> wstring; | |
// ---------- allocated_basic_string ---------- | |
// fundoshi::stringは、文字列の領域をfundoshi側には確保しない一方、 | |
// fundoshi::astringは、与えられた文字列の領域をコピーして確保しておく。 | |
// fundoshi::basic_stringを継承している。 | |
template <class CharType> | |
class allocated_basic_string{ | |
private: | |
typedef boost::shared_ptr< std::basic_string<CharType> > memory_ptr_type; | |
memory_ptr_type pmemory; | |
public: | |
struct is_fundoshi_string{}; // dummy | |
allocated_basic_string(); | |
allocated_basic_string(const CharType * newstr, size_t newstr_length); | |
allocated_basic_string(const CharType * newstr); | |
allocated_basic_string(const std::basic_string<CharType> & newstr); | |
const CharType * c_str(void) const; | |
size_t length(void) const; | |
CharType operator [](size_t pos) const; | |
FOR_FUNDOSHI_STRING_TYPE(X) bool operator ==(const X & other) const { | |
return compare(*this, other) == 0; } | |
FOR_FUNDOSHI_STRING_TYPE(X) bool operator < (const X & other) const { | |
return compare(*this, other) < 0; } | |
FOR_FUNDOSHI_STRING_TYPE(X) bool operator <=(const X & other) const { | |
return compare(*this, other) <= 0; } | |
FOR_FUNDOSHI_STRING_TYPE(X) bool operator > (const X & other) const { | |
return compare(*this, other) > 0; } | |
FOR_FUNDOSHI_STRING_TYPE(X) bool operator >=(const X & other) const { | |
return compare(*this, other) >= 0; } | |
}; | |
typedef allocated_basic_string<char> astring; | |
typedef allocated_basic_string<wchar_t> awstring; | |
}; | |
FOR_FUNDOSHI_STRING_TYPE(X) std::ostream& operator <<(std::ostream & os, const X & str); | |
#include "fundoshi.cpp" // Because this library is not for solely compiled | |
#endif // _FUNDOSHI_HPP_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "fundoshi.hpp" | |
#include <iostream> | |
#include <string> | |
int main(void){ | |
fundoshi::string fs; | |
// const char *からfundoshi::stringを生成する例 | |
fs = fundoshi::string("abcde"); | |
std::cout << fs.length() << std::endl; // 5 が表示される | |
std::cout << fs[0] << std::endl; // a が表示される | |
std::cout << fs[2] << std::endl; // c が表示される | |
// std::stringからfundoshi::stringを生成する例 | |
std::string x("abcde"); | |
fs = fundoshi::string(x); | |
std::cout << fs.length() << std::endl; // 5 が表示される | |
std::cout << fs[0] << std::endl; // a が表示される | |
std::cout << fs[2] << std::endl; // c が表示される | |
// std::stringのインスタンスとメモリを共有したまま、 | |
// それの部分文字列に相当するfundoshi::stringを生成する例 | |
fs = fundoshi::string(&(x[1]), 3); // ここで、yは「"bcd"」を表している | |
std::cout << fs.length() << std::endl; // 3 が表示される | |
std::cout << fs[0] << std::endl; // b が表示される | |
std::cout << fs[2] << std::endl; // d が表示される | |
// fundoshiにはwstringも存在する | |
fundoshi::wstring fws(L"vwxyz"); | |
std::cout << fws.length() << std::endl; // 5 が表示される | |
std::cout << fws[0] << std::endl; // vのASCIIコード(118)が表示される | |
std::cout << fws[2] << std::endl; // xのASCIIコード(120)が表示される | |
// charやwchar_t以外も使える | |
int y[10] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; | |
fundoshi::basic_string<int> fi(y, 10); | |
std::cout << fi.length() << std::endl; // 10 が表示される | |
std::cout << fi[5] << std::endl; // 25 が表示される | |
std::cout << fi[8] << std::endl; // 64 が表示される | |
// 文字列比較 | |
fundoshi::string fs2; | |
std::cout << "string comparison" << std::endl; | |
fs = fundoshi::string("abc"); | |
fs2 = fundoshi::string("abc"); | |
std::cout << (fs == fs2); // 1が表示される | |
std::cout << (fs > fs2); // 0が表示される | |
std::cout << (fs >= fs2); // 1が表示される | |
std::cout << (fs < fs2); // 0が表示される | |
std::cout << (fs <= fs2); // 1が表示される | |
std::cout << std::endl; | |
fs2 = fundoshi::string("adc"); | |
std::cout << (fs == fs2); // 0が表示される | |
std::cout << (fs > fs2); // 0が表示される | |
std::cout << (fs >= fs2); // 0が表示される | |
std::cout << (fs < fs2); // 1が表示される | |
std::cout << (fs <= fs2); // 1が表示される | |
std::cout << std::endl; | |
fs2 = fundoshi::string("ab"); | |
std::cout << (fs == fs2); // 0が表示される | |
std::cout << (fs > fs2); // 1が表示される | |
std::cout << (fs >= fs2); // 1が表示される | |
std::cout << (fs < fs2); // 0が表示される | |
std::cout << (fs <= fs2); // 0が表示される | |
std::cout << std::endl; | |
fs2 = fundoshi::string("abcd"); | |
std::cout << (fs == fs2); // 0が表示される | |
std::cout << (fs > fs2); // 0が表示される | |
std::cout << (fs >= fs2); // 0が表示される | |
std::cout << (fs < fs2); // 1が表示される | |
std::cout << (fs <= fs2); // 1が表示される | |
std::cout << std::endl; | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "fundoshi.hpp" | |
fundoshi::astring test1(void){ | |
std::string hoge("hoge"); | |
return fundoshi::astring(hoge); | |
} | |
fundoshi::string test2(void){ | |
std::string hoge("hoge"); | |
return fundoshi::string(hoge); | |
} | |
#include <iostream> | |
using namespace std; | |
int main(void){ | |
fundoshi::astring fas = test1(); | |
cout << fas << endl; | |
fundoshi::string fus = test2(); | |
cout << fus << endl; | |
cout << (fas == fus) << endl; | |
cout << (fus == fas) << endl; | |
// cout << (fus == 2) << endl; // これはコンパイルエラー | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "fundoshi.hpp" | |
#include <iostream> | |
#include <map> | |
#include <string> | |
// 与えられた文字列に対し、「どの単語が何番目にあるか」を示す | |
// 連想配列を生成したい。 | |
// 例えば | |
// std::string text = "I love C++"; | |
// という文字列があったとき、 | |
// data["I"] == 0; | |
// data["love"] == 1; | |
// data["C++"] == 2; | |
// としたい。 | |
void position(const std::string & str, | |
std::map<fundoshi::string, size_t> & result){ | |
size_t number = 0, begin_pos = 0, end_pos; | |
result.clear(); | |
for(;;){ | |
end_pos = str.find(' ', begin_pos); | |
if(end_pos == std::string::npos){ | |
result[fundoshi::string(&(str[begin_pos]))] = number; | |
break; | |
}else{ | |
result[fundoshi::string(&(str[begin_pos]), | |
end_pos - begin_pos)] = number; | |
} | |
begin_pos = end_pos + 1; | |
number++; | |
} | |
} | |
int main(void){ | |
std::map<fundoshi::string, size_t> result; | |
position("I love C++", result); | |
std::cout << result["I"] << std::endl; // 0 | |
std::cout << result["C++"] << std::endl; // 2 | |
std::cout << result["love"] << std::endl; // 1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment