Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@maraigue
Created November 17, 2011 06:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maraigue/1372506 to your computer and use it in GitHub Desktop.
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
#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_
#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_
#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;
}
#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; // これはコンパイルエラー
}
#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