OSDN Git Service

<identify>、<number>、<boolean>を解釈するそれぞれの部分字句解析を行うLexerを追加。
[simplecms/utakata.git] / src / unicode.h
1 // utakataで利用される、Unicode文字及び文字列を統合して扱うことが
2 // 可能である、Unicodeオブジェクトを定義します。
3 // UniCharは、Unicode文字1文字に対応し、各種オペレータオーバロードを
4 // 提供し、組込型と同様な利用ができるようになっています。
5 // UniStringは、UniCharを集めたUnicode文字列を表現し、UniChar単位での
6 // 文字列操作を提供します。
7 #ifndef _UTAKATA_SRC_UNICODE_H_
8 #define _UTAKATA_SRC_UNICODE_H_
9
10 #include <vector>
11 #include <algorithm>
12 #include <string>
13 #include "lib/crtp.h"
14 #include "lib/range.h"
15
16 namespace utakata {
17 namespace unicode {
18
19 typedef unsigned int unicode_t;
20
21 // Unicode一文字を表現するためのオブジェクトです。
22 // unicodeはunsigned intで表現され、組込型と同様の利用ができるように
23 // 設計されています。
24 // 各operator overloadは、同様の機能を提供する各関数によって機能が
25 // 実装されており、各operator overloadを利用しないことも可能です。
26 class UniChar : private akebono::crtp::less_than_comparable<UniChar>,
27                 private akebono::crtp::equal_comparable<UniChar> {
28  public:
29
30   // Schemeシステム内で最大値となるUnicode値です。この値以上の
31   // Unicodeは無効です。
32   static const unsigned int kOutOfUnicode = 0x110000;
33   static const unsigned int kExclusionMin = 0xD800;
34   static const unsigned int kExclusionMax = 0xDFFF;
35
36   UniChar() : rawcode_(0x0000) {}
37   virtual ~UniChar() {}
38
39   UniChar(const UniChar& ch) : rawcode_(ch.rawcode_) {}
40   explicit UniChar(unicode_t code) : rawcode_(code) {}
41
42   UniChar& operator=(const UniChar& ch) {
43     UniChar tmp(ch);
44     swap(tmp);
45     return *this;
46   }
47
48   // Equalのコメントを参照してください。
49   bool operator==(const UniChar& code) const {return rawcode_ == code.rawcode_;}
50
51   // Lessのコメントを参照してください。
52   bool operator<(const UniChar& code) const {return rawcode_ < code.rawcode_;}
53
54   // 内部で保持している、実際のunicodeの値を返します。
55   unicode_t rawcode() const {return rawcode_;}
56
57  private:
58
59   // 渡されたchのrawcodeを交換します。
60   void swap(UniChar& ch) {
61     std::swap(rawcode_, ch.rawcode_);
62   }
63
64   unicode_t rawcode_;
65 };
66
67 // 渡されたUniCharが、ascii文字の範囲内である場合、trueを返します。
68 inline bool IsAscii(const UniChar& unichar) {
69   return unichar.rawcode() >= 0 && unichar.rawcode() <= 0x7F;
70 }
71
72 // 渡されたUniCharが、数値項目に該当しているかを返します。
73 inline bool IsNumeric(const UniChar& unichar) {
74   return ('0' <= unichar.rawcode() && unichar.rawcode() <= '9');
75 }
76
77 // 渡されたUniCharが、小文字のアルファベットに該当しているかどうかを返します。
78 inline bool IsAlphabetUpperCase(const UniChar& unichar) {
79   return ('A' <= unichar.rawcode() && unichar.rawcode() <= 'Z');
80 }
81
82 // 渡されたUniCharが、大文字のアルファベットに該当しているかどうかを返します。
83 inline bool IsAlphabetLowerCase(const UniChar& unichar) {
84   return ('a' <= unichar.rawcode() && unichar.rawcode() <= 'z');
85 }
86
87 // 渡されたUniCharが、アルファベットに該当しているかどうかを返します。
88 // 大文字小文字は区別しません。
89 inline bool IsAlphabet(const UniChar& unichar) {
90   return IsAlphabetLowerCase(unichar) || IsAlphabetUpperCase(unichar);
91 }
92
93 // 渡されたUniCharが、unicodeの有効範囲である場合trueを返します。
94 inline bool IsValidUnicode(const UniChar& unichar) {
95   return UniChar::kOutOfUnicode > unichar.rawcode() &&
96       !(UniChar::kExclusionMin <= unichar.rawcode() &&
97         unichar.rawcode() <= UniChar::kExclusionMax);
98 }
99
100
101 // UniCharを連結したコンテナのラッパーとして機能し、擬似的な
102 // Unicode文字列を提供します。
103 // 相互での比較などもサポートし、utakataの内部全般で
104 // 標準として使用することが想定されています。
105 // また、内部へのiteratorを取得することができるため、標準
106 // アルゴリズムを利用することができます。
107 class UniString : private akebono::crtp::less_than_comparable<UniString>,
108                   private akebono::crtp::equal_comparable<UniString> {
109  public:
110   // 内部で利用されるiteratorを定義します。
111   typedef std::vector<UniChar>::iterator iterator;
112   typedef std::vector<UniChar>::const_iterator const_iterator;
113
114   UniString() : unicode_chars_() {}
115   // 第一引数のchをnum個数分の文字列で初期化します。
116   UniString(const UniChar& ch, int num) : unicode_chars_(num, ch) {}
117   // 単純なコピーコンストラクタです。
118   UniString(const UniString& str) : unicode_chars_(str.unicode_chars_) {}
119
120   // 複数のunsigned intをUniCharとして変換し、文字列を構成します。
121   explicit UniString(const std::vector<unsigned int>& multis);
122
123   // std::stringの限定的な変換を行います。この時、内部バイトは意識されず、
124   // 単純にstd::stringの一文字をUniStringの一文字として、単純に変換します。
125   explicit UniString(const std::string& str);
126   virtual ~UniString() {}
127
128   // 渡されたUniCharを、numだけ連続した文字列を代入します。
129   // assignでは、代入前の値は破棄されます。
130   void Assign(const UniChar& ch, int num);
131
132   // 渡したUniStringをコピーします。コピー前の値は破棄されます。
133   void Assign(const UniString& str);
134
135   // 複数のunsigned intをUniCharとして変換し、文字列を構成します。
136   // また、この関数はコンストラクタの内部で利用されます。
137   void Assign(const std::vector<unsigned int>& multis);
138
139   // std::stringの限定的な変換を行います。この時、内部バイトは意識されず、
140   // 単純にstd::stringの一文字をUniStringの一文字として、単純に変換します。
141   // また、この関数はコンストラクタの内部で利用されます。
142   void Assign(const std::string& str);
143
144   // 文字列の先頭を指すiteratorを取得します。
145   const_iterator Begin() const {return unicode_chars_.begin();}
146   iterator Begin() {return unicode_chars_.begin();}
147
148   // 文字列の末尾を指すiteratorを取得します。
149   const_iterator End() const {return unicode_chars_.end();}
150   iterator End() {return unicode_chars_.end();}
151
152   // 指定したインデックスのデータを取得します。
153   // インデックスが有効では無い場合、std::range_error例外が
154   // 発生します。
155   const UniChar& At(size_t index) const {return unicode_chars_.at(index);}
156   UniChar& At(size_t index) {
157     return const_cast<UniChar&>(
158         static_cast<const UniString*>(this)->At(index));
159   }
160
161   // 現在の文字列のサイズを取得します。
162   size_t GetSize() const {return unicode_chars_.size();}
163
164   // 文字列が空である場合にtrueを返します。
165   bool IsEmpty() const {return unicode_chars_.empty();}
166
167   // 渡されたUniStringをコピーします。
168   UniString& operator=(const UniString& str);
169
170   // 渡されたデータを、それぞれUniStringの末尾に追加します。
171   void Append(const UniString& str);
172   void Append(const UniChar& ch);
173
174   // 渡されたUniStringと内容が完全に一致している場合trueを返します。
175   // ここでの完全一致とは、文字列長と文字列の内容が完全に一致している
176   // 事を示します。
177   bool operator==(const UniString& str) const;
178
179   // 渡されたUniStringの先頭から比較していき、先頭から一致しているか、
180   // それ以外が < である場合、trueを返します。
181   bool operator<(const UniString& str) const;
182
183   // itの位置に、[begin, last)のデータを挿入します。
184   // beginとlastが異なるUniStringのiteratorであってはなりません。
185   void Insert(iterator It, iterator begin, iterator Last);
186   void Insert(iterator it, const_iterator begin, const_iterator last);
187
188  private:
189
190   // 渡されたUniStringのデータを入れ替えます。
191   void Swap(UniString& str) {std::swap(unicode_chars_, str.unicode_chars_);}
192
193   // UniCharのコンテナです。擬似的な文字列を表現します。
194   std::vector<UniChar> unicode_chars_;
195 };
196
197 namespace detail {
198
199 // utakata::unicode名前空間内で利用される、コンテナからUniStringへの
200 // 変換を行うための関数オブジェクトです。
201 template<typename T>
202 struct UnicodeConverter : public std::unary_function<T, void> {
203   UnicodeConverter(UniString& string)
204       : string_(string) {}
205
206   // 渡されたデータを、UniCharに変換語、string_の末尾に追加していきます。
207   void operator()(const T& t) {
208     string_.Append(utakata::unicode::UniChar(static_cast<unicode_t>(t)));
209   }
210   UniString& string_;
211 };
212
213 // 渡された型をUnicodeConverterのテンプレート引数として利用し、UnicodeConverterを生成します。
214 // この時、TはT::value_typeを保持している必要があります。
215 template <typename T>
216 utakata::unicode::detail::UnicodeConverter<typename T::value_type>
217 MakeConverter(const T& container, unicode::UniString& string) {
218   return utakata::unicode::detail::UnicodeConverter<typename T::value_type>(string);
219 }
220 }
221
222 // 渡されたUnicodeから、beginの位置から末尾までの文字列をUniStringで返します。
223 // beginが有効範囲外であった場合、std::range_eror例外が発生します。
224 UniString Substring(const UniString& str, unsigned int begin);
225
226 // 渡されたUnicodeから、[begin, end)の範囲の文字列を取得します。
227 // beginがend以降であったり、endがbegin以前である場合、空のUniStringが
228 // 返されます。
229 // begin、endのいずれかが有効範囲外であった場合、std::range_error例外が
230 // 発生します。
231 UniString Substring(const UniString& str, unsigned int begin, unsigned int end);
232
233 // 渡されたunicode_tの配列を、一要素が一UniCharであるとしてUniStringを作成
234 // して返します。
235 UniString Convert(const std::vector<unicode_t>& byte_list);
236
237 // 渡したstd::stringを、一文字を一UniCharであるとしてUniStringを作成して
238 // 返します。std::stringのエンコードは無視されます。
239 UniString Convert(const std::string& target);
240
241 // 渡されたUniStringを、std::stringに変換します。変換規則は、UniStringの
242 // 一文字を、std::stringの1文字として強制的に変換します。
243 std::string Convert(const UniString& string);
244
245 // 渡されたデータを、targetの末尾に追加します。
246 // この時、T は akebono::range::for_eachの引数として渡せるものである場合、
247 // すべて受領します。
248 // T として渡された型は、akebono::rangeの関数が適用可能である必要があります。
249 template <typename T>
250 bool Append(UniString& target, const T& multis) {
251   akebono::range::for_each(
252       multis, unicode::detail::MakeConverter(multis, target));
253   return true;
254 }
255
256 // lib/range.hを利用する際に必要となるbeginとendの特殊化関数を定義します。
257
258 inline UniString::iterator begin(UniString& c) {return c.Begin();}
259
260 inline UniString::const_iterator begin(const UniString& c) {return c.Begin();}
261
262 inline UniString::iterator end(UniString& c) {return c.End();}
263
264 inline UniString::const_iterator end(const UniString& c) {return c.End();}
265 }
266 }
267
268 #endif /* _UTAKATA_SRC_UNICODE_H_ */