YSTest  PreAlpha_b400_20130424
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
textmgr.cpp
浏览该文件的文档.
1 /*
2  Copyright by FrankHB 2010 - 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 #include "YSLib/Service/textmgr.h"
29 #include "CHRLib/MapEx.h"
30 #include <ystdex/any_iterator.hpp>
31 #include "CHRLib/Convert.hpp"
32 
34 
36 
37 namespace
38 {
39 
42  ystdex::input_monomorphic_iterator&&, ConversionState&&)>);
45  ystdex::input_monomorphic_iterator&&, ConversionState&&)>);
46 
47 } // unnamed namespace;
48 
49 
50 TextFileBuffer::Iterator::Iterator(TextFileBuffer* pBuf, size_t b, size_t idx)
51  ynothrow
52  : pBuffer(pBuf), block(b), index(idx)
53 {}
54 
56 TextFileBuffer::Iterator::operator++() ynothrow
57 {
58  YAssert(pBuffer, "Null pointer found.");
59  YAssert(block < pBuffer->nBlock, "End iterator found.");
60 
61  auto& vec((*pBuffer)[block].first);
62 
63  YAssert(index < vec.size(), "Invalid index found.");
64 
65  if(YB_UNLIKELY(++index == vec.size()))
66  yunseq(++block, index = 0);
67  return *this;
68 }
69 
71 TextFileBuffer::Iterator::operator--() ynothrow
72 {
73  YAssert(pBuffer, "Null buffer pointer found.");
74  YAssert(block != 0 || index != 0, "Begin iterator found."),
75  YAssert(block < pBuffer->nBlock || *this == pBuffer->GetEnd(),
76  "Invalid iterator found.");
77 
78  if(index == 0)
79  {
80  index = (*pBuffer)[--block].first.size();
81 
82  YAssert(index != 0, "Invalid index found.");
83  }
84  else
85  YAssert(index < (*pBuffer)[block].first.size(), "Invalid index found.");
86  --index;
87  return *this;
88 }
89 
90 ucs2_t
92 {
93  YAssert(pBuffer, "Null pointer found.");
94 
95  auto& vec((*pBuffer)[block].first);
96 
97  YAssert(!vec.empty(), "Empty block found.");
98  YAssert(index < vec.size(), "Invalid index found.");
99 
100  return vec[index];
101 }
102 
103 bool
104 operator==(const TextFileBuffer::Iterator& x, const TextFileBuffer::Iterator& y)
105  ynothrow
106 {
107  YAssert(x.pBuffer == y.pBuffer, "Iterators to different buffer are not"
108  " comparable.");
109 
110  return x.block == y.block && x.index == y.index;
111 }
112 
113 
114 TextFileBuffer::TextFileBuffer(TextFile& file)
115  : File(file), nTextSize(File.GetTextSize()),
116  nBlock((nTextSize + BlockSize - 1) / BlockSize), Map(),
117  fixed_width(FetchFixedCharWidth(File.Encoding)), max_width(fixed_width
118  == 0 ? FetchMaxVariantCharWidth(File.Encoding) : fixed_width)
119 {
120  YAssert(max_width != 0, "Unknown encoding found.");
121 
122  if(fixed_width == 0)
123  ++fixed_width;
124  // TODO: Implementation for non-fixed-width char streams.
125 }
126 
129 {
130  YAssert(idx < nBlock, "Invalid index found.");
131 
132  auto& b(Map[idx]);
133  auto& vec(b.first);
134 
135  if(YB_UNLIKELY(vec.empty() && bool(File)))
136  if(const auto pfun = FetchMapperFunc(File.Encoding))
137  {
138  File.Locate(idx * BlockSize);
139 
140  size_t len(idx == nBlock - 1 && nTextSize % BlockSize != 0
141  ? nTextSize % BlockSize : BlockSize);
142 
143  vec.reserve(len / fixed_width);
144 
145  size_t n_byte(0);
146  ucs2_t c;
148 
149  while(n_byte < len)
150  {
151  ConversionState st;
152 
153  if(YB_LIKELY(ConvertCharacter(pfun, c, i, std::move(st))
154  == ConversionResult::OK))
155  vec.push_back(c);
156  n_byte += GetCountOf(st);
157  }
158  std::ungetc(*i, File.GetPtr()),
159  vec.shrink_to_fit();
160  }
161  return b;
162 }
163 
166 {
167  return TextFileBuffer::Iterator(this);
168 }
171 {
172  return TextFileBuffer::Iterator(this, nBlock);
173 }
176 {
177  if(pos < nTextSize)
178  {
179  const size_t idx(pos / BlockSize);
180 
181  pos %= BlockSize;
182  if(fixed_width == max_width)
183  return TextFileBuffer::Iterator(this, idx, pos / max_width);
184 
185  YAssert(bool(File), "Invalid file found.");
186 
187  if(const auto pfun = FetchSkipMapperFunc(File.Encoding))
188  {
189  File.Locate(idx * BlockSize);
190 
191  size_t n_byte(0), n_char(0);
193 
194  while(n_byte < pos)
195  {
196  ConversionState st;
197 
198  if(YB_LIKELY(ConvertCharacter(pfun, i, std::move(st))
199  == ConversionResult::OK))
200  ++n_char;
201  n_byte += GetCountOf(st);
202  }
203  std::ungetc(*i, File.GetPtr());
204  return TextFileBuffer::Iterator(this, idx, n_char);
205  }
206  return TextFileBuffer::Iterator(this, idx, 0);
207  }
208  return GetEnd();
209 }
210 size_t
212 {
213  if(i == GetEnd())
214  return nTextSize;
215 
216  auto idx(i.GetBlockN());
217  const auto pos(i.GetIndexN());
218 
219  if(fixed_width == max_width)
220  return idx * BlockSize + pos * max_width;
221 
222  if(const auto pfun = FetchSkipMapperFunc(File.Encoding))
223  {
224  const auto& vec((*this)[idx].first);
225 
226  YAssert(!vec.empty() && bool(File), "Block loading failed.");
227 
228  File.Locate(idx *= BlockSize);
229 
230  const auto mid(vec.cbegin() + pos);
231 
232  YAssert(mid <= vec.cend(), "Wrong iterator found.");
233 
234  auto it(vec.begin());
235 
236  YAssert(it <= mid, "Wrong iterator found.");
237 
239  size_t n_byte(0);
240 
241  while(it != mid)
242  {
243  ConversionState st;
244 
245  if(YB_LIKELY(ConvertCharacter(pfun, i, std::move(st))
246  == ConversionResult::OK))
247  ++it;
248  n_byte += GetCountOf(st);
249  }
250  return idx + n_byte;
251  }
252  return idx;
253 }
254 
255 
256 string
257 CopySliceFrom(TextFileBuffer& buf, size_t pos, size_t len)
258  ythrow(std::out_of_range)
259 {
260  const auto i_end(buf.GetEnd());
261  auto i_beg(buf.GetIterator(pos));
262 
263  if(i_beg == i_end)
264  throw std::out_of_range("Wrong offset found.");
265  if(len == 0)
266  return {};
267 
268  YAssert(pos < pos + len, "Unexpected unsigned integer round up.");
269 
270  string str;
271 
272  str.reserve(len * 2);
273  while(len != 0 && i_beg != i_end)
274  {
275  str.push_back(*i_beg);
276  yunseq(++i_beg, --len);
277  }
278  return std::move(str);
279 }
280 
281 YSL_END_NAMESPACE(Text)
282 
283 YSL_END
284