YSTest: smap.hpp 源文件

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
35 CHRLIB_BEGIN
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
50 if(YB_UNLIKELY(is_undereferenceable(i)))
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>
66 class GUCS2Mapper
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>
234 yconstfn ConversionResult
235 UCS2Mapper_Map(_tParams&&...)
236 {
237 return ConversionResult::Unhandled;
238 }
239 template<Encoding _vEnc, typename _tDst, typename _tSrc, typename _tState>
240 yconstfn ConversionResult
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>
248 yconstfn byte
249 UCS2Mapper_InverseMap(_tDst, _tSrc)
250 {
251 return 0;
252 }
253 template<Encoding _vEnc, typename _tDst>
254 yconstfn byte
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>
263 yconstexpr ConversionResult
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>
269 yconstexpr ConversionResult
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
284 CHRLIB_END
285
286 #endif
287