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::u32string
runes (
const char* s,
size_t nch = 0);
95std::u32string
runes (
const std::string& s);
97char32_t rune (
const char* p);
98char32_t rune (
const std::string::const_iterator& p);
102bool is_valid (std::string::const_iterator p,
const std::string::const_iterator last);
103bool valid_str (
const char* s,
size_t nch = 0);
106char32_t next (std::string::const_iterator& ptr,
const std::string::const_iterator last);
107char32_t next (std::string::iterator& ptr,
const std::string::const_iterator last);
108char32_t next (
const char*& ptr);
109char32_t next (
char*& p);
111char32_t prev (
const char*& ptr);
112char32_t prev (
char*& ptr);
113char32_t prev (std::string::const_iterator& ptr,
const std::string::const_iterator first);
114char32_t prev (std::string::iterator& ptr,
const std::string::const_iterator first);
116size_t length (
const std::string& s);
117size_t length (
const char* s);
125std::string
tolower (
const std::string& str);
126std::string
toupper (
const std::string& str);
127int icompare (
const std::string& s1,
const std::string& s2);
137bool isspace (std::string::const_iterator p);
141bool isblank (std::string::const_iterator p);
145bool isdigit (std::string::const_iterator p);
149bool isalnum (std::string::const_iterator p);
153bool isalpha (std::string::const_iterator p);
157bool isxdigit (std::string::const_iterator p);
161bool isupper (std::string::const_iterator p);
165bool islower (std::string::const_iterator p);
170class ifstream :
public std::ifstream
174 explicit ifstream (
const char* filename, std::ios_base::openmode mode = ios_base::in)
175 : std::ifstream (utf8::
widen (filename), mode) {};
176 explicit ifstream (
const std::string& filename, std::ios_base::openmode mode = ios_base::in)
178 ifstream (ifstream&& other) noexcept : std::ifstream ((std::ifstream&&)other) {};
179 ifstream (
const ifstream& rhs) =
delete;
181 void open (
const char* filename, std::ios_base::openmode mode = ios_base::in)
183 std::ifstream::open (
utf8::widen (filename), mode);
185 void open (
const std::string& filename, ios_base::openmode mode = ios_base::in)
187 std::ifstream::open (
utf8::widen (filename), mode);
191class ofstream :
public std::ofstream
194 ofstream () : std::ofstream () {};
195 explicit ofstream (
const char* filename, std::ios_base::openmode mode = ios_base::out)
196 : std::ofstream (utf8::
widen (filename), mode) {};
197 explicit ofstream (
const std::string& filename, std::ios_base::openmode mode = ios_base::out)
198 : std::ofstream (utf8::
widen (filename), mode) {};
199 ofstream (ofstream&& other) noexcept : std::ofstream ((std::ofstream&&)other) {};
200 ofstream (
const ofstream& rhs) =
delete;
202 void open (
const char* filename, ios_base::openmode mode = ios_base::out)
204 std::ofstream::open (
utf8::widen (filename), mode);
206 void open (
const std::string& filename, ios_base::openmode mode = ios_base::out)
208 std::ofstream::open (
utf8::widen (filename), mode);
213class fstream :
public std::fstream
216 fstream () : std::fstream () {};
217 explicit fstream (
const char* filename, std::ios_base::openmode mode = ios_base::in | ios_base::out)
218 : std::fstream (utf8::
widen (filename), mode) {};
219 explicit fstream (
const std::string& filename, std::ios_base::openmode mode = ios_base::in | ios_base::out)
220 : std::fstream (utf8::
widen (filename), mode) {};
221 fstream (fstream&& other) noexcept : std::fstream ((std::fstream&&)other) {};
222 fstream (
const fstream& rhs) =
delete;
224 void open (
const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out)
228 void open (
const std::string& filename, ios_base::openmode mode = ios_base::in | ios_base::out)
237typedef std::ofstream ofstream;
238typedef std::fstream fstream;
253 auto prev_mode =
error_mode (action::replace);
267bool is_valid (std::string::const_iterator p,
const std::string::const_iterator last)
270 auto prev_mode =
error_mode (action::replace);
278char32_t next (std::string::iterator& ptr,
const std::string::const_iterator last)
280 return next (*(std::string::const_iterator*)(&ptr), last);
285char32_t prev (std::string::iterator& ptr,
const std::string::const_iterator first)
287 return prev (*(std::string::const_iterator*)(&ptr), first);
317 return next (
const_cast<const char*&
>(ptr));
332 return prev (
const_cast<const char*&
>(ptr));
349char32_t rune (
const std::string::const_iterator& p)
410 return '0' <= r && r <=
'9';
439 return (
'0' <= r && r <=
'9') || (
'A' <= r && r <=
'Z') || (
'a' <= r && r <=
'z');
468 return (
'A' <= r && r <=
'Z') || (
'a' <= r && r <=
'z');
498 return (
'0' <= r && r <=
'9') || (
'A' <= r && r <=
'F') || (
'a' <= r && r <=
'f');
543FILE*
fopen (
const std::string& filename,
const std::string& mode)
547 _wfopen_s (&h,
widen (filename).c_str (),
widen (mode).c_str ());
549 h = ::fopen (filename.c_str(), mode.c_str());
556FILE*
fopen (
const char* filename,
const char* mode)
560 _wfopen_s (&h,
widen (filename).c_str (),
widen (mode).c_str ());
562 h = ::fopen (filename, mode);
574#if UTF8_USE_WINDOWS_API
575 wchar_t tmp[_MAX_PATH];
576 if (_wgetcwd (tmp, _countof (tmp)))
579 return std::string ();
582 std::filesystem::path wd = std::filesystem::current_path (ec);
584 return std::string ();
586 return narrow (wd.native());
600bool chdir (
const std::string& dirname)
602#if UTF8_USE_WINDOWS_API
603 return (_wchdir (
widen (dirname).c_str ()) == 0);
606 std::filesystem::path dir (
widen (dirname));
608 std::filesystem::path dir (dirname);
611 std::filesystem::current_path (dir, ec);
620#if UTF8_USE_WINDOWS_API
621 return (_wchdir (
widen (dirname).c_str ()) == 0);
624 std::filesystem::path dir (
widen (dirname));
626 std::filesystem::path dir (dirname);
629 std::filesystem::current_path (dir, ec);
642bool mkdir (
const std::string& dirname)
644#if UTF8_USE_WINDOWS_API
645 return (_wmkdir (
widen (dirname).c_str ()) == 0);
648 std::filesystem::path dir (
widen (dirname));
650 std::filesystem::path dir (dirname);
653 std::filesystem::create_directory (dir, ec);
663#if UTF8_USE_WINDOWS_API
664 return (_wmkdir (
widen (dirname).c_str ()) == 0);
667 std::filesystem::path dir (
widen (dirname));
669 std::filesystem::path dir (dirname);
672 std::filesystem::create_directory (dir, ec);
684bool rmdir (
const std::string& dirname)
686#if UTF8_USE_WINDOWS_API
687 return (_wrmdir (
widen (dirname).c_str ()) == 0);
690 std::filesystem::path dir (
widen (dirname));
692 std::filesystem::path dir (dirname);
695 std::filesystem::remove (dir, ec);
704#if UTF8_USE_WINDOWS_API
705 return (_wrmdir (
widen (dirname).c_str ()) == 0);
708 std::filesystem::path dir (
widen (dirname));
710 std::filesystem::path dir (dirname);
713 std::filesystem::remove (dir, ec);
726bool rename (
const std::string& oldname,
const std::string& newname)
728#if UTF8_USE_WINDOWS_API
729 return (_wrename (
widen (oldname).c_str (),
widen (newname).c_str ()) == 0);
732 std::filesystem::path fn (
widen (newname));
733 std::filesystem::path fo (
widen (oldname));
735 std::filesystem::path fn (newname);
736 std::filesystem::path fo (oldname);
739 std::filesystem::rename (fo, fn, ec);
746bool rename (
const char* oldname,
const char* newname)
748#if UTF8_USE_WINDOWS_API
749 return (_wrename (
widen (oldname).c_str (),
widen (newname).c_str ()) == 0);
752 std::filesystem::path fn (
widen (newname));
753 std::filesystem::path fo (
widen (oldname));
755 std::filesystem::path fn (newname);
756 std::filesystem::path fo (oldname);
759 std::filesystem::rename (fo, fn, ec);
773#if UTF8_USE_WINDOWS_API
774 return (_wremove (
widen (filename).c_str ()) == 0);
777 std::filesystem::path f (
widen(filename));
779 std::filesystem::path f (filename);
782 std::filesystem::remove (f, ec);
792#if UTF8_USE_WINDOWS_API
793 return (_wremove (
widen (filename).c_str ()) == 0);
796 std::filesystem::path f (
widen (filename));
798 std::filesystem::path f (filename);
801 std::filesystem::remove (f, ec);
825 return !operator ==(lhs, rhs);
830#if defined(_WIN32) && !defined(UTF8_KEEP_WIN32_API)
836#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:298
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:437
bool isalpha(char32_t r)
Check if character is an alphabetic character (A-Z or a-z)
Definition utf8.h:466
bool isxdigit(char32_t r)
Check if character is a hexadecimal digit (0-9 or A-F or a-f)
Definition utf8.h:496
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:408
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: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:251
std::ifstream ifstream
Input stream class using UTF-8 filename.
Definition utf8.h:236
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:808
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:600
bool rename(const std::string &oldname, const std::string &newname)
Rename a file or directory.
Definition utf8.h:726
bool remove(const std::string &filename)
Delete a file.
Definition utf8.h:771
std::string getcwd()
Gets the current working directory.
Definition utf8.h:572
FILE * fopen(const std::string &filename, const std::string &mode)
Open a file.
Definition utf8.h:543
bool mkdir(const std::string &dirname)
Creates a new directory.
Definition utf8.h:642
bool rmdir(const std::string &dirname)
Deletes a directory.
Definition utf8.h:684