YSTest  PreAlpha_b500_20140530
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
textmgr.cpp
浏览该文件的文档.
1 /*
2  © 2010-2014 FrankHB.
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 #include "YSLib/Service/YModules.h"
29 #include YFM_YSLib_Service_TextManager
30 #include YFM_CHRLib_MappingEx
31 #include <ystdex/any_iterator.hpp>
32 #include YFM_CHRLib_Convert
33 
34 namespace YSLib
35 {
36 
37 namespace Text
38 {
39 
40 namespace
41 {
42 
44 yconstexpr auto& FetchMapperFunc(FetchMapperPtr<ConversionResult(ucs2_t&,
45  ystdex::input_monomorphic_iterator&&, ConversionState&&)>);
47 yconstexpr auto& FetchSkipMapperFunc(FetchMapperPtr<ConversionResult(
48  ystdex::input_monomorphic_iterator&&, ConversionState&&)>);
49 
50 } // unnamed namespace;
51 
52 
54  ynothrow
55  : p_buffer(p_buf), block(b), index(idx)
56 {}
57 
60 {
62  YAssert(block < p_buffer->nBlock, "End iterator found.");
63 
64  auto& vec((*p_buffer)[block].first);
65 
66  YAssert(index < vec.size(), "Invalid index found.");
67  if(YB_UNLIKELY(++index == vec.size()))
68  yunseq(++block, index = 0);
69  return *this;
70 }
71 
74 {
75  YAssert(p_buffer, "Null buffer pointer found.");
76  YAssert(block != 0 || index != 0, "Begin iterator found."),
77  YAssert(block < p_buffer->nBlock || *this == p_buffer->end(),
78  "Invalid iterator found.");
79  if(index == 0)
80  {
81  index = (*p_buffer)[--block].first.size();
82 
83  YAssert(index != 0, "Invalid index found.");
84  }
85  else
86  YAssert(index < (*p_buffer)[block].first.size(),
87  "Invalid index found.");
88  --index;
89  return *this;
90 }
91 
92 TextFileBuffer::iterator::reference
94 {
95  YAssertNonnull(p_buffer);
96 
97  auto& vec((*p_buffer)[block].first);
98 
99  YAssert(!vec.empty(), "Empty block found.");
100  YAssert(index < vec.size(), "Invalid index found.");
101  return vec[index];
102 }
103 
104 bool
106  ynothrow
107 {
108  YAssert(x.p_buffer == y.p_buffer, "Iterators to different buffer are not"
109  " comparable.");
110 
111  return x.block == y.block && x.index == y.index;
112 }
113 
114 
116  : File(file), nTextSize(File.GetTextSize()),
117  nBlock((nTextSize + BlockSize - 1) / BlockSize), Map(),
120 {
121  YAssert(max_width != 0, "Unknown encoding found.");
122 
123  if(fixed_width == 0)
124  ++fixed_width;
125  // TODO: Implementation for non-fixed-width char streams.
126 }
127 
129 TextFileBuffer::operator[](size_t idx)
130 {
131  YAssert(idx < nBlock, "Invalid index found.");
132 
133  auto& b(Map[idx]);
134  auto& vec(b.first);
135 
136  if(YB_UNLIKELY(vec.empty() && bool(File)))
137  if(const auto pfun = FetchMapperFunc(File.Encoding))
138  {
139  File.Locate(idx * BlockSize);
140 
141  size_t len(idx == nBlock - 1 && nTextSize % BlockSize != 0
142  ? nTextSize % BlockSize : BlockSize);
143 
144  vec.reserve(len / fixed_width);
145 
146  size_t n_byte(0);
147  ucs2_t c;
148  ystdex::ifile_iterator i(File.GetPtr());
149 
150  while(n_byte < len)
151  {
152  ConversionState st;
153 
154  if(YB_LIKELY(ConvertCharacter(pfun, c, i, std::move(st))
155  == ConversionResult::OK))
156  vec.push_back(c);
157  n_byte += GetCountOf(st);
158  }
159  std::ungetc(*i, File.GetPtr()),
160  vec.shrink_to_fit();
161  }
162  return b;
163 }
164 
165 TextFileBuffer::iterator
167 {
168  return TextFileBuffer::iterator(this);
169 }
172 {
173  return TextFileBuffer::iterator(this, nBlock);
174 }
177 {
178  if(pos < nTextSize)
179  {
180  const size_t idx(pos / BlockSize);
181 
182  pos %= BlockSize;
183  if(fixed_width == max_width)
184  return TextFileBuffer::iterator(this, idx, pos / max_width);
185 
186  YAssert(bool(File), "Invalid file found.");
187 
188  if(const auto pfun = FetchSkipMapperFunc(File.Encoding))
189  {
190  File.Locate(idx * BlockSize);
191 
192  size_t n_byte(0), n_char(0);
193  ystdex::ifile_iterator i(File.GetPtr());
194 
195  while(n_byte < pos)
196  {
197  ConversionState st;
198 
199  if(YB_LIKELY(ConvertCharacter(pfun, i, std::move(st))
200  == ConversionResult::OK))
201  ++n_char;
202  n_byte += GetCountOf(st);
203  }
204  std::ungetc(*i, File.GetPtr());
205  return TextFileBuffer::iterator(this, idx, n_char);
206  }
207  return TextFileBuffer::iterator(this, idx, 0);
208  }
209  return end();
210 }
211 size_t
213 {
214  if(i == end())
215  return nTextSize;
216 
217  auto idx(i.GetBlockN());
218  const auto pos(i.GetIndexN());
219 
220  if(fixed_width == max_width)
221  return idx * BlockSize + pos * max_width;
222 
223  if(const auto pfun = FetchSkipMapperFunc(File.Encoding))
224  {
225  const auto& vec((*this)[idx].first);
226 
227  YAssert(!vec.empty() && bool(File), "Block loading failed.");
228 
229  File.Locate(idx *= BlockSize);
230 
231  const auto mid(vec.cbegin() + pos);
232 
233  YAssert(mid <= vec.cend(), "Wrong iterator found.");
234 
235  auto it(vec.begin());
236 
237  YAssert(it <= mid, "Wrong iterator found.");
238 
239  ystdex::ifile_iterator i(File.GetPtr());
240  size_t n_byte(0);
241 
242  while(it != mid)
243  {
244  ConversionState st;
245 
246  if(YB_LIKELY(ConvertCharacter(pfun, i, std::move(st))
247  == ConversionResult::OK))
248  ++it;
249  n_byte += GetCountOf(st);
250  }
251  return idx + n_byte;
252  }
253  return idx;
254 }
255 
256 
257 string
258 CopySliceFrom(TextFileBuffer& buf, size_t pos, size_t len)
259  ythrow(std::out_of_range)
260 {
261  const auto i_end(buf.end());
262  auto i_beg(buf.GetIterator(pos));
263 
264  if(i_beg == i_end)
265  throw std::out_of_range("Wrong offset found.");
266  if(len == 0)
267  return {};
268 
269  YAssert(pos < pos + len, "Unexpected unsigned integer round up.");
270 
271  string str;
272 
273  str.reserve(len * 2);
274  while(len != 0 && i_beg != i_end)
275  {
276  str.push_back(*i_beg);
277  yunseq(++i_beg, --len);
278  }
279  return str;
280 }
281 
282 } // namespace Text;
283 
284 } // namespace YSLib;
285 
TextFileBuffer(TextFile &)
构造:使用文本文件。
Definition: textmgr.cpp:115
size_t nBlock
区块数。
Definition: textmgr.h:137
ConversionResult
编码转换结果。
Definition: chrmap.h:75
目标编码迭代器类型。
Definition: textmgr.h:68
static auto first(const _tIterator &i) -> decltype((i->first))
Definition: iterator.hpp:759
size_t GetPosition(iterator)
取迭代器对应的文本字节位置。
Definition: textmgr.cpp:212
ConversionResult ConvertCharacter(_fConv f, ucs2_t &uc, _tIn &&i, ConversionState &&st)
Definition: Convert.hpp:40
编码转换状态。
Definition: chrmap.h:89
基于 ISO C 标准库的流只读迭代器。
Definition: cstdio.h:73
文本文件类。
Definition: TextFile.h:56
iterator & operator++() ynothrow
迭代:循环向后遍历。
Definition: textmgr.cpp:59
文件基类。
Definition: File.h:43
iterator end() ynothrow
取文本缓冲区终止迭代器。
Definition: textmgr.cpp:171
size_t max_width
最大编码每字符的字节数。
Definition: textmgr.h:155
#define YB_UNLIKELY(expr)
分支预测提示。
Definition: ydef.h:298
size_t fixed_width
固定编码每字符的字节数。
Definition: textmgr.h:150
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:748
#define ynothrow
YSLib 无异常抛出保证:若支持 noexcept 关键字, 指定特定的 noexcept 异常规范。
Definition: ydef.h:514
#define ythrow(...)
YSLib 动态异常规范:根据是否使用异常规范宏指定或忽略动态异常规范。
Definition: ydef.h:476
YF_API size_t FetchMaxVariantCharWidth(Encoding)
取指定变长编码的最大字符宽度。
Definition: chrmap.cpp:67
iterator & operator--() ynothrow
迭代:循环向前遍历。
Definition: textmgr.cpp:73
#define YAssertNonnull(_expr)
Definition: cassert.h:81
iterator begin() ynothrow
取文本缓冲区起始迭代器。
Definition: textmgr.cpp:166
YF_API size_t FetchFixedCharWidth(Encoding)
取指定固定编码的固定字符宽度。
Definition: chrmap.cpp:37
动态泛型输入迭代器。
char16_t ucs2_t
UCS-2 字符类型。
Definition: chrdef.h:44
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:462
size_t nTextSize
文本大小。
Definition: textmgr.h:132
bool operator==(const TextFileBuffer::iterator &x, const TextFileBuffer::iterator &y) ynothrow
Definition: textmgr.cpp:105
#define YB_LIKELY(expr)
Definition: ydef.h:297
static yconstexpr size_t BlockSize
默认文本区块大小。
Definition: textmgr.h:120
File Encoding nTextSize iterator GetIterator(size_t)
取文本字节位置对应的迭代器。
Definition: textmgr.cpp:176
MapType Map
缓冲映射。
Definition: textmgr.h:142
动态泛型迭代器。
_fCodemapTransform * FetchMapperPtr(Encoding enc)
取指定编码映射的转换函数指针。
Definition: MapEx.h:217
string CopySliceFrom(TextFileBuffer &buf, size_t pos, size_t len) ythrow(std
Definition: textmgr.cpp:258
iterator(TextFileBuffer *={}, size_t=0, size_t=0) ynothrow
构造:指定文本读取位置。
Definition: textmgr.cpp:53
#define YAssert(_expr, _msg)
Definition: cassert.h:73
pair< vector< ucs2_t >, size_t > BlockType
缓冲区块类型。
Definition: textmgr.h:55