YSTest: TextFile.cpp 源文件

YSTest PreAlpha_b900_20201012 The YSLib Test Project

TextFile.cpp
浏览该文件的文档.
1 /*
2 © 2009-2016, 2019 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_TextFile // for ystdex::min;
30 #include YFM_CHRLib_Convert
31 #include <ystdex/utility.hpp> // for ystdex::as_const;
32
33 namespace YSLib
34 {
35
36 namespace Text
37 {
38
39 Encoding
40 VerifyEncoding(std::FILE* fp, char* s, size_t buflen, size_t txt_len,
41 Encoding enc)
42 {
43 const auto n(ystdex::min(txt_len, buflen));
44
45 std::char_traits<char>::assign(Nonnull(s) + n, buflen - n, char());
46 if(std::fread(s, 1, n, Nonnull(fp)) == n)
47 {
48 std::rewind(fp);
49 if(VerifyUC(&ystdex::as_const(s[0]), ptrdiff_t(n), enc))
50 return enc;
51 }
52 return CharSet::Null;
53 }
54 Encoding
55 VerifyEncoding(std::streambuf& sb, char* s, size_t buflen, size_t txt_len,
56 Encoding enc)
57 {
58 const auto n(ystdex::min(txt_len, buflen));
59
60 std::char_traits<char>::assign(Nonnull(s) + n, buflen - n, char());
61
62 if(sb.sgetn(s, std::streamsize(n)) == std::streamsize(n))
63 {
64 ;
65 if(sb.pubseekpos(0, std::ios_base::in)
66 != std::streampos(std::streamoff(-1))
67 && VerifyUC(&ystdex::as_const(s[0]), ptrdiff_t(n), enc))
68 return enc;
69 }
70 return CharSet::Null;
71 }
72 Encoding
73 VerifyEncoding(std::istream& stream, char* s, size_t buflen, size_t txt_len,
74 Encoding enc)
75 {
76 const auto n(ystdex::min(txt_len, buflen));
77
78 std::char_traits<char>::assign(Nonnull(s) + n, buflen - n, char());
79 stream.read(s, std::streamsize(n));
80 if(stream)
81 {
82 stream.seekg(0);
83 if(VerifyUC(&ystdex::as_const(s[0]), ptrdiff_t(n), enc))
84 return enc;
85 }
86 return CharSet::Null;
87 }
88
89 bool
90 CheckBOM(std::istream& is, string_view str)
91 {
92 const auto len(str.length());
93 // NOTE: Max allowed size in all BOMs is needed.
94 array<char, 4> buf;
95
96 YAssert(len <= 4, "BOM length is too long.");
97 is.read(buf.data(), std::streamsize(len));
98 return is.gcount() == std::streamsize(len)
99 ? CheckBOM(buf.data(), str.data(), len) : false;
100 }
101
102 pair<Encoding, size_t>
103 DetectBOM(const char* buf)
104 {
105 YAssertNonnull(buf);
106 #define YSL_Impl_DetectBOM(_n) \
107 if(CheckBOM(buf, BOM_##_n)) \
108 return {CharSet::_n, size(BOM_##_n) - 1};
109 YSL_Impl_DetectBOM(UTF_32LE)
110 YSL_Impl_DetectBOM(UTF_32BE)
111 YSL_Impl_DetectBOM(UTF_8)
112 YSL_Impl_DetectBOM(UTF_16LE)
113 YSL_Impl_DetectBOM(UTF_16BE)
114 #undef YSL_Impl_DetectBOM
115 return {CharSet::Null, 0};
116 }
117 pair<Encoding, size_t>
118 DetectBOM(string_view sv)
119 {
120 YAssertNonnull(sv.data());
121 #define YSL_Impl_DetectBOM(_n) \
122 if(sv.length() >= size(BOM_##_n) - 1 && CheckBOM(sv.data(), BOM_##_n)) \
123 return {CharSet::_n, size(BOM_##_n) - 1};
124 YSL_Impl_DetectBOM(UTF_32LE)
125 YSL_Impl_DetectBOM(UTF_32BE)
126 YSL_Impl_DetectBOM(UTF_8)
127 YSL_Impl_DetectBOM(UTF_16LE)
128 YSL_Impl_DetectBOM(UTF_16BE)
129 #undef YSL_Impl_DetectBOM
130 return {CharSet::Null, 0};
131 }
132 pair<Encoding, size_t>
133 DetectBOM(std::streambuf& sb, std::size_t fsize, Encoding enc)
134 {
135 const auto pos(sb.pubseekpos(0, std::ios_base::in));
136
137 if(pos != std::streampos(std::streamoff(-1)))
138 {
139 if(fsize > 1U)
140 {
141 array<char, 4> buf;
142 const auto n(sb.sgetn(buf.data(), 4));
143
144 if(n != 0)
145 {
146 const auto res(DetectBOM(string_view(buf.data(),
147 CheckNonnegative<size_t>(n))));
148
149 if(sb.pubseekpos(std::streamoff(res.second), std::ios_base::in)
150 != std::streampos(std::streamoff(-1)) && res.second != 0)
151 return res;
152 }
153 else
154 return {CharSet::Null, 0};
155 }
156
157 char s[64U];
158
159 return {VerifyEncoding(sb, s, size(s), size_t(fsize), enc), 0};
160 }
161 return {CharSet::Null, 0};
162 }
163 pair<Encoding, size_t>
164 DetectBOM(std::istream& is, std::size_t fsize, Encoding enc)
165 {
166 is.seekg(0);
167 if(fsize > 1U)
168 {
169 array<char, 4> buf;
170
171 is.read(buf.data(), 4);
172 if(bool(is) || is.eof())
173 {
174 const auto res(DetectBOM(string_view(buf.data(),
175 CheckNonnegative<size_t>(is.gcount()))));
176
177 is.seekg(std::istream::off_type(res.second));
178 if(res.second != 0)
179 return res;
180 }
181 else
182 return {CharSet::Null, 0};
183 }
184
185 char s[64U];
186
187 return {VerifyEncoding(is, s, size(s), size_t(fsize), enc), 0};
188 }
189
190 size_t
191 WriteBOM(std::ostream& os, Encoding enc)
192 {
193 switch(enc)
194 {
195 #define YSL_Impl_WriteBOM(_n) \
196 case CharSet::_n: \
197 ystdex::write_literal(os, BOM_##_n); \
198 return size(BOM_##_n) - 1;
199 YSL_Impl_WriteBOM(UTF_16LE)
200 YSL_Impl_WriteBOM(UTF_16BE)
201 YSL_Impl_WriteBOM(UTF_8)
202 YSL_Impl_WriteBOM(UTF_32LE)
203 YSL_Impl_WriteBOM(UTF_32BE)
204 #undef YSL_Impl_WriteBOM
205 default:
206 return 0;
207 }
208 }
209
210 } // namespace Text;
211
212 } // namespace YSLib;
213
platform::Nonnull
YB_PURE _type && Nonnull(_type &&p) ynothrowv
断言并返回非空参数。
Definition: Debug.h:518
size
size_t size
Definition: memory_resource.cpp:295
YSL_Impl_DetectBOM
#define YSL_Impl_DetectBOM(_n)
ystdex::cpp2014::min
const _type & min(const _type &a, const _type &b, _fComp comp=less< _type >())
取较小的元素。
Definition: algorithm.hpp:614
CHRLib::CharSet::UTF_8
yconstexpr const Encoding UTF_8(csUTF8)
ystdex::cpp2017::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:437
YSLib::Text::CheckBOM
YB_ATTR_nodiscard YB_PURE CheckBOM
Definition: TextFile.h:83
platform::size_t
YB_ATTR_nodiscard YF_API size_t
Definition: FileIO.h:1345
CHRLib::CharSet::Null
@ Null
空字符集。
Definition: Encoding.h:63
CHRLib::CharSet::Encoding
Encoding
字符流编码标识。
Definition: Encoding.h:59
CHRLib::CharSet::UTF_32LE
yconstexpr const Encoding UTF_32LE(csUTF32LE)
YModules.h
YSLib 服务模块配置文件。
CHRLib::CharSet::UTF_16BE
yconstexpr const Encoding UTF_16BE(csUTF16BE)
YSLib::Text::WriteBOM
YF_API size_t WriteBOM(std::ostream &, Text::Encoding)
写入指定编码的 BOM 。
Definition: TextFile.cpp:191
YSLib::YAssert
YAssert(!(v< Deref(a)), "Value less than lower bound found.")
YSLib::Text::DetectBOM
YB_ATTR_nodiscard YF_API size_t DetectBOM(const char *)
Definition: TextFile.cpp:103
YSL_Impl_WriteBOM
#define YSL_Impl_WriteBOM(_n)
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:165
utility.hpp
实用设施。
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:46
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:143
CHRLib::CharSet::UTF_32BE
yconstexpr const Encoding UTF_32BE(csUTF32BE)
YSLib::Text::VerifyEncoding
Encoding VerifyEncoding(std::FILE *fp, char *s, size_t buflen, size_t txt_len, Encoding enc)
Definition: TextFile.cpp:40
YSLib::Text::buf
YB_ATTR_nodiscard YB_PURE const char * buf
Definition: TextFile.h:83
ystdex::assign
void assign(_tCon &con, _tParams &&... args)
插入参数指定的元素到容器。
Definition: container.hpp:150
CHRLib::VerifyUC
bool VerifyUC(_tIn &&first, ystdex::remove_reference_t< _tIn > last, Encoding enc)
验证指定字符序列是否可转换为 UCS-2 字符串。
Definition: Convert.hpp:84
fp
tidy_ptr< std::streambuf > fp
Definition: TextManager.cpp:93
CHRLib::enc
enc
Definition: CharacterProcessing.h:84
YSLib::Text::str
YB_ATTR_nodiscard YB_PURE const char const char * str
Definition: TextFile.h:83
CHRLib::CharSet::UTF_16LE
yconstexpr const Encoding UTF_16LE(csUTF16LE)
ystdex::cpp2017::as_const
add_const_t< _type > & as_const(_type &t)
转换 const 引用。
Definition: utility.hpp:77