ここでは、ソースのみ記載します。

ソースの説明はこちら を参照ください。

※昔に書いたソースの修正版です。(クラス名とクラス構成を変更しました)


※注意
下の方に2ファイル目もありますので、忘れずにコピーしてください。




MCharIterator.hppファイル


#ifndef __MCHAR_ITERATOR_H__
#define __MCHAR_ITERATOR_H__


#include <cstdlib>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <sstream>
#include <string.h>
#include <functional>

#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>



namespace nana{

using namespace std;
using namespace boost;


//-----------------------------------
class MChar;

//


/**
文字コードを表す基底クラス 。
*/
class CharSet : noncopyable{
public:
enum Type{ NONE_KIND=-1, ASCII, KANJI, KANA };

///
virtual ~CharSet(){};

/**
次の1文字の長さを計算する。(文字コードの特徴が表れる)
@param p [in]次の文字の先頭ポインタ
@param now_type [in]今の文字のタイプ
@n [out]次の文字のタイプを返す
@return 次の文字の長さ
*/
virtual const int calc(const char* p, CharSet::Type& now_type) const =0;

///同じ文字かどうかを比較する
virtual const bool equals(const MChar& m1, const MChar& m2) const;

protected:
CharSet() {};

private:
};


///文字コードのタイプを出力する("ASCII", "KANJI"など)
ostream& operator <<(ostream& out, const CharSet::Type& type);


/**
CharSet のデフォルトを扱うクラス。
*/
class CharSetDefault{
public:
static const CharSet* get()
{ return defaultCharSet; };

static void set(const CharSet* p)
{ defaultCharSet = p; };

protected:
CharSetDefault(){};
static const CharSet* defaultCharSet;
};




//--------------------------------------------------


/**
<pre>
ある文字列のうちのマルチバイト1文字を表す、文字位置参照クラス。
文字の位置と長さと文字コードを内部に持つ。

【注意点】
このクラスは参照を作るだけなので、参照する文字列が破壊されると動作不確定になるので
このクラスを使用する間は参照文字列が破壊されないようにすること。

【使用例】
const char* str1 = "abcdあいうef";
const char* str2 = "a";
MChar m1(str1, getCharSet("sjis"));
MChar m2(str2, getCharSet("sjis"));
//比較
if(m1 == m2) cout << "true";
//代入
m2 = m1.next();
//次の文字へ移動
++m1;
cout << m1 << endl; //"b"
</pre>
*/
class MChar
{
public:
///
explicit MChar(const CharSet* charSet)
: m_len(0), m_type(CharSet::NONE_KIND), m_pos(NULL), m_pcharSet(charSet)
{};

///
MChar(const char* p, const CharSet* charSet)
: m_pcharSet(charSet), m_type(CharSet::NONE_KIND)
{
set(p);
};

///
~MChar(){};


///出力させる
friend ostream& operator << (ostream& out, const MChar& w){
return out.write(w.pos(), w.size());
};

friend string& operator += (string& left, const MChar& w){
return left.append(w.pos(), w.size());
};

///文字列が同じかどうか?
const bool operator == (const MChar& w) const {
return m_pcharSet->equals(*this, w);
};

///文字列のポインタを代入
MChar& operator =(const char* p){
set(p);
return *this;
};

///次の文字に移動する
MChar& operator ++(){
m_pos += m_len;
return reset();
};

///次の文字を取得する
const MChar next() const {
return MChar(m_pos + m_len, m_pcharSet);
}

///1文字をstringにする
const string str() const
{ return string(m_pos, m_len); };

///1文字のサイズを取得
const int& size() const
{ return m_len; };

///1文字のタイプ(派生クラスに定義)を取得
const CharSet::Type& type() const
{ return m_type; };

///現在の位置を取得する
const char* pos() const
{ return m_pos; };

///
const CharSet* charSet() const
{ return m_pcharSet; }

protected:
MChar(){};

///今の位置について文字の長さを計算しなおす
MChar& reset(){
m_len = m_pcharSet->calc(m_pos, m_type);
return *this;
};

void set(const char* p){
if(p == NULL){
m_pos = NULL;
m_len = 0;
m_type= CharSet::NONE_KIND;
}else{
m_pos = p;
reset();
}
}

void set(const char* p, const CharSet* pcharSet){
m_pcharSet = pcharSet;
set(p);
}

private:
//もしメンバーにコピーコンストラクタが必要なときはコンストラクタ作る
int m_len;
CharSet::Type m_type;
const char* m_pos;
const CharSet* m_pcharSet;
};




//イテレータ========================================



/**
文字列を扱うイテレータ。
文字列の長さは、 MChar が計算する。
Iterator [in]char*とstring::const_iteratorのみ
*/
template <typename Iterator>
class MCharIterator : public std::iterator<input_iterator_tag, MChar, int>
{
public:
///コンストラクタ
MCharIterator(const Iterator& begin, const Iterator& end, const CharSet* pcharset)
: m_endPos(&*end), m_mchar(&*begin, pcharset)
{
};

///endイテレータを作る
MCharIterator()
: m_endPos(NULL), m_mchar(&*CharSetDefault::get())
{};

///
const MChar& operator *() const { return m_mchar; };

///実体参照
const MChar* operator ->() const { return &m_mchar; };

///1つ次へ進める
MCharIterator& operator ++()
{
if(isEnd()) return *this;
++m_mchar;
return *this;
};

///等価演算子
bool operator ==(const MCharIterator& ite) const {
if(isEnd() != ite.isEnd()) return false;
if(isEnd() && ite.isEnd()) return true;
return (m_mchar == ite.m_mchar);
};

///否定演算子
bool operator !=(const MCharIterator& ite) const {
return !(*this == ite);
};

///代入
//void appendByte(const int& n){ m_mchar = m_mchar.pos() + n; };
void set(const char* p){ m_mchar = p; };

protected:
///終了の位置かどうか。m_curPos == m_endのときtrue
const bool isEnd() const {
return (m_mchar.pos()==NULL || m_mchar.pos() >= m_endPos);
};

private:
MChar m_mchar;
const char* m_endPos;
};




//================================================


//MCharIterator作成のためのヘルパー---------------------

//型宣言-----------
//イテレータ型
typedef MCharIterator<const char*> CharMCharIterator;
typedef MCharIterator<string::const_iterator> StringMCharIterator;



/**
CharMCharIteratorのコンストラクタの記述を短くするための関数。
*/
inline CharMCharIterator mcharIterator(const char* str,
const CharSet* pcharset = &*CharSetDefault::get())
{
return CharMCharIterator(str, str+strlen(str), pcharset);
};


/**
StringMCharIteratorのコンストラクタの記述を短くするための関数。
*/
inline StringMCharIterator mcharIterator(const string& str,
const CharSet* pcharset = &*CharSetDefault::get())
{
return StringMCharIterator(str.begin(), str.end(), pcharset);
};


}; //namespace nana

#endif









MCharIterator.cppファイル

#include "MCharIterator.hpp"



namespace nana{

using namespace std;
using namespace boost;



//CharSet-----------------------------------------------
const bool CharSet::equals(const MChar& m1, const MChar& m2) const{
if(m1.size() != m2.size()) return false;
if(m1.pos() == m2.pos()) return true;
if(m1.pos() == NULL || m2.pos() == NULL) return false;
return (strncmp(m1.pos(), m2.pos(), m1.size()) == 0);
};


//文字タイプを出力する
ostream& operator <<(ostream& out, const CharSet::Type& type){
switch(type){
case CharSet::NONE_KIND:
out << "NONE";
break;
case CharSet::ASCII:
out << "ASCII";
break;
case CharSet::KANJI:
out << "KANJI";
break;
case CharSet::KANA:
out << "KANA";
break;
default:
out << "?";
break;
}
return out;
};


}; //namespace nana{