windows fixes and proper UTF-8 conversion

This commit is contained in:
Jack Andersen 2015-08-29 19:07:00 -10:00 committed by Phillip Stephens
parent 1de67f30b8
commit 9b6fea36e3
9 changed files with 2197 additions and 44 deletions

View File

@ -6,9 +6,8 @@ set(YAML_VERSION_STRING "${YAML_VERSION_MAJOR}.${YAML_VERSION_MINOR}.${YAML_VERS
file(GLOB SRC src/*.c) file(GLOB SRC src/*.c)
include_directories(include win32) include_directories(include win32)
add_definitions(-DYAML_DECLARE_STATIC)
add_library(AthenaLibYaml STATIC ${SRC} include/yaml.h) add_library(AthenaLibYaml STATIC ${SRC} include/yaml.h)
set(YAML_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE PATH "YAML include path" FORCE) set(YAML_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE PATH "YAML include path" FORCE)
install(DIRECTORY include/ DESTINATION include/Athena COMPONENT yaml) #install(DIRECTORY include/ DESTINATION include/Athena COMPONENT yaml)
install(TARGETS AthenaLibYaml DESTINATION lib COMPONENT yaml) install(TARGETS AthenaLibYaml DESTINATION lib COMPONENT yaml)

View File

@ -26,7 +26,7 @@ extern "C" {
/** The public API declaration. */ /** The public API declaration. */
#ifdef _WIN32 #if 0 /* Disabled for Athena */
# if defined(YAML_DECLARE_STATIC) # if defined(YAML_DECLARE_STATIC)
# define YAML_DECLARE(type) type # define YAML_DECLARE(type) type
# elif defined(YAML_DECLARE_EXPORT) # elif defined(YAML_DECLARE_EXPORT)

View File

@ -7,6 +7,11 @@
* Any changes to the types or namespacing must be reflected in 'atdna/main.cpp' * Any changes to the types or namespacing must be reflected in 'atdna/main.cpp'
*/ */
#if _WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif
#include <string.h> #include <string.h>
#include <yaml.h> #include <yaml.h>
#include "DNA.hpp" #include "DNA.hpp"
@ -374,29 +379,44 @@ inline std::unique_ptr<YAMLNode> ValToNode(const char* val)
template <> template <>
inline std::wstring NodeToVal(const YAMLNode* node) inline std::wstring NodeToVal(const YAMLNode* node)
{ {
#if _WIN32
int len = MultiByteToWideChar(CP_UTF8, 0, node->m_scalarString.c_str(), node->m_scalarString.size(), nullptr, 0);
std::wstring retval(len, L'\0');
MultiByteToWideChar(CP_UTF8, 0, node->m_scalarString.c_str(), node->m_scalarString.size(), &retval[0], len);
return retval;
#else
std::wstring retval; std::wstring retval;
retval.reserve(node->m_scalarString.length()); retval.reserve(node->m_scalarString.length());
const char* buf = node->m_scalarString.c_str(); const char* buf = node->m_scalarString.c_str();
std::mbstate_t state = {};
while (*buf) while (*buf)
{ {
wchar_t wc; wchar_t wc;
buf += std::mbtowc(&wc, buf, MB_CUR_MAX); buf += std::mbrtowc(&wc, buf, MB_LEN_MAX, &state);
retval += wc; retval += wc;
} }
return retval; return retval;
#endif
} }
template <> template <>
inline std::unique_ptr<YAMLNode> ValToNode(const std::wstring& val) inline std::unique_ptr<YAMLNode> ValToNode(const std::wstring& val)
{ {
YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE);
#if _WIN32
int len = WideCharToMultiByte(CP_UTF8, 0, val.c_str(), val.size(), nullptr, 0, nullptr, nullptr);
ret->m_scalarString.assign(len, '\0');
WideCharToMultiByte(CP_UTF8, 0, val.c_str(), val.size(), &ret->m_scalarString[0], len, nullptr, nullptr);
#else
ret->m_scalarString.reserve(val.length()); ret->m_scalarString.reserve(val.length());
std::mbstate_t state = {};
for (wchar_t ch : val) for (wchar_t ch : val)
{ {
char mb[4]; char mb[MB_LEN_MAX];
int c = std::wctomb(mb, ch); int c = std::wcrtomb(mb, ch, &state);
ret->m_scalarString.append(mb, c); ret->m_scalarString.append(mb, c);
} }
#endif
return std::unique_ptr<YAMLNode>(ret); return std::unique_ptr<YAMLNode>(ret);
} }

View File

@ -64,10 +64,10 @@ namespace error
{ {
enum Level enum Level
{ {
MESSAGE, LevelMessage,
WARNING, LevelWarning,
ERROR, LevelError,
FATAL LevelFatal
}; };
} }
enum SeekOrigin enum SeekOrigin
@ -125,7 +125,7 @@ std::ostream& operator<<(std::ostream& os, const Athena::Endian& endian);
#define atDebug(fmt, ...) \ #define atDebug(fmt, ...) \
do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
if (__handler) \ if (__handler) \
__handler(Athena::error::MESSAGE, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ __handler(Athena::error::LevelMessage, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \
} while(0) } while(0)
#else #else
#define atDebug(fmt, ...) #define atDebug(fmt, ...)
@ -134,25 +134,25 @@ std::ostream& operator<<(std::ostream& os, const Athena::Endian& endian);
#define atMessage(fmt, ...) \ #define atMessage(fmt, ...) \
do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
if (__handler) \ if (__handler) \
__handler(Athena::error::MESSAGE, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ __handler(Athena::error::LevelMessage, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \
} while(0) } while(0)
#define atWarning(fmt, ...) \ #define atWarning(fmt, ...) \
do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
if (__handler) \ if (__handler) \
__handler(Athena::error::WARNING, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ __handler(Athena::error::LevelWarning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \
} while(0) } while(0)
#define atError(fmt, ...) \ #define atError(fmt, ...) \
do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
if (__handler) \ if (__handler) \
__handler(Athena::error::ERROR, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ __handler(Athena::error::LevelError, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \
} while(0) } while(0)
#define atFatal(fmt, ...) \ #define atFatal(fmt, ...) \
do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
if (__handler) \ if (__handler) \
__handler(Athena::error::FATAL, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \ __handler(Athena::error::LevelFatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt, ##__VA_ARGS__); \
} while(0) } while(0)
#elif defined(__GNUC__) #elif defined(__GNUC__)
@ -175,19 +175,19 @@ std::ostream& operator<<(std::ostream& os, const Athena::Endian& endian);
#define atWarning(fmt...) \ #define atWarning(fmt...) \
do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
if (__handler) \ if (__handler) \
__handler(Athena::error::WARNING, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ __handler(Athena::error::LevelWarning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \
} while(0) } while(0)
#define atError(fmt...) \ #define atError(fmt...) \
do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
if (__handler) \ if (__handler) \
__handler(Athena::error::ERROR, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ __handler(Athena::error::LevelError, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \
} while(0) } while(0)
#define atFatal(fmt...) \ #define atFatal(fmt...) \
do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \ do { atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
if (__handler) \ if (__handler) \
__handler(Athena::error::FATAL, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \ __handler(Athena::error::LevelFatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, fmt); \
} while(0) } while(0)
#endif // defined(__GNUC__) #endif // defined(__GNUC__)

View File

@ -1,6 +1,11 @@
#ifndef ISTREAMREADER_HPP #ifndef ISTREAMREADER_HPP
#define ISTREAMREADER_HPP #define ISTREAMREADER_HPP
#if _WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif
#include <memory> #include <memory>
#include <functional> #include <functional>
#include "IStream.hpp" #include "IStream.hpp"
@ -590,11 +595,12 @@ public:
*/ */
inline std::string readWStringAsString(atInt32 fixedLen = -1) inline std::string readWStringAsString(atInt32 fixedLen = -1)
{ {
std::string retval; #if _WIN32
std::wstring wstr;
atUint16 chr = readUint16(); atUint16 chr = readUint16();
atInt32 i; atInt32 i;
for (i = 0 ;; ++i) for (i=0 ;; ++i)
{ {
if (fixedLen >= 0 && i >= fixedLen - 1) if (fixedLen >= 0 && i >= fixedLen - 1)
break; break;
@ -602,12 +608,33 @@ public:
if (!chr) if (!chr)
break; break;
char mb[4]; wstr += chr;
int c = std::wctomb(mb, chr);
retval.append(mb, c);
chr = readUint16(); chr = readUint16();
} }
int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), nullptr, 0, nullptr, nullptr);
std::string retval(len, '\0');
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), &retval[0], len, nullptr, nullptr);
#else
std::string retval;
atUint16 chr = readUint16();
atInt32 i;
std::mbstate_t state = {};
for (i=0 ;; ++i)
{
if (fixedLen >= 0 && i >= fixedLen - 1)
break;
if (!chr)
break;
char mb[MB_LEN_MAX];
int c = std::wcrtomb(mb, chr, &state);
retval.append(mb, c);
chr = readUint16();
}
#endif
if (fixedLen >= 0 && i < fixedLen) if (fixedLen >= 0 && i < fixedLen)
seek(fixedLen - i); seek(fixedLen - i);
@ -616,11 +643,12 @@ public:
inline std::string readWStringAsStringLittle(atInt32 fixedLen = -1) inline std::string readWStringAsStringLittle(atInt32 fixedLen = -1)
{ {
std::string retval; #if _WIN32
std::wstring wstr;
atUint16 chr = readUint16Little(); atUint16 chr = readUint16Little();
atInt32 i; atInt32 i;
for (i = 0 ;; ++i) for (i=0 ;; ++i)
{ {
if (fixedLen >= 0 && i >= fixedLen - 1) if (fixedLen >= 0 && i >= fixedLen - 1)
break; break;
@ -628,12 +656,33 @@ public:
if (!chr) if (!chr)
break; break;
char mb[4]; wstr += chr;
int c = std::wctomb(mb, chr);
retval.append(mb, c);
chr = readUint16Little(); chr = readUint16Little();
} }
int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), nullptr, 0, nullptr, nullptr);
std::string retval(len, '\0');
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), &retval[0], len, nullptr, nullptr);
#else
std::string retval;
atUint16 chr = readUint16Little();
atInt32 i;
std::mbstate_t state = {};
for (i=0 ;; ++i)
{
if (fixedLen >= 0 && i >= fixedLen - 1)
break;
if (!chr)
break;
char mb[MB_LEN_MAX];
int c = std::wcrtomb(mb, chr, &state);
retval.append(mb, c);
chr = readUint16Little();
}
#endif
if (fixedLen >= 0 && i < fixedLen) if (fixedLen >= 0 && i < fixedLen)
seek(fixedLen - i); seek(fixedLen - i);
@ -642,10 +691,32 @@ public:
inline std::string readWStringAsStringBig(atInt32 fixedLen = -1) inline std::string readWStringAsStringBig(atInt32 fixedLen = -1)
{ {
#if _WIN32
std::wstring wstr;
atUint16 chr = readUint16Big();
atInt32 i;
for (i=0 ;; ++i)
{
if (fixedLen >= 0 && i >= fixedLen - 1)
break;
if (!chr)
break;
wstr += chr;
chr = readUint16Big();
}
int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), nullptr, 0, nullptr, nullptr);
std::string retval(len, '\0');
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), &retval[0], len, nullptr, nullptr);
#else
std::string retval; std::string retval;
atUint16 chr = readUint16Big(); atUint16 chr = readUint16Big();
atInt32 i; atInt32 i;
std::mbstate_t state = {};
for (i = 0 ;; ++i) for (i = 0 ;; ++i)
{ {
if (fixedLen >= 0 && i >= fixedLen - 1) if (fixedLen >= 0 && i >= fixedLen - 1)
@ -654,12 +725,12 @@ public:
if (!chr) if (!chr)
break; break;
char mb[4]; char mb[MB_LEN_MAX];
int c = std::wctomb(mb, chr); int c = std::wcrtomb(mb, chr, &state);
retval.append(mb, c); retval.append(mb, c);
chr = readUint16Big(); chr = readUint16Big();
} }
#endif
if (fixedLen >= 0 && i < fixedLen) if (fixedLen >= 0 && i < fixedLen)
seek(fixedLen - i); seek(fixedLen - i);

View File

@ -1,6 +1,11 @@
#ifndef ISTREAMWRITER_HPP #ifndef ISTREAMWRITER_HPP
#define ISTREAMWRITER_HPP #define ISTREAMWRITER_HPP
#if _WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif
#include "IStream.hpp" #include "IStream.hpp"
namespace Athena namespace Athena
@ -437,14 +442,42 @@ public:
inline void writeStringAsWString(const std::string& str, atInt32 fixedLen = -1) inline void writeStringAsWString(const std::string& str, atInt32 fixedLen = -1)
{ {
std::string tmpStr = "\xEF\xBB\xBF" + str; std::string tmpStr = "\xEF\xBB\xBF" + str;
const char* buf = tmpStr.c_str();
#if _WIN32
int len = MultiByteToWideChar(CP_UTF8, 0, tmpStr.c_str(), tmpStr.size(), nullptr, 0);
std::wstring retval(len, L'\0');
MultiByteToWideChar(CP_UTF8, 0, tmpStr.c_str(), tmpStr.size(), &retval[0], len);
if (fixedLen < 0)
{
for (wchar_t ch : retval)
{
if (ch != 0xFEFF)
writeUint16(ch);
}
writeUint16(0);
}
else
{
for (atInt32 i=0 ; i<fixedLen ; ++i)
{
wchar_t wc = retval[i];
if (wc == 0xFEFF)
{
--i;
continue;
}
writeUint16(wc);
}
}
#else
const char* buf = tmpStr.c_str();
std::mbstate_t state = {};
if (fixedLen < 0) if (fixedLen < 0)
{ {
while (*buf) while (*buf)
{ {
wchar_t wc; wchar_t wc;
buf += std::mbtowc(&wc, buf, MB_CUR_MAX); buf += std::mbrtowc(&wc, buf, MB_LEN_MAX, &state);
if (wc != 0xFEFF) if (wc != 0xFEFF)
writeUint16(wc); writeUint16(wc);
} }
@ -456,7 +489,7 @@ public:
{ {
wchar_t wc = 0; wchar_t wc = 0;
if (*buf) if (*buf)
buf += std::mbtowc(&wc, buf, MB_CUR_MAX); buf += std::mbrtowc(&wc, buf, MB_LEN_MAX, &state);
if (wc == 0xFEFF) if (wc == 0xFEFF)
{ {
@ -467,19 +500,48 @@ public:
writeUint16(wc); writeUint16(wc);
} }
} }
#endif
} }
inline void writeStringAsWStringLittle(const std::string& str, atInt32 fixedLen = -1) inline void writeStringAsWStringLittle(const std::string& str, atInt32 fixedLen = -1)
{ {
std::string tmpStr = "\xEF\xBB\xBF" + str; std::string tmpStr = "\xEF\xBB\xBF" + str;
const char* buf = tmpStr.c_str();
#if _WIN32
int len = MultiByteToWideChar(CP_UTF8, 0, tmpStr.c_str(), tmpStr.size(), nullptr, 0);
std::wstring retval(len, L'\0');
MultiByteToWideChar(CP_UTF8, 0, tmpStr.c_str(), tmpStr.size(), &retval[0], len);
if (fixedLen < 0)
{
for (wchar_t ch : retval)
{
if (ch != 0xFEFF)
writeUint16(ch);
}
writeUint16Little(0);
}
else
{
for (atInt32 i = 0; i<fixedLen; ++i)
{
wchar_t wc = retval[i];
if (wc == 0xFEFF)
{
--i;
continue;
}
writeUint16Little(wc);
}
}
#else
const char* buf = tmpStr.c_str();
std::mbstate_t state = {};
if (fixedLen < 0) if (fixedLen < 0)
{ {
while (*buf) while (*buf)
{ {
wchar_t wc; wchar_t wc;
buf += std::mbtowc(&wc, buf, MB_CUR_MAX); buf += std::mbrtowc(&wc, buf, MB_LEN_MAX, &state);
if (wc != 0xFEFF) if (wc != 0xFEFF)
writeUint16Little(wc); writeUint16Little(wc);
} }
@ -491,7 +553,7 @@ public:
{ {
wchar_t wc = 0; wchar_t wc = 0;
if (*buf) if (*buf)
buf += std::mbtowc(&wc, buf, MB_CUR_MAX); buf += std::mbrtowc(&wc, buf, MB_LEN_MAX, &state);
if (wc == 0xFEFF) if (wc == 0xFEFF)
{ {
@ -502,19 +564,48 @@ public:
writeUint16Little(wc); writeUint16Little(wc);
} }
} }
#endif
} }
inline void writeStringAsWStringBig(const std::string& str, atInt32 fixedLen = -1) inline void writeStringAsWStringBig(const std::string& str, atInt32 fixedLen = -1)
{ {
std::string tmpStr = "\xEF\xBB\xBF" + str; std::string tmpStr = "\xEF\xBB\xBF" + str;
const char* buf = tmpStr.c_str();
#if _WIN32
int len = MultiByteToWideChar(CP_UTF8, 0, tmpStr.c_str(), tmpStr.size(), nullptr, 0);
std::wstring retval(len, L'\0');
MultiByteToWideChar(CP_UTF8, 0, tmpStr.c_str(), tmpStr.size(), &retval[0], len);
if (fixedLen < 0)
{
for (wchar_t ch : retval)
{
if (ch != 0xFEFF)
writeUint16(ch);
}
writeUint16Big(0);
}
else
{
for (atInt32 i = 0; i<fixedLen; ++i)
{
wchar_t wc = retval[i];
if (wc == 0xFEFF)
{
--i;
continue;
}
writeUint16Big(wc);
}
}
#else
const char* buf = tmpStr.c_str();
std::mbstate_t state = {};
if (fixedLen < 0) if (fixedLen < 0)
{ {
while (*buf) while (*buf)
{ {
wchar_t wc; wchar_t wc;
buf += std::mbtowc(&wc, buf, MB_CUR_MAX); buf += std::mbrtowc(&wc, buf, MB_LEN_MAX, &state);
if (wc != 0xFEFF) if (wc != 0xFEFF)
writeUint16Big(wc); writeUint16Big(wc);
} }
@ -526,7 +617,7 @@ public:
{ {
wchar_t wc = 0; wchar_t wc = 0;
if (*buf) if (*buf)
buf += std::mbtowc(&wc, buf, MB_CUR_MAX); buf += std::mbrtowc(&wc, buf, MB_LEN_MAX, &state);
if (wc == 0xFEFF) if (wc == 0xFEFF)
{ {
@ -537,6 +628,7 @@ public:
writeUint16Big(wc); writeUint16Big(wc);
} }
} }
#endif
} }
/*! \brief Writes an string to the buffer and advances the buffer. /*! \brief Writes an string to the buffer and advances the buffer.

1971
include/yaml.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -175,7 +175,7 @@ static inline bool EmitKeyScalar(yaml_emitter_t* doc, const char* val)
if (!yaml_scalar_event_initialize(&event, nullptr, nullptr, (yaml_char_t*)val, if (!yaml_scalar_event_initialize(&event, nullptr, nullptr, (yaml_char_t*)val,
strlen(val), true, true, YAML_PLAIN_SCALAR_STYLE)) strlen(val), true, true, YAML_PLAIN_SCALAR_STYLE))
return false; return false;
return yaml_emitter_emit(doc, &event); return yaml_emitter_emit(doc, &event) != 0;
} }
static inline yaml_scalar_style_t ScalarStyle(const YAMLNode& node) static inline yaml_scalar_style_t ScalarStyle(const YAMLNode& node)

View File

@ -46,13 +46,13 @@ static void __defaultExceptionHandler(const Athena::error::Level& level, const c
std::string levelStr; std::string levelStr;
switch(level) switch(level)
{ {
case Athena::error::WARNING: case Athena::error::LevelWarning:
levelStr = "[WARNING] "; levelStr = "[WARNING] ";
break; break;
case Athena::error::ERROR: case Athena::error::LevelError:
levelStr = "[ERROR ] "; levelStr = "[ERROR ] ";
break; break;
case Athena::error::FATAL: case Athena::error::LevelFatal:
levelStr = "[FATAL ] "; levelStr = "[FATAL ] ";
break; break;
default: break; default: break;