21#if defined (_WIN32) && !defined (USE_WINDOWS_API)
22#define USE_WINDOWS_API 1
23#elif !defined (USE_WINDOWS_API)
24#define USE_WINDOWS_API 0
30#if (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) \
31 || (!defined(_MSVC_LANG) && (__cplusplus < 201703L))
32#error "UTF8 requires c++17 or newer if not using Windows API functions"
43 enum cause { invalid_utf8=1, invalid_wchar, invalid_char32 };
51 const char*
what() const noexcept
53 return (
code == cause::invalid_utf8) ?
"Invalid UTF-8 encoding"
54 : (
code == cause::invalid_wchar) ?
"Invalid UTF-16 encoding"
55 : (
code == cause::invalid_char32) ?
"Invalid code-point value"
56 :
"Other UTF-8 exception";
69action error_mode (action mode);
77std::string
narrow (
const wchar_t* s,
size_t nch=0);
78std::string
narrow (
const std::wstring& s);
79std::string
narrow (
const char32_t* s,
size_t nch = 0);
80std::string
narrow (
const std::u32string& s);
81std::string
narrow (
char32_t r);
83std::wstring
widen (
const char* s,
size_t nch = 0);
84std::wstring
widen (
const std::string& s);
85std::u32string
runes (
const char* s,
size_t nch = 0);
86std::u32string
runes (
const std::string& s);
88char32_t rune (
const char* p);
89char32_t rune (
const std::string::const_iterator& p);
93bool is_valid (std::string::const_iterator p,
const std::string::const_iterator last);
94bool valid_str (
const char* s,
size_t nch = 0);
97char32_t next (std::string::const_iterator& ptr,
const std::string::const_iterator last);
98char32_t next (std::string::iterator& ptr,
const std::string::const_iterator last);
99char32_t next (
const char*& ptr);
100char32_t next (
char*& p);
102char32_t prev (
const char*& ptr);
103char32_t prev (
char*& ptr);
104char32_t prev (std::string::const_iterator& ptr,
const std::string::const_iterator first);
105char32_t prev (std::string::iterator& ptr,
const std::string::const_iterator first);
107size_t length (
const std::string& s);
108size_t length (
const char* s);
116std::string
tolower (
const std::string& str);
117std::string
toupper (
const std::string& str);
118int icompare (
const std::string& s1,
const std::string& s2);
128bool isspace (std::string::const_iterator p);
132bool isblank (std::string::const_iterator p);
136bool isdigit (std::string::const_iterator p);
140bool isalnum (std::string::const_iterator p);
144bool isalpha (std::string::const_iterator p);
148bool isxdigit (std::string::const_iterator p);
152bool isupper (std::string::const_iterator p);
156bool islower (std::string::const_iterator p);
161class ifstream :
public std::ifstream
165 explicit ifstream (
const char* filename, std::ios_base::openmode mode = ios_base::in)
166 : std::ifstream (utf8::
widen (filename), mode) {};
167 explicit ifstream (
const std::string& filename, std::ios_base::openmode mode = ios_base::in)
169 ifstream (ifstream&& other) noexcept : std::ifstream ((std::ifstream&&)other) {};
170 ifstream (
const ifstream& rhs) =
delete;
172 void open (
const char* filename, std::ios_base::openmode mode = ios_base::in)
174 std::ifstream::open (
utf8::widen (filename), mode);
176 void open (
const std::string& filename, ios_base::openmode mode = ios_base::in)
178 std::ifstream::open (
utf8::widen (filename), mode);
182class ofstream :
public std::ofstream
185 ofstream () : std::ofstream () {};
186 explicit ofstream (
const char* filename, std::ios_base::openmode mode = ios_base::out)
187 : std::ofstream (utf8::
widen (filename), mode) {};
188 explicit ofstream (
const std::string& filename, std::ios_base::openmode mode = ios_base::out)
189 : std::ofstream (utf8::
widen (filename), mode) {};
190 ofstream (ofstream&& other) noexcept : std::ofstream ((std::ofstream&&)other) {};
191 ofstream (
const ofstream& rhs) =
delete;
193 void open (
const char* filename, ios_base::openmode mode = ios_base::out)
195 std::ofstream::open (
utf8::widen (filename), mode);
197 void open (
const std::string& filename, ios_base::openmode mode = ios_base::out)
199 std::ofstream::open (
utf8::widen (filename), mode);
204class fstream :
public std::fstream
207 fstream () : std::fstream () {};
208 explicit fstream (
const char* filename, std::ios_base::openmode mode = ios_base::in | ios_base::out)
209 : std::fstream (utf8::
widen (filename), mode) {};
210 explicit fstream (
const std::string& filename, std::ios_base::openmode mode = ios_base::in | ios_base::out)
211 : std::fstream (utf8::
widen (filename), mode) {};
212 fstream (fstream&& other) noexcept : std::fstream ((std::fstream&&)other) {};
213 fstream (
const fstream& rhs) =
delete;
215 void open (
const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out)
219 void open (
const std::string& filename, ios_base::openmode mode = ios_base::in | ios_base::out)
228typedef std::ofstream ofstream;
229typedef std::fstream fstream;
244 auto prev_mode =
error_mode (action::replace);
258bool is_valid (std::string::const_iterator p,
const std::string::const_iterator last)
261 auto prev_mode =
error_mode (action::replace);
269char32_t next (std::string::iterator& ptr,
const std::string::const_iterator last)
271 return next (*(std::string::const_iterator*)(&ptr), last);
276char32_t prev (std::string::iterator& ptr,
const std::string::const_iterator first)
278 return prev (*(std::string::const_iterator*)(&ptr), first);
308 return next (
const_cast<const char*&
>(ptr));
323 return prev (
const_cast<const char*&
>(ptr));
340char32_t rune (
const std::string::const_iterator& p)
401 return '0' <= r && r <=
'9';
430 return (
'0' <= r && r <=
'9') || (
'A' <= r && r <=
'Z') || (
'a' <= r && r <=
'z');
459 return (
'A' <= r && r <=
'Z') || (
'a' <= r && r <=
'z');
489 return (
'0' <= r && r <=
'9') || (
'A' <= r && r <=
'F') || (
'a' <= r && r <=
'f');
534FILE*
fopen (
const std::string& filename,
const std::string& mode)
538 _wfopen_s (&h,
widen (filename).c_str (),
widen (mode).c_str ());
540 h = ::fopen (filename.c_str(), mode.c_str());
547FILE*
fopen (
const char* filename,
const char* mode)
551 _wfopen_s (&h,
widen (filename).c_str (),
widen (mode).c_str ());
553 h = ::fopen (filename, mode);
566 wchar_t tmp[_MAX_PATH];
567 if (_wgetcwd (tmp, _countof (tmp)))
570 return std::string ();
573 std::filesystem::path wd = std::filesystem::current_path (ec);
575 return std::string ();
577 return narrow (wd.native());
591bool chdir (
const std::string& dirname)
594 return (_wchdir (
widen (dirname).c_str ()) == 0);
597 std::filesystem::path dir (
widen (dirname));
599 std::filesystem::path dir (dirname);
602 std::filesystem::current_path (dir, ec);
612 return (_wchdir (
widen (dirname).c_str ()) == 0);
615 std::filesystem::path dir (
widen (dirname));
617 std::filesystem::path dir (dirname);
620 std::filesystem::current_path (dir, ec);
633bool mkdir (
const std::string& dirname)
636 return (_wmkdir (
widen (dirname).c_str ()) == 0);
639 std::filesystem::path dir (
widen (dirname));
641 std::filesystem::path dir (dirname);
644 std::filesystem::create_directory (dir, ec);
655 return (_wmkdir (
widen (dirname).c_str ()) == 0);
658 std::filesystem::path dir (
widen (dirname));
660 std::filesystem::path dir (dirname);
663 std::filesystem::create_directory (dir, ec);
675bool rmdir (
const std::string& dirname)
678 return (_wrmdir (
widen (dirname).c_str ()) == 0);
681 std::filesystem::path dir (
widen (dirname));
683 std::filesystem::path dir (dirname);
686 std::filesystem::remove (dir, ec);
696 return (_wrmdir (
widen (dirname).c_str ()) == 0);
699 std::filesystem::path dir (
widen (dirname));
701 std::filesystem::path dir (dirname);
704 std::filesystem::remove (dir, ec);
717bool rename (
const std::string& oldname,
const std::string& newname)
720 return (_wrename (
widen (oldname).c_str (),
widen (newname).c_str ()) == 0);
723 std::filesystem::path fn (
widen (newname));
724 std::filesystem::path fo (
widen (oldname));
726 std::filesystem::path fn (newname);
727 std::filesystem::path fo (oldname);
730 std::filesystem::rename (fo, fn, ec);
737bool rename (
const char* oldname,
const char* newname)
740 return (_wrename (
widen (oldname).c_str (),
widen (newname).c_str ()) == 0);
743 std::filesystem::path fn (
widen (newname));
744 std::filesystem::path fo (
widen (oldname));
746 std::filesystem::path fn (newname);
747 std::filesystem::path fo (oldname);
750 std::filesystem::rename (fo, fn, ec);
765 return (_wremove (
widen (filename).c_str ()) == 0);
768 std::filesystem::path f (
widen(filename));
770 std::filesystem::path f (filename);
773 std::filesystem::remove (f, ec);
784 return (_wremove (
widen (filename).c_str ()) == 0);
787 std::filesystem::path f (
widen (filename));
789 std::filesystem::path f (filename);
792 std::filesystem::remove (f, ec);
816 return !operator ==(lhs, rhs);
827#pragma comment (lib, "utf8")
std::u32string runes(const char *s, size_t nch)
Conversion from UTF-8 to UTF-32.
Definition utf8.cpp:287
std::string narrow(const wchar_t *s, size_t nch)
Conversion from wide character to UTF-8.
Definition utf8.cpp:52
char32_t rune(const char *p)
Conversion from UTF-8 to UTF-32.
Definition utf8.h:289
std::wstring widen(const char *s, size_t nch)
Conversion from UTF-8 to wide character.
Definition utf8.cpp:207
bool islower(char32_t r)
Definition casecvt.cpp:48
bool isspace(char32_t r)
Check if character is white space.
Definition utf8.cpp:688
bool isalnum(char32_t r)
Check if character is an alphanumeric character (0-9 or A-Z or a-z)
Definition utf8.h:428
bool isalpha(char32_t r)
Check if character is an alphabetic character (A-Z or a-z)
Definition utf8.h:457
bool isxdigit(char32_t r)
Check if character is a hexadecimal digit (0-9 or A-F or a-f)
Definition utf8.h:487
bool isblank(char32_t r)
Check if character is space or tab.
Definition utf8.cpp:671
bool isupper(char32_t r)
Definition casecvt.cpp:106
bool isdigit(char32_t r)
Check if character is a decimal digit (0-9)
Definition utf8.h:399
void make_lower(std::string &str)
In place version converts a UTF-8 encoded string to lowercase.
Definition casecvt.cpp:99
std::string tolower(const std::string &str)
Convert UTF-8 string to lower case.
Definition casecvt.cpp:76
std::string toupper(const std::string &str)
Convert a UTF-8 string to upper case.
Definition casecvt.cpp:133
void make_upper(std::string &str)
In place version converts a UTF-8 encoded string to lowercase.
Definition casecvt.cpp:156
Exception thrown on encoding/decoding failure.
Definition utf8.h:41
const char * what() const noexcept
Exception message.
Definition utf8.h:51
exception(cause c)
Constructor.
Definition utf8.h:46
cause
Possible causes.
Definition utf8.h:43
cause code
Condition that triggered the exception.
Definition utf8.h:59
bool valid_str(const char *s, size_t nch)
Verifies if string is a valid UTF-8 string.
Definition utf8.cpp:333
action error_mode(action mode)
Set error handling mode for this thread.
Definition utf8.cpp:22
char32_t next(std::string::const_iterator &ptr, const std::string::const_iterator last)
Decodes a UTF-8 encoded character and advances iterator to next code point.
Definition utf8.cpp:359
char32_t prev(const char *&ptr)
Decrements a character pointer to previous UTF-8 character.
Definition utf8.cpp:519
size_t length(const std::string &s)
Counts number of characters in an UTF8 encoded string.
Definition utf8.cpp:609
bool is_valid(const char *p)
Check if pointer points to a valid UTF-8 encoding.
Definition utf8.h:242
std::ifstream ifstream
Input stream class using UTF-8 filename.
Definition utf8.h:227
const char32_t REPLACEMENT_CHARACTER
Replacement character used for invalid encodings.
Definition utf8.h:72
std::ostream & operator<<(std::ostream &os, const exception &x)
Extraction operator for exception objects.
Definition utf8.h:799
action
Error handling methods.
Definition utf8.h:63
@ replace
Use replacement character for invalid encodings.
Definition utf8.h:64
@ except
Throw an exception on invalid encodings.
Definition utf8.h:65
bool chdir(const std::string &dirname)
Changes the current working directory.
Definition utf8.h:591
bool rename(const std::string &oldname, const std::string &newname)
Rename a file or directory.
Definition utf8.h:717
bool remove(const std::string &filename)
Delete a file.
Definition utf8.h:762
std::string getcwd()
Gets the current working directory.
Definition utf8.h:563
FILE * fopen(const std::string &filename, const std::string &mode)
Open a file.
Definition utf8.h:534
bool mkdir(const std::string &dirname)
Creates a new directory.
Definition utf8.h:633
bool rmdir(const std::string &dirname)
Deletes a directory.
Definition utf8.h:675