30#if defined (_WIN32) && !defined (UTF8_USE_WINDOWS_API)
31#define UTF8_USE_WINDOWS_API 1
32#elif !defined (UTF8_USE_WINDOWS_API)
33#define UTF8_USE_WINDOWS_API 0
36#if !UTF8_USE_WINDOWS_API
39#if (defined(_MSVC_LANG) && _MSVC_LANG < 201703L) \
40 || (!defined(_MSVC_LANG) && (__cplusplus < 201703L))
41#error "UTF8 requires c++17 or newer if not using Windows API functions"
52 enum cause { invalid_utf8=1, invalid_wchar, invalid_char32 };
60 const char*
what() const noexcept
62 return (
code == cause::invalid_utf8) ?
"Invalid UTF-8 encoding"
63 : (
code == cause::invalid_wchar) ?
"Invalid UTF-16 encoding"
64 : (
code == cause::invalid_char32) ?
"Invalid code-point value"
65 :
"Other UTF-8 exception";
78action error_mode (action mode);
86std::string
narrow (
const wchar_t* s,
size_t nch=0);
87std::string
narrow (
const std::wstring& s);
88std::string
narrow (
const char32_t* s,
size_t nch = 0);
89std::string
narrow (
const std::u32string& s);
90std::string
narrow (
char32_t r);
92std::wstring
widen (
const char* s,
size_t nch = 0);
93std::wstring
widen (
const std::string& s);
94std::wstring
widen (
char32_t r);
96std::u32string
runes (
const char* s,
size_t nch = 0);
97std::u32string
runes (
const std::string& s);
99char32_t rune (
const char* p);
100char32_t rune (
const std::string::const_iterator& p);
104bool is_valid (std::string::const_iterator p,
const std::string::const_iterator last);
105bool valid_str (
const char* s,
size_t nch = 0);
108char32_t next (std::string::const_iterator& ptr,
const std::string::const_iterator last);
109char32_t next (std::string::iterator& ptr,
const std::string::const_iterator last);
110char32_t next (
const char*& ptr);
111char32_t next (
char*& p);
113char32_t prev (
const char*& ptr);
114char32_t prev (
char*& ptr);
115char32_t prev (std::string::const_iterator& ptr,
const std::string::const_iterator first);
116char32_t prev (std::string::iterator& ptr,
const std::string::const_iterator first);
118size_t length (
const std::string& s);
119size_t length (
const char* s);
127std::string
tolower (
const std::string& str);
128std::string
toupper (
const std::string& str);
129int icompare (
const std::string& s1,
const std::string& s2);
139bool isspace (std::string::const_iterator p);
143bool isblank (std::string::const_iterator p);
147bool isdigit (std::string::const_iterator p);
151bool isalnum (std::string::const_iterator p);
155bool isalpha (std::string::const_iterator p);
159bool isxdigit (std::string::const_iterator p);
163bool isupper (std::string::const_iterator p);
167bool islower (std::string::const_iterator p);
172class ifstream :
public std::ifstream
176 explicit ifstream (
const char* filename, std::ios_base::openmode mode = ios_base::in)
177 : std::ifstream (utf8::
widen (filename), mode) {};
178 explicit ifstream (
const std::string& filename, std::ios_base::openmode mode = ios_base::in)
180 ifstream (ifstream&& other) noexcept : std::ifstream ((std::ifstream&&)other) {};
181 ifstream (
const ifstream& rhs) =
delete;
183 void open (
const char* filename, std::ios_base::openmode mode = ios_base::in)
185 std::ifstream::open (
utf8::widen (filename), mode);
187 void open (
const std::string& filename, ios_base::openmode mode = ios_base::in)
189 std::ifstream::open (
utf8::widen (filename), mode);
193class ofstream :
public std::ofstream
196 ofstream () : std::ofstream () {};
197 explicit ofstream (
const char* filename, std::ios_base::openmode mode = ios_base::out)
198 : std::ofstream (utf8::
widen (filename), mode) {};
199 explicit ofstream (
const std::string& filename, std::ios_base::openmode mode = ios_base::out)
200 : std::ofstream (utf8::
widen (filename), mode) {};
201 ofstream (ofstream&& other) noexcept : std::ofstream ((std::ofstream&&)other) {};
202 ofstream (
const ofstream& rhs) =
delete;
204 void open (
const char* filename, ios_base::openmode mode = ios_base::out)
206 std::ofstream::open (
utf8::widen (filename), mode);
208 void open (
const std::string& filename, ios_base::openmode mode = ios_base::out)
210 std::ofstream::open (
utf8::widen (filename), mode);
215class fstream :
public std::fstream
218 fstream () : std::fstream () {};
219 explicit fstream (
const char* filename, std::ios_base::openmode mode = ios_base::in | ios_base::out)
220 : std::fstream (utf8::
widen (filename), mode) {};
221 explicit fstream (
const std::string& filename, std::ios_base::openmode mode = ios_base::in | ios_base::out)
222 : std::fstream (utf8::
widen (filename), mode) {};
223 fstream (fstream&& other) noexcept : std::fstream ((std::fstream&&)other) {};
224 fstream (
const fstream& rhs) =
delete;
226 void open (
const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out)
230 void open (
const std::string& filename, ios_base::openmode mode = ios_base::in | ios_base::out)
239typedef std::ofstream ofstream;
240typedef std::fstream fstream;
255 auto prev_mode =
error_mode (action::replace);
269bool is_valid (std::string::const_iterator p,
const std::string::const_iterator last)
272 auto prev_mode =
error_mode (action::replace);
280char32_t next (std::string::iterator& ptr,
const std::string::const_iterator last)
282 return next (*(std::string::const_iterator*)(&ptr), last);
287char32_t prev (std::string::iterator& ptr,
const std::string::const_iterator first)
289 return prev (*(std::string::const_iterator*)(&ptr), first);
319 return next (
const_cast<const char*&
>(ptr));
334 return prev (
const_cast<const char*&
>(ptr));
351char32_t rune (
const std::string::const_iterator& p)
412 return '0' <= r && r <=
'9';
441 return (
'0' <= r && r <=
'9') || (
'A' <= r && r <=
'Z') || (
'a' <= r && r <=
'z');
470 return (
'A' <= r && r <=
'Z') || (
'a' <= r && r <=
'z');
500 return (
'0' <= r && r <=
'9') || (
'A' <= r && r <=
'F') || (
'a' <= r && r <=
'f');
545FILE*
fopen (
const std::string& filename,
const std::string& mode)
549 _wfopen_s (&h,
widen (filename).c_str (),
widen (mode).c_str ());
551 h = ::fopen (filename.c_str(), mode.c_str());
558FILE*
fopen (
const char* filename,
const char* mode)
562 _wfopen_s (&h,
widen (filename).c_str (),
widen (mode).c_str ());
564 h = ::fopen (filename, mode);
576#if UTF8_USE_WINDOWS_API
577 wchar_t tmp[_MAX_PATH];
578 if (_wgetcwd (tmp, _countof (tmp)))
581 return std::string ();
584 std::filesystem::path wd = std::filesystem::current_path (ec);
586 return std::string ();
588 return narrow (wd.native());
602bool chdir (
const std::string& dirname)
604#if UTF8_USE_WINDOWS_API
605 return (_wchdir (
widen (dirname).c_str ()) == 0);
608 std::filesystem::path dir (
widen (dirname));
610 std::filesystem::path dir (dirname);
613 std::filesystem::current_path (dir, ec);
622#if UTF8_USE_WINDOWS_API
623 return (_wchdir (
widen (dirname).c_str ()) == 0);
626 std::filesystem::path dir (
widen (dirname));
628 std::filesystem::path dir (dirname);
631 std::filesystem::current_path (dir, ec);
644bool mkdir (
const std::string& dirname)
646#if UTF8_USE_WINDOWS_API
647 return (_wmkdir (
widen (dirname).c_str ()) == 0);
650 std::filesystem::path dir (
widen (dirname));
652 std::filesystem::path dir (dirname);
655 std::filesystem::create_directory (dir, ec);
665#if UTF8_USE_WINDOWS_API
666 return (_wmkdir (
widen (dirname).c_str ()) == 0);
669 std::filesystem::path dir (
widen (dirname));
671 std::filesystem::path dir (dirname);
674 std::filesystem::create_directory (dir, ec);
686bool rmdir (
const std::string& dirname)
688#if UTF8_USE_WINDOWS_API
689 return (_wrmdir (
widen (dirname).c_str ()) == 0);
692 std::filesystem::path dir (
widen (dirname));
694 std::filesystem::path dir (dirname);
697 std::filesystem::remove (dir, ec);
706#if UTF8_USE_WINDOWS_API
707 return (_wrmdir (
widen (dirname).c_str ()) == 0);
710 std::filesystem::path dir (
widen (dirname));
712 std::filesystem::path dir (dirname);
715 std::filesystem::remove (dir, ec);
728bool rename (
const std::string& oldname,
const std::string& newname)
730#if UTF8_USE_WINDOWS_API
731 return (_wrename (
widen (oldname).c_str (),
widen (newname).c_str ()) == 0);
734 std::filesystem::path fn (
widen (newname));
735 std::filesystem::path fo (
widen (oldname));
737 std::filesystem::path fn (newname);
738 std::filesystem::path fo (oldname);
741 std::filesystem::rename (fo, fn, ec);
748bool rename (
const char* oldname,
const char* newname)
750#if UTF8_USE_WINDOWS_API
751 return (_wrename (
widen (oldname).c_str (),
widen (newname).c_str ()) == 0);
754 std::filesystem::path fn (
widen (newname));
755 std::filesystem::path fo (
widen (oldname));
757 std::filesystem::path fn (newname);
758 std::filesystem::path fo (oldname);
761 std::filesystem::rename (fo, fn, ec);
775#if UTF8_USE_WINDOWS_API
776 return (_wremove (
widen (filename).c_str ()) == 0);
779 std::filesystem::path f (
widen(filename));
781 std::filesystem::path f (filename);
784 std::filesystem::remove (f, ec);
794#if UTF8_USE_WINDOWS_API
795 return (_wremove (
widen (filename).c_str ()) == 0);
798 std::filesystem::path f (
widen (filename));
800 std::filesystem::path f (filename);
803 std::filesystem::remove (f, ec);
827 return !operator ==(lhs, rhs);
832#if defined(_WIN32) && !defined(UTF8_KEEP_WIN32_API)
838#pragma comment (lib, "utf8")
std::u32string runes(const char *s, size_t nch)
Conversion from UTF-8 to UTF-32.
Definition utf8.cpp:308
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:300
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:709
bool isalnum(char32_t r)
Check if character is an alphanumeric character (0-9 or A-Z or a-z)
Definition utf8.h:439
bool isalpha(char32_t r)
Check if character is an alphabetic character (A-Z or a-z)
Definition utf8.h:468
bool isxdigit(char32_t r)
Check if character is a hexadecimal digit (0-9 or A-F or a-f)
Definition utf8.h:498
bool isblank(char32_t r)
Check if character is space or tab.
Definition utf8.cpp:692
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:410
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:50
const char * what() const noexcept
Exception message.
Definition utf8.h:60
exception(cause c)
Constructor.
Definition utf8.h:55
cause
Possible causes.
Definition utf8.h:52
cause code
Condition that triggered the exception.
Definition utf8.h:68
bool valid_str(const char *s, size_t nch)
Verifies if string is a valid UTF-8 string.
Definition utf8.cpp:354
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:380
char32_t prev(const char *&ptr)
Decrements a character pointer to previous UTF-8 character.
Definition utf8.cpp:540
size_t length(const std::string &s)
Counts number of characters in an UTF8 encoded string.
Definition utf8.cpp:630
bool is_valid(const char *p)
Check if pointer points to a valid UTF-8 encoding.
Definition utf8.h:253
std::ifstream ifstream
Input stream class using UTF-8 filename.
Definition utf8.h:238
const char32_t REPLACEMENT_CHARACTER
Replacement character used for invalid encodings.
Definition utf8.h:81
std::ostream & operator<<(std::ostream &os, const exception &x)
Extraction operator for exception objects.
Definition utf8.h:810
action
Error handling methods.
Definition utf8.h:72
@ replace
Use replacement character for invalid encodings.
Definition utf8.h:73
@ except
Throw an exception on invalid encodings.
Definition utf8.h:74
bool chdir(const std::string &dirname)
Changes the current working directory.
Definition utf8.h:602
bool rename(const std::string &oldname, const std::string &newname)
Rename a file or directory.
Definition utf8.h:728
bool remove(const std::string &filename)
Delete a file.
Definition utf8.h:773
std::string getcwd()
Gets the current working directory.
Definition utf8.h:574
FILE * fopen(const std::string &filename, const std::string &mode)
Open a file.
Definition utf8.h:545
bool mkdir(const std::string &dirname)
Creates a new directory.
Definition utf8.h:644
bool rmdir(const std::string &dirname)
Deletes a directory.
Definition utf8.h:686