Commit MetaInfo

Revision45f9de52a43cdd37aacd1d31317e948ab1af21f1 (tree)
Time2013-05-12 12:25:13
Author <exeal@user...>

Log Message

Added fileio.PathStringPiece type.

Change Summary

Incremental Difference

diff -r 8257513d0169 -r 45f9de52a43c ascension/ascension/kernel/fileio.hpp
--- a/ascension/ascension/kernel/fileio.hpp Sat May 11 12:12:08 2013 +0900
+++ b/ascension/ascension/kernel/fileio.hpp Sun May 12 12:25:13 2013 +0900
@@ -18,6 +18,8 @@
1818 #elif defined(ASCENSION_OS_POSIX)
1919 # include <dirent.h> // DIR
2020 #endif
21+#include <boost/range/const_iterator.hpp>
22+#include <array>
2123 #ifndef ASCENSION_NO_GREP
2224 # include <stack>
2325 #endif // !ASCENSION_NO_GREP
@@ -34,6 +36,8 @@
3436 typedef ASCENSION_FILE_NAME_CHARACTER_TYPE PathCharacter;
3537 /// String type for file names.
3638 typedef std::basic_string<PathCharacter> PathString;
39+ /// String reference type for file names.
40+ typedef boost::basic_string_ref<PathCharacter, std::char_traits<PathCharacter>> PathStringPiece;
3741
3842 /// Used by functions and methods write to files.
3943 struct WritingFormat {
@@ -50,8 +54,8 @@
5054
5155 class IOException : public std::ios_base::failure {
5256 public:
53- explicit IOException(const PathString& fileName);
54- IOException(const PathString& fileName, const std::error_code::value_type code);
57+ explicit IOException(const PathStringPiece& fileName);
58+ IOException(const PathStringPiece& fileName, const std::error_code::value_type code);
5559 ~IOException() BOOST_NOEXCEPT;
5660 const PathString& fileName() const BOOST_NOEXCEPT;
5761 public:
@@ -133,7 +137,7 @@
133137 class TextFileStreamBuffer : public std::basic_streambuf<Char> {
134138 ASCENSION_NONCOPYABLE_TAG(TextFileStreamBuffer);
135139 public:
136- TextFileStreamBuffer(const PathString& fileName,
140+ TextFileStreamBuffer(const PathStringPiece& fileName,
137141 std::ios_base::openmode mode, const std::string& encoding,
138142 encoding::Encoder::SubstitutionPolicy encodingSubstitutionPolicy,
139143 bool writeUnicodeByteOrderMark);
@@ -165,10 +169,10 @@
165169 #endif
166170 const PathString fileName_;
167171 std::ios_base::openmode mode_;
168- struct {
169- const Byte* first;
170- const Byte* last;
172+ struct InputMapping {
173+ boost::iterator_range<const Byte*> buffer;
171174 const Byte* current;
175+ InputMapping() BOOST_NOEXCEPT : buffer(nullptr, nullptr), current(nullptr) {}
172176 } inputMapping_;
173177 #ifdef ASCENSION_OS_WINDOWS
174178 LARGE_INTEGER originalFileEnd_;
@@ -176,7 +180,7 @@
176180 off_t originalFileEnd_;
177181 #endif
178182 std::unique_ptr<encoding::Encoder> encoder_;
179- Char ucsBuffer_[8192];
183+ std::array<Char, 8192> ucsBuffer_;
180184 };
181185
182186 class TextFileDocumentInput : public DocumentInput {
@@ -217,7 +221,7 @@
217221
218222 /// @name Bound File
219223 /// @{
220- void bind(const PathString& fileName);
224+ void bind(const PathStringPiece& fileName);
221225 PathString fileName() const BOOST_NOEXCEPT;
222226 bool isBoundToFile() const BOOST_NOEXCEPT;
223227 void lockFile(const LockMode& mode);
@@ -302,7 +306,7 @@
302306 class DirectoryIterator : public DirectoryIteratorBase {
303307 public:
304308 // constructors
305- DirectoryIterator(const PathCharacter* directoryName);
309+ DirectoryIterator(const PathStringPiece& directoryName);
306310 ~DirectoryIterator() BOOST_NOEXCEPT;
307311 // DirectoryIteratorBase
308312 const PathString& current() const;
@@ -326,7 +330,7 @@
326330 class RecursiveDirectoryIterator : public DirectoryIteratorBase {
327331 public:
328332 // constructors
329- RecursiveDirectoryIterator(const PathCharacter* directoryName);
333+ RecursiveDirectoryIterator(const PathStringPiece& directoryName);
330334 ~RecursiveDirectoryIterator() BOOST_NOEXCEPT;
331335 // attributes
332336 void dontPush();
@@ -345,16 +349,20 @@
345349 };
346350 #endif // !ASCENSION_NO_GREP
347351
348- // free functions related to file path name
349- PathString canonicalizePathName(const PathCharacter* pathName);
350- bool comparePathNames(const PathCharacter* s1, const PathCharacter* s2);
352+ /// @defgroup file_pathname Free Functions Related to File Path Name
353+ /// @{
354+ PathString canonicalizePathName(const PathStringPiece& pathName);
355+ bool comparePathNames(const PathStringPiece& s1, const PathStringPiece& s2);
356+ /// @}
351357
352- // free function
358+ /// @defgroup Free Functions Related to Document and File Path Name
359+ /// @{
353360 std::pair<std::string, bool> insertFileContents(Document& document,
354- const Position& at, const PathString& fileName, const std::string& encoding,
361+ const Position& at, const PathStringPiece& fileName, const std::string& encoding,
355362 encoding::Encoder::SubstitutionPolicy encodingSubstitutionPolicy, Position* endOfInsertedString = nullptr);
356363 void writeRegion(const Document& document, const Region& region,
357- const PathString& fileName, const WritingFormat& format, bool append = false);
364+ const PathStringPiece& fileName, const WritingFormat& format, bool append = false);
365+ /// @}
358366
359367 /// Returns the file name.
360368 inline const PathString& TextFileStreamBuffer::fileName() const BOOST_NOEXCEPT {return fileName_;}
diff -r 8257513d0169 -r 45f9de52a43c ascension/src/kernel/fileio.cpp
--- a/ascension/src/kernel/fileio.cpp Sat May 11 12:12:08 2013 +0900
+++ b/ascension/src/kernel/fileio.cpp Sun May 12 12:25:13 2013 +0900
@@ -10,6 +10,8 @@
1010 #include <ascension/config.hpp> // ASCENSION_NO_STANDARD_ENCODINGS
1111 #include <ascension/kernel/fileio.hpp>
1212 #include <boost/range/algorithm/copy.hpp>
13+#include <boost/range/algorithm/find.hpp>
14+#include <boost/range/algorithm/find_first_of.hpp>
1315 #include <limits> // std.numeric_limits
1416 #ifdef ASCENSION_OS_POSIX
1517 # include <cstdio> // std.tempnam
@@ -29,30 +31,37 @@
2931 // free function //////////////////////////////////////////////////////////////////////////////////
3032
3133 namespace {
34+ inline void sanityCheckPathName(const PathStringPiece& s, const std::string& variableName) {
35+ if(s.cbegin() == nullptr || s.cend() == nullptr)
36+ throw NullPointerException(variableName);
37+ if(s.cbegin() > s.cend())
38+ throw invalid_argument(variableName + ".cbegin() > " + variableName + ".cend()");
39+ }
40+}
41+
42+namespace {
3243 #ifdef ASCENSION_OS_WINDOWS
33- static const PathCharacter PATH_SEPARATORS[] = {0x005cu, 0x002fu, 0}; // \ or /
44+ static const array<PathCharacter, 2> PATH_SEPARATORS = {0x005cu, 0x002fu}; // \ or /
3445 #else // ASCENSION_OS_POSIX
35- static const PathCharacter PATH_SEPARATORS[] = "/";
46+ static const array<PathCharacter, 1> PATH_SEPARATORS = {'/'};
3647 #endif
3748 static const PathCharacter PREFERRED_PATH_SEPARATOR = PATH_SEPARATORS[0];
3849 /// Returns @c true if the given character is a path separator.
39- inline bool isPathSeparator(PathCharacter c) /*noexcept*/ {
40- return find(PATH_SEPARATORS, ASCENSION_ENDOF(PATH_SEPARATORS) - 1, c) != ASCENSION_ENDOF(PATH_SEPARATORS) - 1;}
50+ inline bool isPathSeparator(PathCharacter c) BOOST_NOEXCEPT {
51+ return boost::find(PATH_SEPARATORS, c) != boost::end(PATH_SEPARATORS);
52+ }
4153 /**
4254 * Returns @c true if the specified file or directory exists.
4355 * @param name the name of the file
4456 * @return @c true if the file exists
45- * @throw NullPointerException @a fileName is @c null
4657 * @throw IOException any I/O error occurred
4758 */
48- bool pathExists(const PathCharacter* name) {
49- if(name == nullptr)
50- throw NullPointerException("name");
59+ bool pathExists(const PathStringPiece& name) {
5160 #ifdef ASCENSION_OS_WINDOWS
5261 #ifdef PathFileExists
53- return toBoolean(::PathFileExistsW(name));
62+ return win32::boole(::PathFileExistsW(name.cbegin()));
5463 #else
55- if(::GetFileAttributesW(name) != INVALID_FILE_ATTRIBUTES)
64+ if(::GetFileAttributesW(name.cbegin()) != INVALID_FILE_ATTRIBUTES)
5665 return true;
5766 const DWORD e = ::GetLastError();
5867 if(e == ERROR_FILE_NOT_FOUND || e == ERROR_PATH_NOT_FOUND
@@ -70,9 +79,8 @@
7079 }
7180
7281 /// Finds the base name in the given file path name.
73- inline PathString::const_iterator findFileName(const PathString& s) {
74- const PathString::size_type i = s.find_last_of(PATH_SEPARATORS);
75- return begin(s) + ((i != PathString::npos) ? i + 1 : 0);
82+ inline PathStringPiece::const_iterator findFileName(const PathStringPiece& s) {
83+ return s.cbegin() + distance(boost::find_first_of(s | boost::adaptors::reversed, PATH_SEPARATORS), boost::rend(s));
7684 }
7785
7886 /**
@@ -81,14 +89,14 @@
8189 * @param[out] timeStamp The time
8290 * @throw IOException Any I/O error occurred
8391 */
84- void getFileLastWriteTime(const PathString& fileName, TextFileDocumentInput::Time& timeStamp) {
92+ void getFileLastWriteTime(const PathStringPiece& fileName, TextFileDocumentInput::Time& timeStamp) {
8593 #ifdef ASCENSION_OS_WINDOWS
8694 WIN32_FILE_ATTRIBUTE_DATA attributes;
87- if(::GetFileAttributesExW(fileName.c_str(), GetFileExInfoStandard, &attributes) != 0)
95+ if(::GetFileAttributesExW(fileName.cbegin(), GetFileExInfoStandard, &attributes) != 0)
8896 timeStamp = attributes.ftLastWriteTime;
8997 #else // ASCENSION_OS_POSIX
9098 struct stat s;
91- if(::stat(fileName.c_str(), &s) == 0)
99+ if(::stat(fileName.cbegin(), &s) == 0)
92100 timeStamp = s.st_mtime;
93101 #endif
94102 else
@@ -99,21 +107,18 @@
99107 * Returns the size of the specified file.
100108 * @param fileName The name of the file
101109 * @return The size of the file in bytes or -1 if the file is too large
102- * @throw NullPointerException @a fileName is @c null
103110 * @throw IOException Any I/O error occurred
104111 */
105- ptrdiff_t getFileSize(const PathCharacter* fileName) {
106- if(fileName == nullptr)
107- throw NullPointerException("fileName");
112+ ptrdiff_t getFileSize(const PathStringPiece& fileName) {
108113 #ifdef ASCENSION_OS_WINDOWS
109114 WIN32_FILE_ATTRIBUTE_DATA attributes;
110- if(::GetFileAttributesExW(fileName, GetFileExInfoStandard, &attributes) != 0)
115+ if(::GetFileAttributesExW(fileName.cbegin(), GetFileExInfoStandard, &attributes) != 0)
111116 return (attributes.nFileSizeHigh == 0
112117 && attributes.nFileSizeLow <= static_cast<DWORD>(numeric_limits<ptrdiff_t>::max())) ?
113118 static_cast<ptrdiff_t>(attributes.nFileSizeLow) : -1;
114119 #else // ASCENSION_OS_POSIX
115120 struct stat s;
116- if(::stat(fileName, &s) == 0)
121+ if(::stat(fileName.cbegin(), &s) == 0)
117122 return s.st_size;
118123 #endif
119124 else
@@ -127,16 +132,18 @@
127132 * @throw std#bad_alloc POSIX @c tempnam failed (only when @c ASCENSION_OS_POSIX was defined)
128133 * @throw IOException Any I/O error occurred
129134 */
130- PathString makeTemporaryFileName(const PathString& seed) {
131- unique_ptr<PathCharacter[]> s(new PathCharacter[seed.length() + 1]);
132- boost::copy(seed, s.get());
133- s[seed.length()] = 0;
134- PathCharacter* const name = s.get() + (findFileName(seed) - begin(seed));
135- if(name != s.get())
136- name[-1] = 0;
135+ PathString makeTemporaryFileName(const PathStringPiece& seed) {
136+#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
137+ PathString s(seed);
138+#else
139+ PathString s(begin(seed), end(seed));
140+#endif
141+ const PathString::const_iterator name(s.cbegin() + distance(seed.cbegin(), findFileName(seed)));
142+ if(name != s.cbegin())
143+ s.resize(distance(s.cbegin(), name) - 1);
137144 #ifdef ASCENSION_OS_WINDOWS
138145 WCHAR result[MAX_PATH];
139- if(::GetTempFileNameW(s.get(), name, 0, result) != 0)
146+ if(::GetTempFileNameW(s.c_str(), s.data() + distance(s.cbegin(), name), 0, result) != 0)
140147 return result;
141148 #else // ASCENSION_OS_POSIX
142149 if(char* p = ::tempnam(s.get(), name)) {
@@ -154,9 +161,9 @@
154161 * @param fileName The file name
155162 * @throw IOException Any I/O error occurred
156163 */
157- bool isSpecialFile(const PathString& fileName) {
164+ bool isSpecialFile(const PathStringPiece& fileName) {
158165 #ifdef ASCENSION_OS_WINDOWS
159- HANDLE file = ::CreateFileW(fileName.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
166+ HANDLE file = ::CreateFileW(fileName.cbegin(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
160167 if(file != INVALID_HANDLE_VALUE) {
161168 const DWORD fileType = ::GetFileType(file);
162169 ::CloseHandle(file);
@@ -172,7 +179,7 @@
172179 }
173180 #else // ASCENSION_OS_POSIX
174181 struct stat s;
175- if(::stat(fileName.c_str(), &s) == 0)
182+ if(::stat(fileName.cbegin(), &s) == 0)
176183 return !S_ISREG(s.st_mode);
177184 #endif
178185 else
@@ -220,60 +227,70 @@
220227 * @throw NullPointerException @a pathName is @c null
221228 * @see comparePathNames
222229 */
223-PathString fileio::canonicalizePathName(const PathCharacter* pathName) {
224- if(pathName == nullptr)
225- throw NullPointerException("pathName");
230+PathString fileio::canonicalizePathName(const PathStringPiece& pathName) {
231+ sanityCheckPathName(pathName, "pathName");
226232
227233 #ifdef ASCENSION_OS_WINDOWS
228234
229- if(wcslen(pathName) >= MAX_PATH) // too long name
230- return pathName;
235+ if(pathName.length() >= MAX_PATH) // too long name
236+#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
237+ return PathString(pathName);
238+#else
239+ return PathString(begin(pathName), end(pathName));
240+#endif
231241
232242 // resolve relative path name
233- WCHAR path[MAX_PATH];
243+ array<WCHAR, MAX_PATH> fullName;
234244 WCHAR* dummy;
235- if(::GetFullPathNameW(pathName, ASCENSION_COUNTOF(path), path, &dummy) == 0)
236- wcscpy(path, pathName);
245+ if(::GetFullPathNameW(pathName.cbegin(), fullName.size(), fullName.data(), &dummy) == 0)
246+ wcscpy(fullName.data(), pathName.cbegin());
237247
238248 // get real component names (from Ftruename implementation in xyzzy)
239249 PathString result;
240250 result.reserve(MAX_PATH);
241- const PathCharacter* p = path;
242- if(((p[0] >= L'A' && p[0] <= L'Z') || (p[0] >= L'a' && p[0] <= L'z'))
243- && p[1] == L':' && isPathSeparator(p[2])) { // drive letter
244- result.append(path, 3);
245- result[0] = towupper(path[0]); // unify with uppercase letters...
246- p += 3;
247- } else if(isPathSeparator(p[0]) && isPathSeparator(p[1])) { // UNC?
248- if((p = wcspbrk(p + 2, PATH_SEPARATORS)) == nullptr) // server name
251+ auto view(boost::make_iterator_range(fullName));
252+ if(((view[0] >= L'A' && view[0] <= L'Z') || (view[0] >= L'a' && view[0] <= L'z'))
253+ && view[1] == L':' && isPathSeparator(view[2])) { // drive letter
254+ result.append(fullName.data(), 3);
255+ result[0] = towupper(fullName[0]); // unify with uppercase letters...
256+ view.advance_begin(+3);
257+ } else if(all_of(begin(view), begin(view) + 1, &isPathSeparator)) { // UNC?
258+ view = boost::make_iterator_range(boost::find_first_of(view.advance_begin(+2), PATH_SEPARATORS), end(view));
259+ if(view.empty()) // server name
249260 return false;
250- if((p = wcspbrk(p + 1, PATH_SEPARATORS)) == nullptr) // shared name
261+ view = boost::make_iterator_range(boost::find_first_of(view.advance_begin(+1), PATH_SEPARATORS), end(view));
262+ if(view.empty()) // shared name
251263 return false;
252- result.append(path, ++p - path);
264+ result.append(begin(fullName), begin(view.advance_begin(+1)));
253265 } else // not absolute name
254- return pathName;
266+#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
267+ return PathString(pathName);
268+#else
269+ return PathString(begin(pathName), end(pathName));
270+#endif
255271
256272 WIN32_FIND_DATAW wfd;
257273 while(true) {
258- if(PathCharacter* next = wcspbrk(const_cast<PathCharacter*>(p), PATH_SEPARATORS)) {
274+ auto next = boost::find_first_of(view, PATH_SEPARATORS);
275+ if(next != end(view)) {
259276 const PathCharacter c = *next;
260277 *next = 0;
261- HANDLE h = ::FindFirstFileW(path, &wfd);
278+ HANDLE h = ::FindFirstFileW(fullName.data(), &wfd);
262279 if(h != INVALID_HANDLE_VALUE) {
263280 ::FindClose(h);
264281 result += wfd.cFileName;
265282 } else
266- result += p;
283+ result.append(begin(view), end(view));
267284 *next = c;
268285 result += PREFERRED_PATH_SEPARATOR;
269- p = next + 1;
286+ view = boost::make_iterator_range(next + 1, end(view));
270287 } else {
271- HANDLE h = ::FindFirstFileW(path, &wfd);
288+ HANDLE h = ::FindFirstFileW(fullName.data(), &wfd);
272289 if(h != INVALID_HANDLE_VALUE) {
273290 ::FindClose(h);
274291 result += wfd.cFileName;
275292 } else
276- result += p;
293+ result.append(begin(view), end(view));
277294 break;
278295 }
279296 }
@@ -295,32 +312,32 @@
295312 * @throw NullPointerException Either file name is @c null
296313 * @see canonicalizePathName
297314 */
298-bool fileio::comparePathNames(const PathCharacter* s1, const PathCharacter* s2) {
299- if(s1 == nullptr || s2 == nullptr)
300- throw NullPointerException("either file name is null.");
315+bool fileio::comparePathNames(const PathStringPiece& s1, const PathStringPiece& s2) {
316+ sanityCheckPathName(s1, "s1");
317+ sanityCheckPathName(s2, "s2");
301318
302319 #ifdef ASCENSION_OS_WINDOWS
303320 #ifdef PathMatchSpec
304- if(toBoolean(::PathMatchSpecW(s1, s2)))
321+ if(win32::boole(::PathMatchSpecW(s1, s2)))
305322 return true;
306323 #endif // PathMatchSpec
307324 // by lexicographical comparison
308- const int c1 = static_cast<int>(wcslen(s1)) + 1, c2 = static_cast<int>(wcslen(s2)) + 1;
309- const int fc1 = ::LCMapStringW(LOCALE_NEUTRAL, LCMAP_LOWERCASE, s1, c1, nullptr, 0);
310- const int fc2 = ::LCMapStringW(LOCALE_NEUTRAL, LCMAP_LOWERCASE, s2, c2, nullptr, 0);
325+ const int c1 = static_cast<int>(s1.length()) + 1, c2 = static_cast<int>(s2.length()) + 1;
326+ const int fc1 = ::LCMapStringW(LOCALE_NEUTRAL, LCMAP_LOWERCASE, s1.cbegin(), c1, nullptr, 0);
327+ const int fc2 = ::LCMapStringW(LOCALE_NEUTRAL, LCMAP_LOWERCASE, s2.cbegin(), c2, nullptr, 0);
311328 if(fc1 != 0 && fc2 != 0 && fc1 == fc2) {
312329 unique_ptr<WCHAR[]> fs1(new WCHAR[fc1]), fs2(new WCHAR[fc2]);
313- ::LCMapStringW(LOCALE_NEUTRAL, LCMAP_LOWERCASE, s1, c1, fs1.get(), fc1);
314- ::LCMapStringW(LOCALE_NEUTRAL, LCMAP_LOWERCASE, s2, c2, fs2.get(), fc2);
330+ ::LCMapStringW(LOCALE_NEUTRAL, LCMAP_LOWERCASE, s1.cbegin(), c1, fs1.get(), fc1);
331+ ::LCMapStringW(LOCALE_NEUTRAL, LCMAP_LOWERCASE, s2.cbegin(), c2, fs2.get(), fc2);
315332 if(wmemcmp(fs1.get(), fs2.get(), fc1) == 0)
316333 return pathExists(s1);
317334 }
318335 // by volume information
319336 bool eq = false;
320- HANDLE f1 = ::CreateFileW(s1, 0,
337+ HANDLE f1 = ::CreateFileW(s1.cbegin(), 0,
321338 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
322339 if(f1 != INVALID_HANDLE_VALUE) {
323- HANDLE f2 = ::CreateFileW(s2, 0,
340+ HANDLE f2 = ::CreateFileW(s2.cbegin(), 0,
324341 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
325342 if(f2 != INVALID_HANDLE_VALUE) {
326343 BY_HANDLE_FILE_INFORMATION fi1;
@@ -338,11 +355,11 @@
338355 return eq;
339356 #else // ASCENSION_OS_POSIX
340357 // by lexicographical comparison
341- if(strcmp(s1, s2) == 0)
358+ if(boost::lexicographical_compare(s1, s2) == 0)
342359 return true;
343360 // by volume information
344361 struct stat st1, st2;
345- return ::stat(s1, &st1) == 0 && ::stat(s2, &st2) == 0
362+ return ::stat(s1.cbegin(), &st1) == 0 && ::stat(s2.cbegin(), &st2) == 0
346363 && st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino
347364 && st1.st_size == st2.st_size && st1.st_mtime == st2.st_mtime;
348365 #endif
@@ -364,7 +381,7 @@
364381 * @throw ... Any exceptions @c TextFileStreamBuffer#TextFileStreamBuffer and @c kernel#insert throw
365382 */
366383 pair<string, bool> fileio::insertFileContents(Document& document,
367- const Position& at, const PathString& fileName, const string& encoding,
384+ const Position& at, const PathStringPiece& fileName, const string& encoding,
368385 Encoder::SubstitutionPolicy encodingSubstitutionPolicy, Position* endOfInsertedString /* = nullptr */) {
369386 TextFileStreamBuffer sb(fileName, ios_base::in, encoding, encodingSubstitutionPolicy, false);
370387 basic_istream<Char> in(&sb);
@@ -391,7 +408,7 @@
391408 * @throw ... Any I/O error occurred
392409 */
393410 void fileio::writeRegion(const Document& document, const Region& region,
394- const PathString& fileName, const WritingFormat& format, bool append /* = false */) {
411+ const PathStringPiece& fileName, const WritingFormat& format, bool append /* = false */) {
395412 // verify encoding-specific newline
396413 verifyNewline(format.encoding, format.newline);
397414
@@ -405,7 +422,7 @@
405422
406423 // check if writable
407424 #ifdef ASCENSION_OS_WINDOWS
408- const DWORD originalAttributes = ::GetFileAttributesW(fileName.c_str());
425+ const DWORD originalAttributes = ::GetFileAttributesW(fileName.cbegin());
409426 if(originalAttributes != INVALID_FILE_ATTRIBUTES && win32::boole(originalAttributes & FILE_ATTRIBUTE_READONLY))
410427 throw IOException(fileName, ERROR_ACCESS_DENIED);
411428 #else // ASCENSION_OS_POSIX
@@ -441,15 +458,15 @@
441458 /**
442459 * Constructor.
443460 */
444-IOException::IOException(const PathString& fileName) :
445- ios_base::failure(makePlatformError().what(), makePlatformError().code()), fileName_(fileName) {
461+IOException::IOException(const PathStringPiece& fileName) :
462+ ios_base::failure(makePlatformError().what(), makePlatformError().code()), fileName_(fileName.cbegin(), fileName.cend()) {
446463 }
447464
448465 /**
449466 * Constructor.
450467 */
451-IOException::IOException(const PathString& fileName, error_code::value_type code) :
452- ios_base::failure(makePlatformError(code).what(), makePlatformError(code).code()), fileName_(fileName) {
468+IOException::IOException(const PathStringPiece& fileName, error_code::value_type code) :
469+ ios_base::failure(makePlatformError(code).what(), makePlatformError(code).code()), fileName_(fileName.cbegin(), fileName.cend()) {
453470 }
454471
455472 /// Returns the file name.
@@ -522,10 +539,10 @@
522539 * @throw UnsupportedEncodingException The encoding specified by @a encoding is not supported
523540 * @throw PlatformDependentIOError
524541 */
525-TextFileStreamBuffer::TextFileStreamBuffer(const PathString& fileName, ios_base::openmode mode,
542+TextFileStreamBuffer::TextFileStreamBuffer(const PathStringPiece& fileName, ios_base::openmode mode,
526543 const string& encoding, Encoder::SubstitutionPolicy encodingSubstitutionPolicy,
527- bool writeUnicodeByteOrderMark) : fileName_(fileName), mode_(mode) {
528- inputMapping_.first = inputMapping_.last = inputMapping_.current = nullptr;
544+ bool writeUnicodeByteOrderMark) : fileName_(fileName.cbegin(), fileName.cend()), mode_(mode) {
545+ sanityCheckPathName(fileName, "fileName");
529546 if(mode == ios_base::in)
530547 openForReading(encoding);
531548 else if(mode == ios_base::out
@@ -554,7 +571,7 @@
554571 else if(detectEncoding) {
555572 if(EncodingDetector* detector = EncodingDetector::forName(encoding)) {
556573 const pair<MIBenum, string> detected(detector->detect(
557- inputMapping_.first, min(inputMapping_.last, inputMapping_.first + 1024 * 10), nullptr));
574+ begin(inputMapping_.buffer), min(end(inputMapping_.buffer), begin(inputMapping_.buffer) + 1024 * 10), nullptr));
558575 if(detected.first != MIB_OTHER)
559576 encoder_ = Encoder::forMIB(detected.first);
560577 else
@@ -574,18 +591,17 @@
574591 fileMapping_ = ::CreateFileMappingW(fileHandle_, nullptr, PAGE_READONLY, 0, 0, nullptr);
575592 if(fileMapping_ == nullptr)
576593 throw IOException(fileName());
577- inputMapping_.first = static_cast<const Byte*>(::MapViewOfFile(fileMapping_, FILE_MAP_READ, 0, 0, 0));
578- if(inputMapping_.first == nullptr) {
594+ inputMapping_.buffer = boost::make_iterator_range<const Byte*>(static_cast<const Byte*>(::MapViewOfFile(fileMapping_, FILE_MAP_READ, 0, 0, 0)), nullptr);
595+ if(begin(inputMapping_.buffer) == nullptr) {
579596 SystemErrorSaver ses;
580597 ::CloseHandle(fileMapping_);
581598 throw IOException(fileName(), ses.code());
582599 }
583600 } else
584601 fileMapping_ = nullptr;
585- inputMapping_.last = inputMapping_.first + fileSize;
586602 #else // ASCENSION_OS_POSIX
587- inputMapping_.first = static_cast<const Byte*>(::mmap(0, fileSize, PROT_READ, MAP_PRIVATE, fileDescriptor_, 0));
588- if(inputMapping_.first == MAP_FAILED)
603+ inputMapping_.buffer = boost::make_iterator_range<const Byte*>(static_cast<const Byte*>(::mmap(0, fileSize, PROT_READ, MAP_PRIVATE, fileDescriptor_, 0)), nullptr);
604+ if(begin(inputMapping_.buffer) == MAP_FAILED)
589605 throw IOException(fileName());
590606 bool succeeded = false;
591607 off_t org = ::lseek(fileDescriptor_, 0, SEEK_CUR);
@@ -598,9 +614,9 @@
598614 }
599615 if(!succeeded)
600616 throw IOException(fileName());
601- inputMapping_.last = inputMapping_.first + fileSize;
602617 #endif
603- inputMapping_.current = inputMapping_.first;
618+ inputMapping_.buffer = boost::make_iterator_range(begin(inputMapping_.buffer), begin(inputMapping_.buffer) + fileSize);
619+ inputMapping_.current = begin(inputMapping_.buffer);
604620 }
605621
606622 /**
@@ -647,9 +663,9 @@
647663 TextFileStreamBuffer* TextFileStreamBuffer::closeFile() BOOST_NOEXCEPT {
648664 #ifdef ASCENSION_OS_WINDOWS
649665 if(fileMapping_ != nullptr) {
650- ::UnmapViewOfFile(const_cast<Byte*>(inputMapping_.first));
666+ ::UnmapViewOfFile(const_cast<Byte*>(begin(inputMapping_.buffer)));
651667 ::CloseHandle(fileMapping_);
652- inputMapping_.first = nullptr;
668+ inputMapping_.buffer = boost::make_iterator_range<const Byte*>(nullptr, nullptr);
653669 fileMapping_ = nullptr;
654670 }
655671 if(fileHandle_ != INVALID_HANDLE_VALUE) {
@@ -668,11 +684,11 @@
668684 return this;
669685 }
670686 #endif
671- if(encoder_.get() != 0) {
687+ if(encoder_.get() != nullptr) {
672688 encoder_->resetEncodingState();
673689 encoder_->resetDecodingState();
674690 }
675- return 0; // didn't close the file actually
691+ return nullptr; // didn't close the file actually
676692 }
677693
678694 /**
@@ -763,7 +779,7 @@
763779 if((mode() & ios_base::app) != 0)
764780 buildInputMapping();
765781 else
766- inputMapping_.first = nullptr;
782+ inputMapping_.buffer = boost::make_iterator_range<const Byte*>(nullptr, nullptr);
767783 buildEncoder(encoding, (mode() & ios_base::app) != 0);
768784 } catch(...) {
769785 closeFile();
@@ -772,12 +788,12 @@
772788
773789 if(writeUnicodeByteOrderMark)
774790 encoder_->setFlags(encoder_->flags() | Encoder::UNICODE_BYTE_ORDER_MARK);
775- setp(ucsBuffer_, ASCENSION_ENDOF(ucsBuffer_));
791+ setp(ucsBuffer_.data(), ucsBuffer_.data() + ucsBuffer_.size());
776792 }
777793
778794 /// @see std#basic_streambuf#overflow
779795 TextFileStreamBuffer::int_type TextFileStreamBuffer::overflow(int_type c) {
780- if(inputMapping_.first != nullptr || sync() == -1)
796+ if(begin(inputMapping_.buffer) != nullptr || sync() == -1)
781797 return traits_type::eof(); // not output mode or can't synchronize
782798
783799 *pptr() = traits_type::to_char_type(c);
@@ -787,7 +803,7 @@
787803
788804 /// @see std#basic_streambuf#pbackfail
789805 TextFileStreamBuffer::int_type TextFileStreamBuffer::pbackfail(int_type c) {
790- if(inputMapping_.first != nullptr) {
806+ if(begin(inputMapping_.buffer) != nullptr) {
791807 if(gptr() > eback()) {
792808 gbump(-1);
793809 return traits_type::not_eof(c); // c is ignored
@@ -799,17 +815,17 @@
799815 /// std#basic_streambuf#sync
800816 int TextFileStreamBuffer::sync() {
801817 // this method converts ucsBuffer_ into the native encoding and writes
802- if(isOpen() && inputMapping_.first == nullptr && pptr() > pbase()) {
818+ if(isOpen() && begin(inputMapping_.buffer) == nullptr && pptr() > pbase()) {
803819 Byte* toNext;
804820 const Char* fromNext;
805- Byte nativeBuffer[ASCENSION_COUNTOF(ucsBuffer_)];
821+ array<Byte, tuple_size<decltype(ucsBuffer_)>::value> nativeBuffer;
806822 encoder_->setFlags(encoder_->flags() | Encoder::BEGINNING_OF_BUFFER | Encoder::END_OF_BUFFER);
807823 while(true) {
808824 const Char* const fromEnd = pptr();
809825
810826 // conversion
811827 const Encoder::Result encodingResult = encoder_->fromUnicode(
812- nativeBuffer, ASCENSION_ENDOF(nativeBuffer), toNext, pbase(), fromEnd, fromNext);
828+ nativeBuffer.data(), nativeBuffer.data() + nativeBuffer.size(), toNext, pbase(), fromEnd, fromNext);
813829 if(encodingResult == Encoder::UNMAPPABLE_CHARACTER)
814830 throw UnmappableCharacterException();
815831 else if(encodingResult == Encoder::MALFORMED_INPUT)
@@ -818,9 +834,9 @@
818834 // write into the file
819835 #ifdef ASCENSION_OS_WINDOWS
820836 DWORD writtenBytes;
821- assert(static_cast<size_t>(toNext - nativeBuffer) <= numeric_limits<DWORD>::max());
822- const DWORD bytes = static_cast<DWORD>(toNext - nativeBuffer);
823- if(::WriteFile(fileHandle_, nativeBuffer, bytes, &writtenBytes, 0) == 0 || writtenBytes != bytes)
837+ assert(static_cast<size_t>(toNext - nativeBuffer.data()) <= numeric_limits<DWORD>::max());
838+ const DWORD bytes = static_cast<DWORD>(toNext - nativeBuffer.data());
839+ if(::WriteFile(fileHandle_, nativeBuffer.data(), bytes, &writtenBytes, 0) == 0 || writtenBytes != bytes)
824840 #else // ASCENSION_OS_POSIX
825841 const size_t bytes = toNext - nativeBuffer;
826842 const ssize_t writtenBytes = ::write(fileDescriptor_, nativeBuffer, bytes);
@@ -828,25 +844,25 @@
828844 #endif
829845 throw IOException(fileName());
830846
831- setp(ucsBuffer_ + (fromNext - ucsBuffer_), epptr());
847+ setp(ucsBuffer_.data() + (fromNext - ucsBuffer_.data()), epptr());
832848 pbump(static_cast<int>(fromEnd - pbase())); // TODO: this cast may be danger.
833849 if(encodingResult == Encoder::COMPLETED)
834850 break;
835851 }
836- setp(ucsBuffer_, ASCENSION_ENDOF(ucsBuffer_));
852+ setp(ucsBuffer_.data(), ucsBuffer_.data() + ucsBuffer_.size());
837853 }
838854 return 0;
839855 }
840856
841857 /// @see std#basic_streambuf#underflow
842858 TextFileStreamBuffer::int_type TextFileStreamBuffer::underflow() {
843- if(inputMapping_.first == nullptr || inputMapping_.current >= inputMapping_.last)
859+ if(begin(inputMapping_.buffer) == nullptr || inputMapping_.current >= end(inputMapping_.buffer))
844860 return traits_type::eof(); // not input mode or reached EOF
845861
846862 Char* toNext;
847863 const Byte* fromNext;
848864 encoder_->setFlags(encoder_->flags() | Encoder::BEGINNING_OF_BUFFER | Encoder::END_OF_BUFFER);
849- switch(encoder_->toUnicode(ucsBuffer_, ASCENSION_ENDOF(ucsBuffer_), toNext, inputMapping_.current, inputMapping_.last, fromNext)) {
865+ switch(encoder_->toUnicode(ucsBuffer_.data(), ucsBuffer_.data() + ucsBuffer_.size(), toNext, inputMapping_.current, end(inputMapping_.buffer), fromNext)) {
850866 case Encoder::UNMAPPABLE_CHARACTER:
851867 throw UnmappableCharacterException();
852868 case Encoder::MALFORMED_INPUT:
@@ -856,8 +872,8 @@
856872 }
857873
858874 inputMapping_.current = fromNext;
859- setg(ucsBuffer_, ucsBuffer_, toNext);
860- return (toNext > ucsBuffer_) ? traits_type::to_int_type(*gptr()) : traits_type::eof();
875+ setg(ucsBuffer_.data(), ucsBuffer_.data(), toNext);
876+ return (toNext > ucsBuffer_.data()) ? traits_type::to_int_type(*gptr()) : traits_type::eof();
861877 }
862878
863879 /// Returns @c true if the internal encoder has @c Encoder#UNICODE_BYTE_ORDER_MARK flag.
@@ -921,6 +937,7 @@
921937 * @throw IOException
922938 */
923939 bool TextFileDocumentInput::FileLocker::lock(const PathString& fileName, bool share) {
940+ sanityCheckPathName(fileName, "fileName");
924941 if(fileName.empty())
925942 #ifdef ASCENSION_OS_WINDOWS
926943 throw IOException(fileName, ERROR_FILE_NOT_FOUND);
@@ -1096,12 +1113,13 @@
10961113 *
10971114 * @param fileName
10981115 */
1099-void TextFileDocumentInput::bind(const PathString& fileName) {
1116+void TextFileDocumentInput::bind(const PathStringPiece& fileName) {
1117+ sanityCheckPathName(fileName, "fileName");
11001118 if(fileName.empty())
11011119 return unbind();
11021120
1103- const PathString realName(canonicalizePathName(fileName.c_str()));
1104- if(!pathExists(realName.c_str()))
1121+ const PathString realName(canonicalizePathName(fileName));
1122+ if(!pathExists(realName))
11051123 #ifdef ASCENSION_OS_WINDOWS
11061124 throw IOException(fileName, ERROR_FILE_NOT_FOUND);
11071125 #else // ASCENSION_OS_POSIX
@@ -1180,7 +1198,7 @@
11801198 }
11811199
11821200 /// @see IDocumentInput#location
1183-String TextFileDocumentInput::location() const /*noexcept*/ {
1201+String TextFileDocumentInput::location() const BOOST_NOEXCEPT {
11841202 #ifdef ASCENSION_OS_WINDOWS
11851203 return fileName();
11861204 #else // ASCENSION_OS_POSIX
@@ -1386,6 +1404,7 @@
13861404
13871405 /*
13881406 void backupAtRecycleBin(const PathString& fileName) {
1407+ sanityCheckPathName(fileName, "fileName");
13891408 if(pathExists(fileName.c_str())) {
13901409 WCHAR backupPath[MAX_PATH + 1];
13911410 SHFILEOPSTRUCTW shfos = {
@@ -1520,7 +1539,7 @@
15201539 // DirectoryIterator ////////////////////////////////////////////////////////
15211540
15221541 namespace {
1523- inline bool isDotOrDotDot(const PathString& s) {
1542+ inline bool isDotOrDotDot(const PathStringPiece& s) {
15241543 return !s.empty() && s[0] == '.' && (s.length() == 1 || (s.length() == 2 && s[1] == '.'));
15251544 }
15261545 } // namespace @0
@@ -1531,16 +1550,15 @@
15311550 * @throw NullPointerException @a directoryName is @c null
15321551 * @throw IOException Any I/O error occurred
15331552 */
1534-DirectoryIterator::DirectoryIterator(const PathCharacter* directoryName) :
1553+DirectoryIterator::DirectoryIterator(const PathStringPiece& directoryName) :
15351554 #ifdef ASCENSION_OS_WINDOWS
15361555 handle_(INVALID_HANDLE_VALUE),
15371556 #else // ASCENSION_OS_POSIX
15381557 handle_(0),
15391558 #endif
15401559 done_(false) {
1541- if(directoryName == nullptr)
1542- throw NullPointerException("directoryName");
1543- else if(directoryName[0] == 0)
1560+ sanityCheckPathName(directoryName, "directoryName");
1561+ if(directoryName[0] == 0)
15441562 #ifdef ASCENSION_OS_WINDOWS
15451563 throw IOException(directoryName, ERROR_PATH_NOT_FOUND);
15461564 #else // ASCENSION_OS_POSIX
@@ -1550,19 +1568,18 @@
15501568 #ifdef ASCENSION_OS_WINDOWS
15511569 if(!pathExists(directoryName))
15521570 throw IOException(directoryName, ERROR_PATH_NOT_FOUND);
1553- const size_t len = wcslen(directoryName);
1554- assert(len > 0);
1555- unique_ptr<PathCharacter[]> pattern(new PathCharacter[len + 3]);
1556- wmemcpy(pattern.get(), directoryName, len);
1557- wcscpy(pattern.get() + len, isPathSeparator(pattern[len - 1]) ? L"*" : L"\\*");
1571+ PathString pattern;
1572+ pattern.reserve(directoryName.length() + 2);
1573+ pattern.assign(begin(directoryName), end(directoryName));
1574+ pattern.append(isPathSeparator(pattern.back()) ? L"*" : L"\\*");
15581575 WIN32_FIND_DATAW data;
1559- handle_ = ::FindFirstFileW(pattern.get(), &data);
1576+ handle_ = ::FindFirstFileW(pattern.c_str(), &data);
15601577 if(handle_ == INVALID_HANDLE_VALUE)
15611578 throw IOException(directoryName);
15621579 update(&data);
1563- directory_.assign(pattern.get(), isPathSeparator(pattern[len - 1]) ? len - 1 : len);
1580+ directory_.assign(pattern.c_str(), isPathSeparator(pattern[directoryName.length() - 1]) ? directoryName.length() - 1 : directoryName.length());
15641581 #else // ASCENSION_OS_POSIX
1565- handle_ = ::opendir(directoryName);
1582+ handle_ = ::opendir(directoryName.cbegin());
15661583 if(handle_ == 0)
15671584 throw IOException(directoryName);
15681585 update(0);
@@ -1654,7 +1671,7 @@
16541671 * @throw IOException Can be @c IOException#FILE_NOT_FOUND or
16551672 * @c IOException#PLATFORM_DEPENDENT_ERROR
16561673 */
1657-RecursiveDirectoryIterator::RecursiveDirectoryIterator(const PathCharacter* directoryName) : doesntPushNext_(false) {
1674+RecursiveDirectoryIterator::RecursiveDirectoryIterator(const PathStringPiece& directoryName) : doesntPushNext_(false) {
16581675 stack_.push(new DirectoryIterator(directoryName));
16591676 }
16601677
Show on old repository browser