YSTest  PreAlpha_b400_20130424
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
smap.hpp
浏览该文件的文档.
1 /*
2  Copyright by FrankHB 2009 - 2013.
3 
4  This file is part of the YSLib project, and may only be used,
5  modified, and distributed under the terms of the YSLib project
6  license, LICENSE.TXT. By continuing to use, modify, or distribute
7  this file you indicate that you have read the license and
8  understand and accept it fully.
9 */
10 
28 #ifndef CHRLIB_INC_smap_hpp_
29 #define CHRLIB_INC_smap_hpp_ 1
30 
31 #include "chrmap.h"
32 #include <ystdex/cstdio.h>
33 #include <ystdex/any.h> // for ystdex::pseudo_object;
34 
36 
41 template<typename _tIn, typename _tState>
42 inline bool
43 FillByte(_tIn& i, _tState& st)
44 {
45  static_assert(std::is_constructible<const byte, decltype(*i)>::value,
46  "Invalid mapping source type found.");
47  static_assert(!std::is_volatile<typename std::remove_reference<
48  _tState>::type>::value, "Volatile state is not supported.");
49 
51  return false;
52 
53  const byte r(*i);
54 
55  yunseq(++i, GetSequenceOf(st)[GetCountOf(st)++] = r);
56  return true;
57 }
58 
59 
65 template<Encoding>
67 {};
68 
69 template<>
70 struct GUCS2Mapper<CharSet::UTF_8>
71 {
76  static yconstfn bool
77  IsInvalid(byte b)
78  {
79  return b == 0xC0 || b == 0xC1 || b > 0xF4;
80  }
81 
90  template<typename _tObj, typename _tIn, typename _tState>
91  static ConversionResult
92  Map(_tObj& uc, _tIn&& i, _tState&& st)
93  {
94  const auto seq(GetSequenceOf(st));
95 
96  switch(GetCountOf(st))
97  {
98  case 0:
99  if(YB_UNLIKELY(!FillByte(i, st)))
100  return ConversionResult::BadSource;
101  if(seq[0] < 0x80)
102  {
103  uc = seq[0];
104  break;
105  }
106  if(YB_UNLIKELY(IsInvalid(seq[0]) || ((seq[0] & 0xC0) != 0xC0)))
107  return ConversionResult::Invalid;
108  case 1:
109  if(YB_UNLIKELY(!FillByte(i, st)))
110  return ConversionResult::BadSource;
111  if(YB_UNLIKELY(IsInvalid(seq[1]) || ((seq[1] & 0xC0) != 0x80)))
112  return ConversionResult::Invalid;
113  if(((seq[0] ^ 0xC0) & 0xE0) == 0)
114  {
115  uc = ((seq[0] & 0x1C) >> 2 << 8)
116  | ((seq[0] & 0x03) << 6)
117  | (seq[1] & 0x3F);
118  break;
119  }
120  case 2:
121  if(YB_UNLIKELY(!FillByte(i, st)))
122  return ConversionResult::BadSource;
123  if(YB_UNLIKELY(IsInvalid(seq[2]) || ((seq[2] & 0xC0) != 0x80)))
124  return ConversionResult::Invalid;
125  if(((seq[0] ^ 0xE0) & 0xF0) == 0)
126  {
127  uc = (((seq[0] & 0x0F) << 4 | (seq[1] & 0x3C) >> 2) << 8)
128  | ((seq[1] & 0x3) << 6) | (seq[2] & 0x3F);
129  break;
130  }
131  case 3:
132  if(YB_UNLIKELY(!FillByte(i, st)))
133  return ConversionResult::BadSource;
134  if(YB_UNLIKELY(IsInvalid(seq[3]) || ((seq[3] & 0xC0) != 0x80)))
135  return ConversionResult::Invalid;
136  if(YB_LIKELY(((seq[0] ^ 0xF0) & 0xF8) == 0))
137  {
138  uc = (((seq[0] & 0x0F) << 4 | (seq[1] & 0x3C) >> 2) << 8)
139  | ((seq[1] & 0x3) << 6) | (seq[2] & 0x3F);
140  break;
141  }
142  return ConversionResult::Unhandled;
143  default:
144  return ConversionResult::BadState;
145  }
146  return ConversionResult::OK;
147  }
148 
149  template<typename _tOut>
150  static byte
151  InverseMap(_tOut d, const ucs2_t& s)
152  {
153  size_t l(0);
154 
155  if(s < 0x80)
156  {
157  *d = s;
158  return 1;
159  }
160  if(s < 0x800)
161  l = 2;
162  else
163  {
164  *d = 0xE0 | s >> 12;
165  ++d;
166  l = 3;
167  }
168  *d = 0x80 | (s >> 6 & 0x3F);
169  *++d = 0x80 | (s & 0x3F);
170  return l;
171  }
172 };
173 
174 template<>
175 struct GUCS2Mapper<CharSet::UTF_16BE>
176 {
177  template<typename _tObj, typename _tIn, typename _tState>
178  static ConversionResult
179  Map(_tObj& uc, _tIn&& i, _tState&& st)
180  {
181  const auto seq(GetSequenceOf(st));
182 
183  switch(GetCountOf(st))
184  {
185  case 0:
186  if(YB_UNLIKELY(!FillByte(i, st)))
187  return ConversionResult::BadSource;
188  case 1:
189  if(YB_UNLIKELY(!FillByte(i, st)))
190  return ConversionResult::BadSource;
191  uc = seq[0] << 8 | seq[1];
192  break;
193  default:
194  return ConversionResult::BadState;
195  }
196  return ConversionResult::OK;
197  }
198 };
199 
200 template<>
201 struct GUCS2Mapper<CharSet::UTF_16LE>
202 {
203  template<typename _tObj, typename _tIn, typename _tState>
204  static ConversionResult
205  Map(_tObj& uc, _tIn&& i, _tState&& st)
206  {
207  const auto seq(GetSequenceOf(st));
208 
209  switch(GetCountOf(st))
210  {
211  case 0:
212  if(YB_UNLIKELY(!FillByte(i, st)))
213  return ConversionResult::BadSource;
214  case 1:
215  if(YB_UNLIKELY(!FillByte(i, st)))
216  return ConversionResult::BadSource;
217  uc = seq[0] | seq[1] << 8;
218  break;
219  default:
220  return ConversionResult::BadState;
221  }
222  return ConversionResult::OK;
223  }
224 };
226 
227 
233 template<Encoding, typename... _tParams>
235 UCS2Mapper_Map(_tParams&&...)
236 {
237  return ConversionResult::Unhandled;
238 }
239 template<Encoding _vEnc, typename _tDst, typename _tSrc, typename _tState>
241 UCS2Mapper_Map(_tDst&& d, _tSrc&& s, _tState&& st, decltype(
242  &GUCS2Mapper<_vEnc>::template Map<_tDst, _tSrc, _tState>) = {})
243 {
244  return GUCS2Mapper<_vEnc>::Map(d, s, st);
245 }
246 
247 template<Encoding _vEnc, typename _tDst, typename _tSrc>
250 {
251  return 0;
252 }
253 template<Encoding _vEnc, typename _tDst>
255 UCS2Mapper_InverseMap(_tDst&& d, const ucs2_t& s,
256  decltype(&GUCS2Mapper<_vEnc>::template InverseMap<_tDst>) = {})
257 {
258  return GUCS2Mapper<_vEnc>::InverseMap(d, s);
259 }
260 
261 
262 template<Encoding _vEnc, typename _tIn, typename _tState>
264 UCS2Mapper(ucs2_t& uc, _tIn&& i, _tState&& st)
265 {
266  return UCS2Mapper_Map<_vEnc>(uc, i, std::move(st));
267 }
268 template<Encoding _vEnc, typename _tIn, typename _tState>
270 UCS2Mapper(_tIn&& i, _tState&& st)
271 {
272  return UCS2Mapper_Map<_vEnc>(ystdex::pseudo_output(), i, st);
273 }
274 template<Encoding _vEnc>
275 byte
276 UCS2Mapper(char* d, const ucs2_t& s)
277 {
278  yconstraint(d);
279 
280  return UCS2Mapper_InverseMap<_vEnc>(d, s);
281 }
283 
285 
286 #endif
287