Lots of changes in regards to strings, as follows:
Lots of changes in regards to strings, as follows:

* Removed my custom String class, as well as removed the really old
Unicode ConvertUTF, the UTF Converter, and the UTF Encode/Decode
functions.
* Replaced the above with using standard C++ std::wstring_convert and
std::codecvt_utf8.
* Added headers adapted from llvm's libc++ project for allowing the
above C++ classes to exist with GCC and Clang when libc++ isn't being
used.
* Used std::string over std::wstring whenever possible.
* Added header adapted from llvm's libc++ project to create special
versions of the ifstream and ofstream classes that would utilize _wfopen
on non-MSVC Windows compilers, so those compilers could access files on
Windows that use characters outside the current codepage.
* Removed the -static-libgcc and -static-libstdc++ flags from the
Makefile for non-MSVC builds. The generated DLLs will require extra DLLs
from either Cygwin or MinGW (whichever is used to compile), I've only
tested with MinGW and for some reason they crash Winamp on exit, I have
no idea why.

--- a/src/Makefile
+++ b/src/Makefile
@@ -20,17 +20,11 @@
 COMPILER:=	$(shell $(CXX) -v 2>/dev/stdout)
 
 CPPFLAGS+=	-std=gnu++11 -I$(SRCDIR)in_xsf_framework -I/g/Code/Winamp\ SDK -DWINAMP_PLUGIN -DUNICODE_INPUT_PLUGIN
-CXXFLAGS+=	-std=gnu++11 -pipe -Wall -Wctor-dtor-privacy -Wold-style-cast -Wextra -Wno-div-by-zero -Wfloat-equal -Wshadow -Winit-self -Wcast-qual -Wunreachable-code -Wabi -Woverloaded-virtual -Wno-long-long -I$(SRCDIR)in_xsf_framework -I/g/Code/Winamp\ SDK -DWINAMP_PLUGIN -DUNICODE_INPUT_PLUGIN
+CXXFLAGS+=	-std=gnu++11 -pipe -Wall -Wctor-dtor-privacy -Wold-style-cast -Wextra -Wno-div-by-zero -Wfloat-equal -Wshadow -Winit-self -Wcast-qual -Wunreachable-code -Wabi -Woverloaded-virtual -Wno-long-long -Wno-switch -I$(SRCDIR)in_xsf_framework -I/g/Code/Winamp\ SDK -DWINAMP_PLUGIN -DUNICODE_INPUT_PLUGIN
 ifeq (,$(findstring clang,$(COMPILER)))
 CXXFLAGS+=	-Wlogical-op
 endif
 LDFLAGS+=	-lz
-
-ifneq (,$(findstring MINGW,$(UNAME)))
-ifeq (,$(findstring clang,$(COMPILER)))
-LDFLAGS+=	-static-libgcc -static-libstdc++
-endif
-endif
 
 DLL_SRCS_template=	$(1)_SRCS:=	$$(sort $$($(1)_SRCS))
 DLL_OBJS_template=	$(1)_OBJS:=	$$(subst $(SRCDIR),,$$($(1)_SRCS:%.cpp=%.o))

--- a/src/in_2sf/XSFConfig_2SF.cpp
+++ b/src/in_2sf/XSFConfig_2SF.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - 2SF configuration
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
@@ -10,7 +10,6 @@
 #include "XSFPlayer.h"
 #include "XSFConfig.h"
 #include "convert.h"
-#include "BigSString.h"
 #include "desmume/NDSSystem.h"
 #include "desmume/version.h"
 
@@ -24,7 +23,7 @@
 {
 protected:
 	static unsigned initInterpolation;
-	static std::wstring initMutes;
+	static std::string initMutes;
 
 	friend class XSFConfig;
 	unsigned interpolation;
@@ -43,10 +42,10 @@
 };
 
 unsigned XSFConfig::initSampleRate = 44100;
-std::wstring XSFConfig::commonName = L"2SF Decoder";
-std::wstring XSFConfig::versionNumber = L"0.9b";
+std::string XSFConfig::commonName = "2SF Decoder";
+std::string XSFConfig::versionNumber = "0.9b";
 unsigned XSFConfig_2SF::initInterpolation = 2;
-std::wstring XSFConfig_2SF::initMutes = L"0000000000000000";
+std::string XSFConfig_2SF::initMutes = "0000000000000000";
 
 XSFConfig *XSFConfig::Create()
 {
@@ -60,15 +59,15 @@
 
 void XSFConfig_2SF::LoadSpecificConfig()
 {
-	this->interpolation = this->configIO->GetValue(L"Interpolation", XSFConfig_2SF::initInterpolation);
-	std::wstringstream mutesSS(this->configIO->GetValue(L"Mutes", XSFConfig_2SF::initMutes));
+	this->interpolation = this->configIO->GetValue("Interpolation", XSFConfig_2SF::initInterpolation);
+	std::stringstream mutesSS(this->configIO->GetValue("Mutes", XSFConfig_2SF::initMutes));
 	mutesSS >> this->mutes;
 }
 
 void XSFConfig_2SF::SaveSpecificConfig()
 {
-	this->configIO->SetValue(L"Interpolation", this->interpolation);
-	this->configIO->SetValue(L"Mutes", this->mutes.to_string<wchar_t>());
+	this->configIO->SetValue("Interpolation", this->interpolation);
+	this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
 }
 
 void XSFConfig_2SF::GenerateSpecificDialogs()
@@ -132,7 +131,7 @@
 
 void XSFConfig_2SF::About(HWND parent)
 {
-	MessageBoxW(parent, (XSFConfig::commonName + L" v" + XSFConfig::versionNumber + L", using xSF Winamp plugin framework (based on the vio*sf plugins) by Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]\n\n"
-		L"Utilizes modified " + String(EMU_DESMUME_NAME_AND_VERSION()).GetWStr() + L" for audio playback.").c_str(), (XSFConfig::commonName + L" v" + XSFConfig::versionNumber).c_str(), MB_OK);
+	MessageBoxW(parent, ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber + ", using xSF Winamp plugin framework (based on the vio*sf plugins) by Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]\n\n"
+		"Utilizes modified " + EMU_DESMUME_NAME_AND_VERSION() + " for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
 }
 

--- a/src/in_2sf/XSFPlayer_2SF.cpp
+++ b/src/in_2sf/XSFPlayer_2SF.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - 2SF Player
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Based on a modified vio2sf v0.22c
  *
@@ -28,7 +28,7 @@
 	bool Load2SF(XSFFile *xSFToLoad);
 public:
 	XSFPlayer_2SF(const std::string &filename);
-#ifdef _MSC_VER
+#ifdef _WIN32
 	XSFPlayer_2SF(const std::wstring &filename);
 #endif
 	~XSFPlayer_2SF() { this->Terminate(); }
@@ -45,7 +45,7 @@
 	return new XSFPlayer_2SF(fn);
 }
 
-#ifdef _MSC_VER
+#ifdef _WIN32
 XSFPlayer *XSFPlayer::Create(const std::wstring &fn)
 {
 	return new XSFPlayer_2SF(fn);
@@ -146,10 +146,10 @@
 {
 	if (level <= 10 && xSFToLoad->GetTagExists("_lib"))
 	{
-#ifdef _MSC_VER
-		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue("_lib").GetWStr(), 4, 8));
+#ifdef _WIN32
+		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib")), 4, 8));
 #else
-		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue("_lib").GetAnsi(), 4, 8));
+		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib"), 4, 8));
 #endif
 		if (!this->RecursiveLoad2SF(libxSF.get(), level + 1))
 			return false;
@@ -167,10 +167,10 @@
 		if (xSFToLoad->GetTagExists(libTag))
 		{
 			found = true;
-#ifdef _MSC_VER
-			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue(libTag).GetWStr(), 4, 8));
+#ifdef _WIN32
+			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag)), 4, 8));
 #else
-			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue(libTag).GetAnsi(), 4, 8));
+			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag), 4, 8));
 #endif
 			if (!this->RecursiveLoad2SF(libxSF.get(), level + 1))
 				return false;
@@ -192,7 +192,7 @@
 	this->xSF.reset(new XSFFile(filename, 4, 8));
 }
 
-#ifdef _MSC_VER
+#ifdef _WIN32
 XSFPlayer_2SF::XSFPlayer_2SF(const std::wstring &filename) : XSFPlayer()
 {
 	this->xSF.reset(new XSFFile(filename, 4, 8));

--- a/src/in_gsf/XSFConfig_GSF.cpp
+++ b/src/in_gsf/XSFConfig_GSF.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - GSF configuration
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
@@ -10,7 +10,6 @@
 #include "XSFPlayer.h"
 #include "XSFConfig.h"
 #include "convert.h"
-#include "BigSString.h"
 #include "vbam/gba/Sound.h"
 
 enum
@@ -23,7 +22,7 @@
 {
 protected:
 	static bool initLowPassFiltering;
-	static std::wstring initMutes;
+	static std::string initMutes;
 
 	friend class XSFConfig;
 	bool lowPassFiltering;
@@ -42,10 +41,10 @@
 };
 
 unsigned XSFConfig::initSampleRate = 44100;
-std::wstring XSFConfig::commonName = L"GSF Decoder";
-std::wstring XSFConfig::versionNumber = L"0.9b";
+std::string XSFConfig::commonName = "GSF Decoder";
+std::string XSFConfig::versionNumber = "0.9b";
 bool XSFConfig_GSF::initLowPassFiltering = true;
-std::wstring XSFConfig_GSF::initMutes = L"000000";
+std::string XSFConfig_GSF::initMutes = "000000";
 
 XSFConfig *XSFConfig::Create()
 {
@@ -69,15 +68,15 @@
 
 void XSFConfig_GSF::LoadSpecificConfig()
 {
-	this->lowPassFiltering = this->configIO->GetValue(L"LowPassFiltering", XSFConfig_GSF::initLowPassFiltering);
-	std::wstringstream mutesSS(this->configIO->GetValue(L"Mutes", XSFConfig_GSF::initMutes));
+	this->lowPassFiltering = this->configIO->GetValue("LowPassFiltering", XSFConfig_GSF::initLowPassFiltering);
+	std::stringstream mutesSS(this->configIO->GetValue("Mutes", XSFConfig_GSF::initMutes));
 	mutesSS >> this->mutes;
 }
 
 void XSFConfig_GSF::SaveSpecificConfig()
 {
-	this->configIO->SetValue(L"LowPassFiltering", this->lowPassFiltering);
-	this->configIO->SetValue(L"Mutes", this->mutes.to_string<wchar_t>());
+	this->configIO->SetValue("LowPassFiltering", this->lowPassFiltering);
+	this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
 }
 
 void XSFConfig_GSF::GenerateSpecificDialogs()
@@ -141,7 +140,7 @@
 
 void XSFConfig_GSF::About(HWND parent)
 {
-	MessageBoxW(parent, (XSFConfig::commonName + L" v" + XSFConfig::versionNumber + L", using xSF Winamp plugin framework (based on the vio*sf plugins) by Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]\n\n"
-		L"Utilizes modified VBA-M, SVN revision 1231, for audio playback.").c_str(), (XSFConfig::commonName + L" v" + XSFConfig::versionNumber).c_str(), MB_OK);
+	MessageBoxW(parent, ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber + ", using xSF Winamp plugin framework (based on the vio*sf plugins) by Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]\n\n"
+		"Utilizes modified VBA-M, SVN revision 1231, for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
 }
 

--- a/src/in_gsf/XSFPlayer_GSF.cpp
+++ b/src/in_gsf/XSFPlayer_GSF.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - GSF Player
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Based on a modified viogsf v0.08
  *
@@ -24,7 +24,7 @@
 {
 public:
 	XSFPlayer_GSF(const std::string &filename);
-#ifdef _MSC_VER
+#ifdef _WIN32
 	XSFPlayer_GSF(const std::wstring &filename);
 #endif
 	~XSFPlayer_GSF() { this->Terminate(); }
@@ -41,7 +41,7 @@
 	return new XSFPlayer_GSF(fn);
 }
 
-#ifdef _MSC_VER
+#ifdef _WIN32
 XSFPlayer *XSFPlayer::Create(const std::wstring &fn)
 {
 	return new XSFPlayer_GSF(fn);
@@ -152,10 +152,10 @@
 {
 	if (level <= 10 && xSF->GetTagExists("_lib"))
 	{
-#ifdef _MSC_VER
-		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetWStr()) + xSF->GetTagValue("_lib").GetWStr(), 8, 12));
+#ifdef _WIN32
+		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSF->GetFilename()) + xSF->GetTagValue("_lib")), 8, 12));
 #else
-		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetAnsi()) + xSF->GetTagValue("_lib").GetAnsi(), 8, 12));
+		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename()) + xSF->GetTagValue("_lib"), 8, 12));
 #endif
 		if (!RecursiveLoad2SF(libxSF.get(), level + 1))
 			return false;
@@ -173,10 +173,10 @@
 		if (xSF->GetTagExists(libTag))
 		{
 			found = true;
-#ifdef _MSC_VER
-			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetWStr()) + xSF->GetTagValue(libTag).GetWStr(), 8, 12));
+#ifdef _WIN32
+			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSF->GetFilename()) + xSF->GetTagValue(libTag)), 8, 12));
 #else
-			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetAnsi()) + xSF->GetTagValue(libTag).GetAnsi(), 8, 12));
+			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename()) + xSF->GetTagValue(libTag), 8, 12));
 #endif
 			if (!RecursiveLoad2SF(libxSF.get(), level + 1))
 				return false;
@@ -199,7 +199,7 @@
 	this->xSF.reset(new XSFFile(filename, 8, 12));
 }
 
-#ifdef _MSC_VER
+#ifdef _WIN32
 XSFPlayer_GSF::XSFPlayer_GSF(const std::wstring &filename) : XSFPlayer()
 {
 	this->xSF.reset(new XSFFile(filename, 8, 12));

--- a/src/in_ncsf/XSFConfig_NCSF.cpp
+++ b/src/in_ncsf/XSFConfig_NCSF.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - NCSF configuration
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
@@ -10,7 +10,6 @@
 #include "XSFPlayer_NCSF.h"
 #include "XSFConfig.h"
 #include "convert.h"
-#include "BigSString.h"
 
 enum
 {
@@ -22,7 +21,7 @@
 {
 protected:
 	static unsigned initInterpolation;
-	static std::wstring initMutes;
+	static std::string initMutes;
 
 	friend class XSFConfig;
 	unsigned interpolation;
@@ -41,10 +40,10 @@
 };
 
 unsigned XSFConfig::initSampleRate = 44100;
-std::wstring XSFConfig::commonName = L"NCSF Decoder";
-std::wstring XSFConfig::versionNumber = L"1.8.1";
+std::string XSFConfig::commonName = "NCSF Decoder";
+std::string XSFConfig::versionNumber = "1.8.1";
 unsigned XSFConfig_NCSF::initInterpolation = 5;
-std::wstring XSFConfig_NCSF::initMutes = L"0000000000000000";
+std::string XSFConfig_NCSF::initMutes = "0000000000000000";
 
 XSFConfig *XSFConfig::Create()
 {
@@ -68,15 +67,15 @@
 
 void XSFConfig_NCSF::LoadSpecificConfig()
 {
-	this->interpolation = this->configIO->GetValue(L"Interpolation", XSFConfig_NCSF::initInterpolation);
-	std::wstringstream mutesSS(this->configIO->GetValue(L"Mutes", XSFConfig_NCSF::initMutes));
+	this->interpolation = this->configIO->GetValue("Interpolation", XSFConfig_NCSF::initInterpolation);
+	std::stringstream mutesSS(this->configIO->GetValue("Mutes", XSFConfig_NCSF::initMutes));
 	mutesSS >> this->mutes;
 }
 
 void XSFConfig_NCSF::SaveSpecificConfig()
 {
-	this->configIO->SetValue(L"Interpolation", this->interpolation);
-	this->configIO->SetValue(L"Mutes", this->mutes.to_string<wchar_t>());
+	this->configIO->SetValue("Interpolation", this->interpolation);
+	this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
 }
 
 void XSFConfig_NCSF::GenerateSpecificDialogs()
@@ -141,7 +140,7 @@
 
 void XSFConfig_NCSF::About(HWND parent)
 {
-	MessageBoxW(parent, (XSFConfig::commonName + L" v" + XSFConfig::versionNumber + L", using xSF Winamp plugin framework (based on the vio*sf plugins) by Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]\n\n"
-		L"Utilizes code adapted from the FeOS Sound System library by fincs, git revision 5204c55 on GitHub, for audio playback.").c_str(), (XSFConfig::commonName + L" v" + XSFConfig::versionNumber).c_str(), MB_OK);
+	MessageBoxW(parent, ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber + ", using xSF Winamp plugin framework (based on the vio*sf plugins) by Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]\n\n"
+		"Utilizes code adapted from the FeOS Sound System library by fincs, git revision 5204c55 on GitHub, for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
 }
 

--- a/src/in_ncsf/XSFPlayer_NCSF.cpp
+++ b/src/in_ncsf/XSFPlayer_NCSF.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - NCSF Player
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  *
@@ -25,7 +25,7 @@
 	return new XSFPlayer_NCSF(fn);
 }
 
-#ifdef _MSC_VER
+#ifdef _WIN32
 XSFPlayer *XSFPlayer::Create(const std::wstring &fn)
 {
 	return new XSFPlayer_NCSF(fn);
@@ -62,10 +62,10 @@
 {
 	if (level <= 10 && xSFToLoad->GetTagExists("_lib"))
 	{
-#ifdef _MSC_VER
-		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue("_lib").GetWStr(), 8, 12));
+#ifdef _WIN32
+		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib")), 8, 12));
 #else
-		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue("_lib").GetAnsi(), 8, 12));
+		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue("_lib"), 8, 12));
 #endif
 		if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1))
 			return false;
@@ -83,10 +83,10 @@
 		if (xSFToLoad->GetTagExists(libTag))
 		{
 			found = true;
-#ifdef _MSC_VER
-			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetWStr()) + xSFToLoad->GetTagValue(libTag).GetWStr(), 8, 12));
+#ifdef _WIN32
+			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag)), 8, 12));
 #else
-			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename().GetAnsi()) + xSFToLoad->GetTagValue(libTag).GetAnsi(), 8, 12));
+			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSFToLoad->GetFilename()) + xSFToLoad->GetTagValue(libTag), 8, 12));
 #endif
 			if (!this->RecursiveLoadNCSF(libxSF.get(), level + 1))
 				return false;
@@ -107,7 +107,7 @@
 	this->xSF.reset(new XSFFile(filename, 8, 12));
 }
 
-#ifdef _MSC_VER
+#ifdef _WIN32
 XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer()
 {
 	this->uses32BitSamplesClampedTo16Bit = true;

--- a/src/in_ncsf/XSFPlayer_NCSF.h
+++ b/src/in_ncsf/XSFPlayer_NCSF.h
@@ -1,7 +1,7 @@
 /*
  * xSF - NCSF Player
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  *
@@ -33,7 +33,7 @@
 	bool LoadNCSF();
 public:
 	XSFPlayer_NCSF(const std::string &filename);
-#ifdef _MSC_VER
+#ifdef _WIN32
 	XSFPlayer_NCSF(const std::wstring &filename);
 #endif
 	bool Load();

--- a/src/in_snsf/XSFConfig_SNSF.cpp
+++ b/src/in_snsf/XSFConfig_SNSF.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - SNSF configuration
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  *
@@ -12,7 +12,6 @@
 
 #include "XSFConfig_SNSF.h"
 #include "convert.h"
-#include "BigSString.h"
 #include "snes9x/apu/apu.h"
 
 enum
@@ -24,12 +23,12 @@
 };
 
 unsigned XSFConfig::initSampleRate = 44100;
-std::wstring XSFConfig::commonName = L"SNSF Decoder";
-std::wstring XSFConfig::versionNumber = L"0.9b";
+std::string XSFConfig::commonName = "SNSF Decoder";
+std::string XSFConfig::versionNumber = "0.9b";
 //bool XSFConfig_SNSF::initSixteenBitSound = true;
 bool XSFConfig_SNSF::initReverseStereo = false;
 unsigned XSFConfig_SNSF::initResampler = 1;
-std::wstring XSFConfig_SNSF::initMutes = L"00000000";
+std::string XSFConfig_SNSF::initMutes = "00000000";
 
 XSFConfig *XSFConfig::Create()
 {
@@ -53,19 +52,19 @@
 
 void XSFConfig_SNSF::LoadSpecificConfig()
 {
-	//this->sixteenBitSound = this->configIO->GetValue(L"SixteenBitSound", XSFConfig_SNSF::initSixteenBitSound);
-	this->reverseStereo = this->configIO->GetValue(L"ReverseStereo", XSFConfig_SNSF::initReverseStereo);
-	this->resampler = this->configIO->GetValue(L"Resampler", XSFConfig_SNSF::initResampler);
-	std::wstringstream mutesSS(this->configIO->GetValue(L"Mutes", XSFConfig_SNSF::initMutes));
+	//this->sixteenBitSound = this->configIO->GetValue("SixteenBitSound", XSFConfig_SNSF::initSixteenBitSound);
+	this->reverseStereo = this->configIO->GetValue("ReverseStereo", XSFConfig_SNSF::initReverseStereo);
+	this->resampler = this->configIO->GetValue("Resampler", XSFConfig_SNSF::initResampler);
+	std::stringstream mutesSS(this->configIO->GetValue("Mutes", XSFConfig_SNSF::initMutes));
 	mutesSS >> this->mutes;
 }
 
 void XSFConfig_SNSF::SaveSpecificConfig()
 {
-	//this->configIO->SetValue(L"SixteenBitSound", this->sixteenBitSound);
-	this->configIO->SetValue(L"ReverseStereo", this->reverseStereo);
-	this->configIO->SetValue(L"Resampler", this->resampler);
-	this->configIO->SetValue(L"Mutes", this->mutes.to_string<wchar_t>());
+	//this->configIO->SetValue("SixteenBitSound", this->sixteenBitSound);
+	this->configIO->SetValue("ReverseStereo", this->reverseStereo);
+	this->configIO->SetValue("Resampler", this->resampler);
+	this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
 }
 
 void XSFConfig_SNSF::GenerateSpecificDialogs()
@@ -147,7 +146,7 @@
 
 void XSFConfig_SNSF::About(HWND parent)
 {
-	MessageBoxW(parent, (XSFConfig::commonName + L" v" + XSFConfig::versionNumber + L", using xSF Winamp plugin framework (based on the vio*sf plugins) by Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]\n\n"
-		L"Utilizes modified snes9x v1.53 for audio playback.").c_str(), (XSFConfig::commonName + L" v" + XSFConfig::versionNumber).c_str(), MB_OK);
+	MessageBoxW(parent, ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber + ", using xSF Winamp plugin framework (based on the vio*sf plugins) by Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]\n\n"
+		"Utilizes modified snes9x v1.53 for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
 }
 

--- a/src/in_snsf/XSFConfig_SNSF.h
+++ b/src/in_snsf/XSFConfig_SNSF.h
@@ -1,7 +1,7 @@
 /*
  * xSF - SNSF configuration
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-08
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  *
@@ -21,7 +21,7 @@
 protected:
 	static bool /*initSixteenBitSound, */initReverseStereo;
 	static unsigned initResampler;
-	static std::wstring initMutes;
+	static std::string initMutes;
 
 	friend class XSFConfig;
 	bool /*sixteenBitSound, */reverseStereo;

--- a/src/in_snsf/XSFPlayer_SNSF.cpp
+++ b/src/in_snsf/XSFPlayer_SNSF.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - SNSF Player
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Based on a modified in_snsf by Caitsith2
  * http://snsf.caitsith2.net/
@@ -33,7 +33,7 @@
 {
 public:
 	XSFPlayer_SNSF(const std::string &filename);
-#ifdef _MSC_VER
+#ifdef _WIN32
 	XSFPlayer_SNSF(const std::wstring &filename);
 #endif
 	~XSFPlayer_SNSF() { this->Terminate(); }
@@ -52,7 +52,7 @@
 	return new XSFPlayer_SNSF(fn);
 }
 
-#ifdef _MSC_VER
+#ifdef _WIN32
 XSFPlayer *XSFPlayer::Create(const std::wstring &fn)
 {
 	return new XSFPlayer_SNSF(fn);
@@ -169,10 +169,10 @@
 {
 	if (level <= 10 && xSF->GetTagExists("_lib"))
 	{
-#ifdef _MSC_VER
-		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetWStr()) + xSF->GetTagValue("_lib").GetWStr(), 4, 8));
+#ifdef _WIN32
+		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSF->GetFilename()) + xSF->GetTagValue("_lib")), 4, 8));
 #else
-		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetAnsi()) + xSF->GetTagValue("_lib").GetAnsi(), 4, 8));
+		auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename()) + xSF->GetTagValue("_lib"), 4, 8));
 #endif
 		if (!RecursiveLoad2SF(libxSF.get(), level + 1))
 			return false;
@@ -190,10 +190,10 @@
 		if (xSF->GetTagExists(libTag))
 		{
 			found = true;
-#ifdef _MSC_VER
-			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetWStr()) + xSF->GetTagValue(libTag).GetWStr(), 4, 8));
+#ifdef _WIN32
+			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ConvertFuncs::StringToWString(ExtractDirectoryFromPath(xSF->GetFilename()) + xSF->GetTagValue(libTag)), 4, 8));
 #else
-			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename().GetAnsi()) + xSF->GetTagValue(libTag).GetAnsi(), 4, 8));
+			auto libxSF = std::unique_ptr<XSFFile>(new XSFFile(ExtractDirectoryFromPath(xSF->GetFilename()) + xSF->GetTagValue(libTag), 4, 8));
 #endif
 			if (!RecursiveLoad2SF(libxSF.get(), level + 1))
 				return false;
@@ -218,7 +218,7 @@
 	this->xSF.reset(new XSFFile(filename, 4, 8));
 }
 
-#ifdef _MSC_VER
+#ifdef _WIN32
 XSFPlayer_SNSF::XSFPlayer_SNSF(const std::wstring &filename) : XSFPlayer()
 {
 	this->xSF.reset(new XSFFile(filename, 4, 8));

--- a/src/in_xsf_framework/BigSString.h
+++ /dev/null
@@ -1,218 +1,1 @@
-/*
- * String class in ANSI (or rather, current Windows code page), UTF-8, and UTF-16
- * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-08
- */
 
-#pragma once
-
-#include <string>
-#include <cstring>
-#include <cwchar>
-#include "UtfConverter.h"
-#include "UTFEncodeDecode.h"
-
-class String
-{
-public:
-	String(const std::locale &L = std::locale::classic()) : ansi(""), utf8(""), utf16(L""), loc(L) { }
-	String(const char *new_str, bool is_utf8 = false, const std::locale &L = std::locale::classic()) : ansi(is_utf8 ? DecodeFromUTF8(new_str, L) : new_str), utf8(is_utf8 ? new_str : EncodeToUTF8(new_str, L)),
-		utf16(UtfConverter::FromUtf8(utf8)), loc(L) { }
-	String(const std::string &new_str, bool is_utf8 = false, const std::locale &L = std::locale::classic()) : ansi(is_utf8 ? DecodeFromUTF8(new_str, L) : new_str), utf8(is_utf8 ? new_str : EncodeToUTF8(new_str, L)),
-		utf16(UtfConverter::FromUtf8(utf8)), loc(L) { }
-	String(const wchar_t *new_wstr, const std::locale &L = std::locale::classic()) : ansi(DecodeFromUTF8(UtfConverter::ToUtf8(new_wstr), L)), utf8(UtfConverter::ToUtf8(new_wstr)), utf16(new_wstr), loc(L) { }
-	String(const std::wstring &new_wstr, const std::locale &L = std::locale::classic()) : ansi(DecodeFromUTF8(UtfConverter::ToUtf8(new_wstr), L)), utf8(UtfConverter::ToUtf8(new_wstr)), utf16(new_wstr), loc(L) { }
-	bool empty() const { return this->utf8.empty(); }
-	std::string GetAnsi() const { return this->ansi; }
-	const char *GetAnsiC() const { return this->ansi.c_str(); }
-	std::string GetStr() const { return this->utf8; }
-	const char *GetStrC() const { return this->utf8.c_str(); }
-	std::wstring GetWStr() const { return this->utf16; }
-	const wchar_t *GetWStrC() const { return this->utf16.c_str(); }
-	bool operator==(const String &str2) const
-	{
-		return this->utf8 == str2.utf8;
-	}
-	String &operator=(const std::string &new_str)
-	{
-		this->ansi = DecodeFromUTF8(new_str, this->loc);
-		this->utf8 = new_str;
-		this->utf16 = UtfConverter::FromUtf8(new_str);
-		return *this;
-	}
-	String &operator=(const std::wstring &new_wstr)
-	{
-		this->utf8 = UtfConverter::ToUtf8(new_wstr);
-		this->ansi = DecodeFromUTF8(this->utf8, this->loc);
-		this->utf16 = new_wstr;
-		return *this;
-	}
-	String &operator=(const String &new_string)
-	{
-		if (this != &new_string)
-		{
-			this->ansi = new_string.ansi;
-			this->utf8 = new_string.utf8;
-			this->utf16 = new_string.utf16;
-		}
-		return *this;
-	}
-	String &SetISO8859_1(const std::string &new_str)
-	{
-		this->ansi = new_str;
-		this->utf8 = EncodeToUTF8(new_str, this->loc);
-		this->utf16 = UtfConverter::FromUtf8(this->utf8);
-		return *this;
-	}
-	String operator+(const String &str2) const
-	{
-		String new_string = String(*this);
-		new_string.ansi.append(str2.ansi);
-		new_string.utf8.append(str2.utf8);
-		new_string.utf16.append(str2.utf16);
-		return new_string;
-	}
-	String operator+(char chr) const
-	{
-		String new_string = String(*this);
-		char str2[] = { chr, 0 };
-		new_string.ansi.append(str2);
-		std::string new_utf8 = EncodeToUTF8(str2, this->loc);
-		new_string.utf8.append(new_utf8);
-		new_string.utf16.append(UtfConverter::FromUtf8(new_utf8));
-		return new_string;
-	}
-	String operator+(wchar_t wchr) const
-	{
-		String new_string = String(*this);
-		wchar_t wstr2[] = { wchr, 0 };
-		std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
-		new_string.ansi.append(DecodeFromUTF8(new_utf8, this->loc));
-		new_string.utf8.append(new_utf8);
-		new_string.utf16.append(wstr2);
-		return new_string;
-	}
-	String operator+(const char *str2) const
-	{
-		String new_string = String(*this);
-		new_string.ansi.append(DecodeFromUTF8(str2, this->loc));
-		new_string.utf8.append(str2);
-		new_string.utf16.append(UtfConverter::FromUtf8(str2));
-		return new_string;
-	}
-	String operator+(const std::string &str2) const
-	{
-		String new_string = String(*this);
-		new_string.ansi.append(DecodeFromUTF8(str2, this->loc));
-		new_string.utf8.append(str2);
-		new_string.utf16.append(UtfConverter::FromUtf8(str2));
-		return new_string;
-	}
-	String operator+(const wchar_t *wstr2) const
-	{
-		String new_string = String(*this);
-		std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
-		new_string.ansi.append(DecodeFromUTF8(new_utf8, this->loc));
-		new_string.utf8.append(new_utf8);
-		new_string.utf16.append(wstr2);
-		return new_string;
-	}
-	String operator+(const std::wstring &wstr2) const
-	{
-		String new_string = String(*this);
-		std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
-		new_string.ansi.append(DecodeFromUTF8(new_utf8, this->loc));
-		new_string.utf8.append(new_utf8);
-		new_string.utf16.append(wstr2);
-		return new_string;
-	}
-	String &operator+=(const String &str2)
-	{
-		if (this != &str2)
-		{
-			this->ansi.append(str2.ansi);
-			this->utf8.append(str2.utf8);
-			this->utf16.append(str2.utf16);
-		}
-		return *this;
-	}
-	String &operator+=(char chr)
-	{
-		char str2[] = { chr, 0 };
-		this->ansi.append(str2);
-		std::string new_utf8 = EncodeToUTF8(str2, this->loc);
-		this->utf8.append(new_utf8);
-		this->utf16.append(UtfConverter::FromUtf8(new_utf8));
-		return *this;
-	}
-	String &operator+=(wchar_t wchr)
-	{
-		wchar_t wstr2[] = { wchr, 0 };
-		std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
-		this->ansi.append(DecodeFromUTF8(new_utf8, this->loc));
-		this->utf8.append(new_utf8);
-		this->utf16.append(wstr2);
-		return *this;
-	}
-	String &operator+=(const char *str2)
-	{
-		this->ansi.append(DecodeFromUTF8(str2, this->loc));
-		this->utf8.append(str2);
-		this->utf16.append(UtfConverter::FromUtf8(str2));
-		return *this;
-	}
-	String &operator+=(const std::string &str2)
-	{
-		this->ansi.append(DecodeFromUTF8(str2, this->loc));
-		this->utf8.append(str2);
-		this->utf16.append(UtfConverter::FromUtf8(str2));
-		return *this;
-	}
-	String &operator+=(const wchar_t *wstr2)
-	{
-		std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
-		this->ansi.append(DecodeFromUTF8(new_utf8, this->loc));
-		this->utf8.append(new_utf8);
-		this->utf16.append(wstr2);
-		return *this;
-	}
-	String &operator+=(const std::wstring &wstr2)
-	{
-		std::string new_utf8 = UtfConverter::ToUtf8(wstr2);
-		this->ansi.append(DecodeFromUTF8(new_utf8, this->loc));
-		this->utf8.append(new_utf8);
-		this->utf16.append(wstr2);
-		return *this;
-	}
-	String &AppendISO8859_1(const std::string &str2)
-	{
-		this->ansi.append(str2);
-		std::string new_utf8 = EncodeToUTF8(str2, this->loc);
-		this->utf8.append(new_utf8);
-		this->utf16.append(UtfConverter::FromUtf8(new_utf8));
-		return *this;
-	}
-	String Substring(size_t pos = 0, size_t n = std::string::npos) const
-	{
-		String new_string = String(*this);
-		new_string.ansi.substr(pos, n);
-		new_string.utf8.substr(pos, n);
-		if (n == std::string::npos)
-			n = std::wstring::npos;
-		new_string.utf16.substr(pos, n);
-		return new_string;
-	}
-	void CopyToString(wchar_t *str, bool = false) const
-	{
-		wcscpy(str, utf16.c_str());
-	}
-	void CopyToString(char *str, bool use_utf8 = false) const
-	{
-		strcpy(str, (use_utf8 ? utf8 : ansi).c_str());
-	}
-protected:
-	std::string ansi, utf8;
-	std::wstring utf16;
-	std::locale loc;
-};
-

--- a/src/in_xsf_framework/ConvertUTF.cpp
+++ /dev/null
@@ -1,603 +1,1 @@
-/*
- * Copyright 2001-2004 Unicode, Inc.
- *
- * Disclaimer
- *
- * This source code is provided as is by Unicode, Inc. No claims are
- * made as to fitness for any particular purpose. No warranties of any
- * kind are expressed or implied. The recipient agrees to determine
- * applicability of information provided. If this file has been
- * purchased on magnetic or optical media from Unicode, Inc., the
- * sole remedy for any claim will be exchange of defective media
- * within 90 days of receipt.
- *
- * Limitations on Rights to Redistribute This Code
- *
- * Unicode, Inc. hereby grants the right to freely use the information
- * supplied in this file in the creation of products supporting the
- * Unicode Standard, and to make copies of this file in any form
- * for internal or external distribution as long as this notice
- * remains attached.
- */
 
-/* ---------------------------------------------------------------------
-
-    Conversions between UTF32, UTF-16, and UTF-8. Source code file.
-    Author: Mark E. Davis, 1994.
-    Rev History: Rick McGowan, fixes & updates May 2001.
-    Sept 2001: fixed const & error conditions per
-	mods suggested by S. Parent & A. Lillich.
-    June 2002: Tim Dodd added detection and handling of incomplete
-	source sequences, enhanced error detection, added casts
-	to eliminate compiler warnings.
-    July 2003: slight mods to back out aggressive FFFE detection.
-    Jan 2004: updated switches in from-UTF8 conversions.
-    Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
-
-    See the header file "ConvertUTF.h" for complete documentation.
-
------------------------------------------------------------------------- */
-
-#include "ConvertUTF.h"
-
-static const int halfShift  = 10; /* used for shifting by 10 bits */
-
-static const UTF32 halfBase = 0x0010000UL;
-static const UTF32 halfMask = 0x3FFUL;
-
-static const UTF32 UNI_SUR_HIGH_START = 0xD800;
-static const UTF32 UNI_SUR_HIGH_END = 0xDBFF;
-static const UTF32 UNI_SUR_LOW_START = 0xDC00;
-static const UTF32 UNI_SUR_LOW_END = 0xDFFF;
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF32toUTF16(const UTF32 **sourceStart, const UTF32 *sourceEnd, UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags)
-{
-	ConversionResult result = conversionOK;
-	const UTF32 *source = *sourceStart;
-	UTF16 *target = *targetStart;
-	while (source < sourceEnd)
-	{
-		if (target >= targetEnd)
-		{
-			result = targetExhausted;
-			break;
-		}
-		UTF32 ch = *source++;
-		if (ch <= UNI_MAX_BMP) /* Target is a character <= 0xFFFF */
-		{
-			/* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
-			if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
-			{
-				if (flags == strictConversion)
-				{
-					--source; /* return to the illegal value itself */
-					result = sourceIllegal;
-					break;
-				}
-				else
-					*target++ = UNI_REPLACEMENT_CHAR;
-			}
-			else
-				*target++ = static_cast<UTF16>(ch); /* normal case */
-		}
-		else if (ch > UNI_MAX_LEGAL_UTF32)
-		{
-			if (flags == strictConversion)
-				result = sourceIllegal;
-			else
-				*target++ = UNI_REPLACEMENT_CHAR;
-		}
-		else
-		{
-			/* target is a character in range 0xFFFF - 0x10FFFF. */
-			if (target + 1 >= targetEnd)
-			{
-				--source; /* Back up source pointer! */
-				result = targetExhausted;
-				break;
-			}
-			ch -= halfBase;
-			*target++ = static_cast<UTF16>((ch >> halfShift) + UNI_SUR_HIGH_START);
-			*target++ = static_cast<UTF16>((ch & halfMask) + UNI_SUR_LOW_START);
-		}
-	}
-	*sourceStart = source;
-	*targetStart = target;
-	return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF16toUTF32(const UTF16 **sourceStart, const UTF16 *sourceEnd, UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
-{
-	ConversionResult result = conversionOK;
-	const UTF16 *source = *sourceStart;
-	UTF32 *target = *targetStart;
-	while (source < sourceEnd)
-	{
-		const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */
-		UTF32 ch = *source++;
-		/* If we have a surrogate pair, convert to UTF32 first. */
-		if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END)
-		{
-			/* If the 16 bits following the high surrogate are in the source buffer... */
-			if (source < sourceEnd)
-			{
-				UTF32 ch2 = *source;
-				/* If it's a low surrogate, convert to UTF32. */
-				if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END)
-				{
-					ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase;
-					++source;
-				}
-				else if (flags == strictConversion) /* it's an unpaired high surrogate */
-				{
-					--source; /* return to the illegal value itself */
-					result = sourceIllegal;
-					break;
-				}
-			}
-			else /* We don't have the 16 bits following the high surrogate. */
-			{
-				--source; /* return to the high surrogate */
-				result = sourceExhausted;
-				break;
-			}
-		}
-		else if (flags == strictConversion)
-		{
-			/* UTF-16 surrogate values are illegal in UTF-32 */
-			if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)
-			{
-				--source; /* return to the illegal value itself */
-				result = sourceIllegal;
-				break;
-			}
-		}
-		if (target >= targetEnd)
-		{
-			source = oldSource; /* Back up source pointer! */
-			result = targetExhausted;
-			break;
-		}
-		*target++ = ch;
-	}
-	*sourceStart = source;
-	*targetStart = target;
-	return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Index into the table below with the first byte of a UTF-8 sequence to
- * get the number of trailing bytes that are supposed to follow it.
- * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
- * left as-is for anyone who may want to do such conversion, which was
- * allowed in earlier algorithms.
- */
-static const char trailingBytesForUTF8[256] = {
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-	2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
-};
-
-/*
- * Magic values subtracted from a buffer value during UTF8 conversion.
- * This table contains as many values as there might be trailing bytes
- * in a UTF-8 sequence.
- */
-static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
-
-/*
- * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
- * into the first byte, depending on how many bytes follow.  There are
- * as many entries in this table as there are UTF-8 sequence types.
- * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
- * for *legal* UTF-8 will be 4 or fewer bytes total.
- */
-static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
-/* --------------------------------------------------------------------- */
-
-/* The interface converts a whole buffer to avoid function-call overhead.
- * Constants have been gathered. Loops & conditionals have been removed as
- * much as possible for efficiency, in favor of drop-through switches.
- * (See "Note A" at the bottom of the file for equivalent code.)
- * If your compiler supports it, the "isLegalUTF8" call can be turned
- * into an inline function.
- */
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF16toUTF8(const UTF16 **sourceStart, const UTF16 *sourceEnd, UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
-{
-	ConversionResult result = conversionOK;
-	const UTF16 *source = *sourceStart;
-	UTF8 *target = *targetStart;
-	while (source < sourceEnd)
-	{
-		const UTF32 byteMask = 0xBF, byteMark = 0x80;
-		const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */
-		UTF32 ch = *source++;
-		/* If we have a surrogate pair, convert to UTF32 first. */
-		if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END)
-		{
-			/* If the 16 bits following the high surrogate are in the source buffer... */
-			if (source < sourceEnd)
-			{
-				UTF32 ch2 = *source;
-				/* If it's a low surrogate, convert to UTF32. */
-				if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END)
-				{
-					ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase;
-					++source;
-				}
-				else if (flags == strictConversion) /* it's an unpaired high surrogate */
-				{
-					--source; /* return to the illegal value itself */
-					result = sourceIllegal;
-					break;
-				}
-			}
-			else /* We don't have the 16 bits following the high surrogate. */
-			{
-				--source; /* return to the high surrogate */
-				result = sourceExhausted;
-				break;
-			}
-		}
-		else if (flags == strictConversion)
-		{
-			/* UTF-16 surrogate values are illegal in UTF-32 */
-			if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)
-			{
-				--source; /* return to the illegal value itself */
-				result = sourceIllegal;
-				break;
-			}
-		}
-		/* Figure out how many bytes the result will require */
-		unsigned short bytesToWrite = 0;
-		if (ch < 0x80)
-			bytesToWrite = 1;
-		else if (ch < 0x800)
-			bytesToWrite = 2;
-		else if (ch < 0x10000)
-			bytesToWrite = 3;
-		else if (ch < 0x110000)
-			bytesToWrite = 4;
-		else
-		{
-			bytesToWrite = 3;
-			ch = UNI_REPLACEMENT_CHAR;
-		}
-		target += bytesToWrite;
-		if (target > targetEnd)
-		{
-			source = oldSource; /* Back up source pointer! */
-			target -= bytesToWrite;
-			result = targetExhausted;
-			break;
-		}
-		switch (bytesToWrite) /* note: everything falls through. */
-		{
-			case 4: *--target = static_cast<UTF8>((ch | byteMark) & byteMask); ch >>= 6;
-			case 3: *--target = static_cast<UTF8>((ch | byteMark) & byteMask); ch >>= 6;
-			case 2: *--target = static_cast<UTF8>((ch | byteMark) & byteMask); ch >>= 6;
-			case 1: *--target = static_cast<UTF8>(ch | firstByteMark[bytesToWrite]);
-		}
-		target += bytesToWrite;
-	}
-	*sourceStart = source;
-	*targetStart = target;
-	return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Utility routine to tell whether a sequence of bytes is legal UTF-8.
- * This must be called with the length pre-determined by the first byte.
- * If not calling this from ConvertUTF8to*, then the length can be set by:
- *  length = trailingBytesForUTF8[*source]+1;
- * and the sequence is illegal right away if there aren't that many bytes
- * available.
- * If presented with a length > 4, this returns false.  The Unicode
- * definition of UTF-8 goes up to 4-byte sequences.
- */
-
-static bool isLegalUTF8(const UTF8 *source, int length)
-{
-	const UTF8 *srcptr = source + length;
-	UTF8 a;
-	switch (length)
-	{
-		default: return false;
-		/* Everything else falls through when "true"... */
-		case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
-		case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
-		case 2: if ((a = (*--srcptr)) > 0xBF) return false;
-
-		switch (*source)
-		{
-			/* no fall-through in this inner switch */
-			case 0xE0: if (a < 0xA0) return false; break;
-			case 0xED: if (a > 0x9F) return false; break;
-			case 0xF0: if (a < 0x90) return false; break;
-			case 0xF4: if (a > 0x8F) return false; break;
-			default: if (a < 0x80) return false;
-		}
-
-		case 1: if (*source >= 0x80 && *source < 0xC2) return false;
-	}
-	if (*source > 0xF4)
-		return false;
-	return true;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Exported function to return whether a UTF-8 sequence is legal or not.
- * This is not used here; it's just exported.
- */
-bool isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd)
-{
-	int length = trailingBytesForUTF8[*source] + 1;
-	if (source + length > sourceEnd)
-		return false;
-	return isLegalUTF8(source, length);
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF8toUTF16(const UTF8 **sourceStart, const UTF8 *sourceEnd, UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags)
-{
-	ConversionResult result = conversionOK;
-	const UTF8 *source = *sourceStart;
-	UTF16 *target = *targetStart;
-	while (source < sourceEnd)
-	{
-		UTF32 ch = 0;
-		unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
-		if (source + extraBytesToRead >= sourceEnd)
-		{
-			result = sourceExhausted;
-			break;
-		}
-		/* Do this check whether lenient or strict */
-		if (!isLegalUTF8(source, extraBytesToRead + 1))
-		{
-			result = sourceIllegal;
-			break;
-		}
-		/*
-		 * The cases all fall through. See "Note A" below.
-		 */
-		switch (extraBytesToRead)
-		{
-			case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
-			case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
-			case 3: ch += *source++; ch <<= 6;
-			case 2: ch += *source++; ch <<= 6;
-			case 1: ch += *source++; ch <<= 6;
-			case 0: ch += *source++;
-		}
-		ch -= offsetsFromUTF8[extraBytesToRead];
-
-		if (target >= targetEnd)
-		{
-			source -= extraBytesToRead + 1; /* Back up source pointer! */
-			result = targetExhausted;
-			break;
-		}
-		if (ch <= UNI_MAX_BMP) /* Target is a character <= 0xFFFF */
-		{
-			/* UTF-16 surrogate values are illegal in UTF-32 */
-			if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
-			{
-				if (flags == strictConversion)
-				{
-					source -= extraBytesToRead + 1; /* return to the illegal value itself */
-					result = sourceIllegal;
-					break;
-				}
-				else
-					*target++ = UNI_REPLACEMENT_CHAR;
-			}
-			else
-				*target++ = static_cast<UTF16>(ch); /* normal case */
-		}
-		else if (ch > UNI_MAX_UTF16)
-		{
-			if (flags == strictConversion)
-			{
-				result = sourceIllegal;
-				source -= extraBytesToRead + 1; /* return to the start */
-				break; /* Bail out; shouldn't continue */
-			}
-			else
-				*target++ = UNI_REPLACEMENT_CHAR;
-		}
-		else
-		{
-			/* target is a character in range 0xFFFF - 0x10FFFF. */
-			if (target + 1 >= targetEnd)
-			{
-				source -= extraBytesToRead + 1; /* Back up source pointer! */
-				result = targetExhausted;
-				break;
-			}
-			ch -= halfBase;
-			*target++ = static_cast<UTF16>((ch >> halfShift) + UNI_SUR_HIGH_START);
-			*target++ = static_cast<UTF16>((ch & halfMask) + UNI_SUR_LOW_START);
-		}
-	}
-	*sourceStart = source;
-	*targetStart = target;
-	return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF32toUTF8(const UTF32 **sourceStart, const UTF32 *sourceEnd, UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
-{
-	ConversionResult result = conversionOK;
-	const UTF32 *source = *sourceStart;
-	UTF8 *target = *targetStart;
-	while (source < sourceEnd)
-	{
-		const UTF32 byteMask = 0xBF, byteMark = 0x80;
-		UTF32 ch = *source++;
-		if (flags == strictConversion)
-		{
-			/* UTF-16 surrogate values are illegal in UTF-32 */
-			if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
-			{
-				--source; /* return to the illegal value itself */
-				result = sourceIllegal;
-				break;
-			}
-		}
-		/*
-		 * Figure out how many bytes the result will require. Turn any
-		 * illegally large UTF32 things (> Plane 17) into replacement chars.
-		 */
-		unsigned short bytesToWrite = 0;
-		if (ch < 0x80)
-			bytesToWrite = 1;
-		else if (ch < 0x800)
-			bytesToWrite = 2;
-		else if (ch < 0x10000)
-			bytesToWrite = 3;
-		else if (ch <= UNI_MAX_LEGAL_UTF32)
-			bytesToWrite = 4;
-		else
-		{
-			bytesToWrite = 3;
-			ch = UNI_REPLACEMENT_CHAR;
-			result = sourceIllegal;
-		}
-
-		target += bytesToWrite;
-		if (target > targetEnd)
-		{
-			--source; /* Back up source pointer! */
-			target -= bytesToWrite;
-			result = targetExhausted;
-			break;
-		}
-		switch (bytesToWrite) /* note: everything falls through. */
-		{
-			case 4: *--target = static_cast<UTF8>((ch | byteMark) & byteMask); ch >>= 6;
-			case 3: *--target = static_cast<UTF8>((ch | byteMark) & byteMask); ch >>= 6;
-			case 2: *--target = static_cast<UTF8>((ch | byteMark) & byteMask); ch >>= 6;
-			case 1: *--target = static_cast<UTF8>(ch | firstByteMark[bytesToWrite]);
-		}
-		target += bytesToWrite;
-	}
-	*sourceStart = source;
-	*targetStart = target;
-	return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, const UTF8 *sourceEnd, UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
-{
-	ConversionResult result = conversionOK;
-	const UTF8 *source = *sourceStart;
-	UTF32 *target = *targetStart;
-	while (source < sourceEnd)
-	{
-		UTF32 ch = 0;
-		unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
-		if (source + extraBytesToRead >= sourceEnd)
-		{
-			result = sourceExhausted;
-			break;
-		}
-		/* Do this check whether lenient or strict */
-		if (!isLegalUTF8(source, extraBytesToRead + 1))
-		{
-			result = sourceIllegal;
-			break;
-		}
-		/*
-		 * The cases all fall through. See "Note A" below.
-		 */
-		switch (extraBytesToRead)
-		{
-			case 5: ch += *source++; ch <<= 6;
-			case 4: ch += *source++; ch <<= 6;
-			case 3: ch += *source++; ch <<= 6;
-			case 2: ch += *source++; ch <<= 6;
-			case 1: ch += *source++; ch <<= 6;
-			case 0: ch += *source++;
-		}
-		ch -= offsetsFromUTF8[extraBytesToRead];
-
-		if (target >= targetEnd)
-		{
-			source -= extraBytesToRead + 1; /* Back up the source pointer! */
-			result = targetExhausted;
-			break;
-		}
-		if (ch <= UNI_MAX_LEGAL_UTF32)
-		{
-			/*
-			 * UTF-16 surrogate values are illegal in UTF-32, and anything
-			 * over Plane 17 (> 0x10FFFF) is illegal.
-			 */
-			if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
-			{
-				if (flags == strictConversion)
-				{
-					source -= extraBytesToRead + 1; /* return to the illegal value itself */
-					result = sourceIllegal;
-					break;
-				}
-				else
-					*target++ = UNI_REPLACEMENT_CHAR;
-			}
-			else
-				*target++ = ch;
-		}
-		else /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
-		{
-			result = sourceIllegal;
-			*target++ = UNI_REPLACEMENT_CHAR;
-		}
-	}
-	*sourceStart = source;
-	*targetStart = target;
-	return result;
-}
-
-/* ---------------------------------------------------------------------
-
-    Note A.
-    The fall-through switches in UTF-8 reading code save a
-    temp variable, some decrements & conditionals.  The switches
-    are equivalent to the following loop:
-	{
-	    int tmpBytesToRead = extraBytesToRead+1;
-	    do {
-		ch += *source++;
-		--tmpBytesToRead;
-		if (tmpBytesToRead) ch <<= 6;
-	    } while (tmpBytesToRead > 0);
-	}
-    In UTF-8 writing code, the switches on "bytesToWrite" are
-    similarly unrolled loops.
-
-   --------------------------------------------------------------------- */
-

--- a/src/in_xsf_framework/ConvertUTF.h
+++ /dev/null
@@ -1,132 +1,1 @@
-/*
- * Copyright 2001-2004 Unicode, Inc.
- *
- * Disclaimer
- *
- * This source code is provided as is by Unicode, Inc. No claims are
- * made as to fitness for any particular purpose. No warranties of any
- * kind are expressed or implied. The recipient agrees to determine
- * applicability of information provided. If this file has been
- * purchased on magnetic or optical media from Unicode, Inc., the
- * sole remedy for any claim will be exchange of defective media
- * within 90 days of receipt.
- *
- * Limitations on Rights to Redistribute This Code
- *
- * Unicode, Inc. hereby grants the right to freely use the information
- * supplied in this file in the creation of products supporting the
- * Unicode Standard, and to make copies of this file in any form
- * for internal or external distribution as long as this notice
- * remains attached.
- */
 
-/* ---------------------------------------------------------------------
-
-    Conversions between UTF32, UTF-16, and UTF-8.  Header file.
-
-    Several funtions are included here, forming a complete set of
-    conversions between the three formats.  UTF-7 is not included
-    here, but is handled in a separate source file.
-
-    Each of these routines takes pointers to input buffers and output
-    buffers.  The input buffers are const.
-
-    Each routine converts the text between *sourceStart and sourceEnd,
-    putting the result into the buffer between *targetStart and
-    targetEnd. Note: the end pointers are *after* the last item: e.g.
-    *(sourceEnd - 1) is the last item.
-
-    The return result indicates whether the conversion was successful,
-    and if not, whether the problem was in the source or target buffers.
-    (Only the first encountered problem is indicated.)
-
-    After the conversion, *sourceStart and *targetStart are both
-    updated to point to the end of last text successfully converted in
-    the respective buffers.
-
-    Input parameters:
-	sourceStart - pointer to a pointer to the source buffer.
-		The contents of this are modified on return so that
-		it points at the next thing to be converted.
-	targetStart - similarly, pointer to pointer to the target buffer.
-	sourceEnd, targetEnd - respectively pointers to the ends of the
-		two buffers, for overflow checking only.
-
-    These conversion functions take a ConversionFlags argument. When this
-    flag is set to strict, both irregular sequences and isolated surrogates
-    will cause an error.  When the flag is set to lenient, both irregular
-    sequences and isolated surrogates are converted.
-
-    Whether the flag is strict or lenient, all illegal sequences will cause
-    an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
-    or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
-    must check for illegal sequences.
-
-    When the flag is set to lenient, characters over 0x10FFFF are converted
-    to the replacement character; otherwise (when the flag is set to strict)
-    they constitute an error.
-
-    Output parameters:
-	The value "sourceIllegal" is returned from some routines if the input
-	sequence is malformed.  When "sourceIllegal" is returned, the source
-	value will point to the illegal value that caused the problem. E.g.,
-	in UTF-8 when a sequence is malformed, it points to the start of the
-	malformed sequence.
-
-    Author: Mark E. Davis, 1994.
-    Rev History: Rick McGowan, fixes & updates May 2001.
-		 Fixes & updates, Sept 2001.
-
------------------------------------------------------------------------- */
-
-#pragma once
-
-/* ---------------------------------------------------------------------
-    The following 4 definitions are compiler-specific.
-    The C standard does not guarantee that wchar_t has at least
-    16 bits, so wchar_t is no less portable than unsigned short!
-    All should be unsigned values to avoid sign extension during
-    bit mask & shift operations.
------------------------------------------------------------------------- */
-
-typedef unsigned long UTF32; /* at least 32 bits */
-typedef unsigned short UTF16; /* at least 16 bits */
-typedef unsigned char UTF8; /* typically 8 bits */
-
-/* Some fundamental constants */
-static const UTF32 UNI_REPLACEMENT_CHAR = 0x0000FFFD;
-static const UTF32 UNI_MAX_BMP = 0x0000FFFF;
-static const UTF32 UNI_MAX_UTF16 = 0x0010FFFF;
-static const UTF32 UNI_MAX_UTF32 = 0x7FFFFFFF;
-static const UTF32 UNI_MAX_LEGAL_UTF32 = 0x0010FFFF;
-
-enum ConversionResult
-{
-	conversionOK,		/* conversion successful */
-	sourceExhausted,	/* partial character in source, but hit end */
-	targetExhausted,	/* insuff. room in target for conversion */
-	sourceIllegal		/* source sequence is illegal/malformed */
-};
-
-enum ConversionFlags
-{
-	strictConversion,
-	lenientConversion
-};
-
-ConversionResult ConvertUTF8toUTF16(const UTF8 **, const UTF8 *, UTF16 **, UTF16 *, ConversionFlags);
-
-ConversionResult ConvertUTF16toUTF8(const UTF16 **, const UTF16 *, UTF8 **, UTF8 *, ConversionFlags);
-
-ConversionResult ConvertUTF8toUTF32(const UTF8 **, const UTF8 *, UTF32 **, UTF32 *, ConversionFlags);
-
-ConversionResult ConvertUTF32toUTF8(const UTF32 **, const UTF32 *, UTF8 **, UTF8 *, ConversionFlags);
-
-ConversionResult ConvertUTF16toUTF32(const UTF16 **, const UTF16 *, UTF32 **, UTF32 *, ConversionFlags);
-
-ConversionResult ConvertUTF32toUTF16(const UTF32 **, const UTF32 *, UTF16 **, UTF16 *, ConversionFlags);
-
-bool isLegalUTF8Sequence(const UTF8 *, const UTF8 *);
-
-/* --------------------------------------------------------------------- */
-

--- a/src/in_xsf_framework/DialogBuilder.h
+++ b/src/in_xsf_framework/DialogBuilder.h
@@ -1,7 +1,7 @@
 /*
  * Windows Dynamic Dialog Builder framework
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  */
 
 #pragma once
@@ -12,8 +12,8 @@
 #include <algorithm>
 #include <stdexcept>
 #include <cstdint>
+#include "XSFCommon.h"
 #include "windowsh_wrapper.h"
-#include "UtfConverter.h"
 
 template<typename T> struct Point
 {
@@ -621,7 +621,7 @@
 					return;
 				}
 			}
-			throw std::runtime_error("Group " + UtfConverter::ToUtf8(groupBuilder.groupName) + " was not found.");
+			throw std::runtime_error("Group " + ConvertFuncs::WStringToString(groupBuilder.groupName) + " was not found.");
 		}
 	}
 	uint16_t GetTotalControlCount() const;

--- a/src/in_xsf_framework/UTFEncodeDecode.cpp
+++ /dev/null
@@ -1,30 +1,1 @@
-// original code is from here: http://www.codeproject.com/Tips/197097/Converting-ANSI-to-Unicode-and-back
-// License: The Code Project Open License (CPOL) http://www.codeproject.com/info/cpol10.aspx
 
-#include "UTFEncodeDecode.h"
-#include "UtfConverter.h"
-
-std::string EncodeToUTF8(const std::string &source, const std::locale &L)
-{
-	try
-	{
-		return UtfConverter::ToUtf8(cp_converter<>(L).widen(source));
-	}
-	catch (const std::runtime_error &)
-	{
-		return "";
-	}
-}
-
-std::string DecodeFromUTF8(const std::string &source, const std::locale &L)
-{
-	try
-	{
-		return cp_converter<>(L).narrow(UtfConverter::FromUtf8(source));
-	}
-	catch (const std::runtime_error &)
-	{
-		return "";
-	}
-}
-

--- a/src/in_xsf_framework/UTFEncodeDecode.h
+++ /dev/null
@@ -1,61 +1,1 @@
-// original code is from here: http://www.codeproject.com/Tips/197097/Converting-ANSI-to-Unicode-and-back
-// License: The Code Project Open License (CPOL) http://www.codeproject.com/info/cpol10.aspx
 
-#pragma once
-
-#include <string>
-#include <locale>
-#include <sstream>
-#include <stdexcept>
-
-std::string EncodeToUTF8(const std::string &, const std::locale & = std::locale::classic());
-std::string DecodeFromUTF8(const std::string &, const std::locale & = std::locale::classic());
-
-template<size_t buf_size = 100> class cp_converter
-{
-	const std::locale loc;
-public:
-	cp_converter(const std::locale &L = std::locale::classic()) : loc(L) { }
-	std::wstring widen(const std::string &in)
-	{
-		return this->convert<char, wchar_t>(in);
-	}
-	std::string narrow(const std::wstring &in)
-	{
-		return this->convert<wchar_t, char>(in);
-	}
-private:
-	typedef std::codecvt<wchar_t, char, mbstate_t> codecvt_facet;
-
-	// widen
-	codecvt_facet::result cv(const codecvt_facet &facet, mbstate_t &s, const char *f1, const char *l1, const char *&n1, wchar_t *f2, wchar_t *l2, wchar_t *&n2) const
-	{
-		return facet.in(s, f1, l1, n1, f2, l2, n2);
-	}
-
-	// narrow
-	codecvt_facet::result cv(const codecvt_facet &facet, mbstate_t &s, const wchar_t *f1, const wchar_t *l1, const wchar_t *&n1, char *f2, char *l2, char *&n2) const
-	{
-		return facet.out(s, f1, l1, n1, f2, l2, n2);
-	}
-
-	template<class ct_in, class ct_out> std::basic_string<ct_out> convert(const std::basic_string<ct_in> &in)
-	{
-		auto &facet = std::use_facet<codecvt_facet>(this->loc);
-		std::basic_stringstream<ct_out> os;
-		ct_out buf[buf_size];
-		mbstate_t state = {0};
-		codecvt_facet::result result;
-		const ct_in *ipc = &in[0];
-		do
-		{
-			ct_out *opc = nullptr;
-			result = this->cv(facet, state, ipc, &in[0] + in.length(), ipc, buf, buf + buf_size, opc);
-			os << std::basic_string<ct_out>(buf, opc - buf);
-		} while (ipc < &in[0] + in.length() && result != codecvt_facet::error);
-		if (result != codecvt_facet::ok)
-			throw std::runtime_error("result is not ok!");
-		return os.str();
-	}
-};
-

--- a/src/in_xsf_framework/UtfConverter.cpp
+++ /dev/null
@@ -1,70 +1,1 @@
-// original code is from here: http://www.codeproject.com/Articles/17573/Convert-Between-std-string-and-std-wstring-UTF-8-a
-// License: The Code Project Open License (CPOL) http://www.codeproject.com/info/cpol10.aspx
 
-#include <string>
-#include <vector>
-#include <stdexcept>
-#include "ConvertUTF.h"
-
-namespace UtfConverter
-{
-	std::wstring FromUtf8(const std::string &utf8string)
-	{
-		auto widesize = utf8string.length();
-		auto result = std::vector<wchar_t>(widesize + 1, L'\0');
-		auto orig = std::vector<char>(widesize + 1, '\0');
-		std::copy(utf8string.begin(), utf8string.end(), orig.begin());
-		auto sourcestart = reinterpret_cast<const UTF8 *>(&orig[0]), sourceend = sourcestart + widesize;
-		ConversionResult res;
-		if (sizeof(wchar_t) == 2)
-		{
-			auto targetstart = reinterpret_cast<UTF16 *>(&result[0]), targetend = targetstart + widesize;
-			res = ConvertUTF8toUTF16(&sourcestart, sourceend, &targetstart, targetend, strictConversion);
-			*targetstart = 0;
-			unsigned end = targetstart - reinterpret_cast<UTF16 *>(&result[0]);
-			result.erase(result.begin() + end, result.end());
-		}
-		else if (sizeof(wchar_t) == 4)
-		{
-			auto targetstart = reinterpret_cast<UTF32 *>(&result[0]), targetend = targetstart + widesize;
-			res = ConvertUTF8toUTF32(&sourcestart, sourceend, &targetstart, targetend, strictConversion);
-			*targetstart = 0;
-			unsigned end = targetstart - reinterpret_cast<UTF32 *>(&result[0]);
-			result.erase(result.begin() + end, result.end());
-		}
-		else
-			throw std::runtime_error("UtfConverter::FromUtf8: sizeof(wchar_t) is not 2 or 4.");
-		if (res != conversionOK)
-			throw std::runtime_error("UtfConverter::FromUtf8: Conversion failed.");
-		return std::wstring(result.begin(), result.end());
-	}
-
-	std::string ToUtf8(const std::wstring &widestring)
-	{
-		auto widesize = widestring.length(), utf8size = (sizeof(wchar_t) == 2 ? 3 : 4) * widesize + 1;
-		auto result = std::vector<char>(utf8size, '\0');
-		auto orig = std::vector<wchar_t>(widesize + 1, L'\0');
-		std::copy(widestring.begin(), widestring.end(), orig.begin());
-		auto targetstart = reinterpret_cast<UTF8 *>(&result[0]), targetend = targetstart + utf8size;
-		ConversionResult res;
-		if (sizeof(wchar_t) == 2)
-		{
-			auto sourcestart = reinterpret_cast<const UTF16 *>(&orig[0]), sourceend = sourcestart + widesize;
-			res = ConvertUTF16toUTF8(&sourcestart, sourceend, &targetstart, targetend, strictConversion);
-		}
-		else if (sizeof(wchar_t) == 4)
-		{
-			auto sourcestart = reinterpret_cast<const UTF32 *>(&orig[0]), sourceend = sourcestart + widesize;
-			res = ConvertUTF32toUTF8(&sourcestart, sourceend, &targetstart, targetend, strictConversion);
-		}
-		else
-			throw std::runtime_error("UtfConverter::ToUtf8: sizeof(wchar_t) is not 2 or 4.");
-		if (res != conversionOK)
-			throw std::runtime_error("UtfConverter::ToUtf8: Conversion failed.");
-		*targetstart = 0;
-		auto end = targetstart - reinterpret_cast<UTF8 *>(&result[0]);
-		result.erase(result.begin() + end, result.end());
-		return std::string(result.begin(), result.end());
-	}
-}
-

--- a/src/in_xsf_framework/UtfConverter.h
+++ /dev/null
@@ -1,13 +1,1 @@
-// original code is from here: http://www.codeproject.com/Articles/17573/Convert-Between-std-string-and-std-wstring-UTF-8-a
-// License: The Code Project Open License (CPOL) http://www.codeproject.com/info/cpol10.aspx
 
-#pragma once
-
-#include <string>
-
-namespace UtfConverter
-{
-	std::wstring FromUtf8(const std::string &);
-	std::string ToUtf8(const std::wstring &);
-}
-

--- a/src/in_xsf_framework/XSFCommon.h
+++ b/src/in_xsf_framework/XSFCommon.h
@@ -1,7 +1,7 @@
 /*
  * xSF - Common functions
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
@@ -10,10 +10,16 @@
 
 #include <limits>
 #include <fstream>
+#if defined(_WIN32) && !defined(_MSC_VER)
+# include "fstream_wfopen.h"
+#endif
 #include <string>
 #define _USE_MATH_DEFINES
 #include <cmath>
 #include <cstdint>
+#include <cwchar>
+#include <cstring>
+#include "convert.h"
 
 // Code from http://learningcppisfun.blogspot.com/2010/04/comparing-floating-point-numbers.html
 template<typename T> inline bool fEqual(T x, T y, int N = 1)
@@ -80,11 +86,35 @@
 	return !!file;
 }
 
-#ifdef _MSC_VER
+#ifdef _WIN32
 inline bool FileExists(const std::wstring &filename)
 {
+#ifdef _MSC_VER
 	std::ifstream file(filename.c_str());
+#else
+	ifstream_wfopen file(filename.c_str());
+#endif
 	return !!file;
 }
 #endif
 
+inline void CopyToString(const std::wstring &src, wchar_t *dst)
+{
+	wcscpy(dst, src.c_str());
+}
+
+inline void CopyToString(const std::string &src, wchar_t *dst)
+{
+	wcscpy(dst, ConvertFuncs::StringToWString(src).c_str());
+}
+
+inline void CopyToString(const std::string &src, char *dst)
+{
+	strcpy(dst, src.c_str());
+}
+
+inline void CopyToString(const std::wstring &src, char *dst)
+{
+	strcpy(dst, ConvertFuncs::WStringToString(src).c_str());
+}
+

--- a/src/in_xsf_framework/XSFConfig.cpp
+++ b/src/in_xsf_framework/XSFConfig.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - Core configuration handler
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-08
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
@@ -9,7 +9,6 @@
 #include "XSFConfig.h"
 #include "XSFPlayer.h"
 #include "convert.h"
-#include "BigSString.h"
 
 enum
 {
@@ -34,23 +33,23 @@
 };
 
 bool XSFConfig::initPlayInfinitely = false;
-std::wstring XSFConfig::initSkipSilenceOnStartSec = L"5";
-std::wstring XSFConfig::initDetectSilenceSec = L"5";
-std::wstring XSFConfig::initDefaultLength = L"1:55";
-std::wstring XSFConfig::initDefaultFade = L"5";
-std::wstring XSFConfig::initTitleFormat = L"%game%[ - [%disc%.]%track%] - %title%";
+std::string XSFConfig::initSkipSilenceOnStartSec = "5";
+std::string XSFConfig::initDetectSilenceSec = "5";
+std::string XSFConfig::initDefaultLength = "1:55";
+std::string XSFConfig::initDefaultFade = "5";
+std::string XSFConfig::initTitleFormat = "%game%[ - [%disc%.]%track%] - %title%";
 double XSFConfig::initVolume = 1.0;
 VolumeType XSFConfig::initVolumeType = VOLUMETYPE_REPLAYGAIN_ALBUM;
 PeakType XSFConfig::initPeakType = PEAKTYPE_REPLAYGAIN_TRACK;
 
 XSFConfig::XSFConfig() : playInfinitely(false), skipSilenceOnStartSec(0), detectSilenceSec(0), defaultLength(0), defaultFade(0), volume(0.0), volumeType(VOLUMETYPE_NONE), peakType(PEAKTYPE_NONE),
-	sampleRate(0), titleFormat(L""), configDialog(), configDialogProperty(), infoDialog(), supportedSampleRates(), configIO(XSFConfigIO::Create())
-{
-}
-
-const String &XSFConfig::CommonNameWithVersion()
-{
-	static const auto commonNameWithVersion = String(XSFConfig::commonName + L" v" + XSFConfig::versionNumber);
+	sampleRate(0), titleFormat(""), configDialog(), configDialogProperty(), infoDialog(), supportedSampleRates(), configIO(XSFConfigIO::Create())
+{
+}
+
+const std::string &XSFConfig::CommonNameWithVersion()
+{
+	static const auto commonNameWithVersion = XSFConfig::commonName + " v" + XSFConfig::versionNumber;
 	return commonNameWithVersion;
 }
 
@@ -64,32 +63,32 @@
 
 void XSFConfig::LoadConfig()
 {
-	this->playInfinitely = this->configIO->GetValue(L"PlayInfinitely", XSFConfig::initPlayInfinitely);
-	this->skipSilenceOnStartSec = ConvertFuncs::StringToMS(this->configIO->GetValue(L"SkipSilenceOnStartSec", XSFConfig::initSkipSilenceOnStartSec));
-	this->detectSilenceSec = ConvertFuncs::StringToMS(this->configIO->GetValue(L"DetectSilenceSec", XSFConfig::initDetectSilenceSec));
-	this->defaultLength = ConvertFuncs::StringToMS(this->configIO->GetValue(L"DefaultLength", XSFConfig::initDefaultLength));
-	this->defaultFade = ConvertFuncs::StringToMS(this->configIO->GetValue(L"DefaultFade", XSFConfig::initDefaultFade));
-	this->volume = this->configIO->GetValue(L"Volume", XSFConfig::initVolume);
-	this->volumeType = static_cast<VolumeType>(this->configIO->GetValue(L"VolumeType", static_cast<int>(XSFConfig::initVolumeType)));
-	this->peakType = static_cast<PeakType>(this->configIO->GetValue(L"PeakType", static_cast<int>(XSFConfig::initPeakType)));
-	this->sampleRate = this->configIO->GetValue(L"SampleRate", XSFConfig::initSampleRate);
-	this->titleFormat = this->configIO->GetValue(L"TitleFormat", XSFConfig::initTitleFormat);
+	this->playInfinitely = this->configIO->GetValue("PlayInfinitely", XSFConfig::initPlayInfinitely);
+	this->skipSilenceOnStartSec = ConvertFuncs::StringToMS(this->configIO->GetValue("SkipSilenceOnStartSec", XSFConfig::initSkipSilenceOnStartSec));
+	this->detectSilenceSec = ConvertFuncs::StringToMS(this->configIO->GetValue("DetectSilenceSec", XSFConfig::initDetectSilenceSec));
+	this->defaultLength = ConvertFuncs::StringToMS(this->configIO->GetValue("DefaultLength", XSFConfig::initDefaultLength));
+	this->defaultFade = ConvertFuncs::StringToMS(this->configIO->GetValue("DefaultFade", XSFConfig::initDefaultFade));
+	this->volume = this->configIO->GetValue("Volume", XSFConfig::initVolume);
+	this->volumeType = static_cast<VolumeType>(this->configIO->GetValue("VolumeType", static_cast<int>(XSFConfig::initVolumeType)));
+	this->peakType = static_cast<PeakType>(this->configIO->GetValue("PeakType", static_cast<int>(XSFConfig::initPeakType)));
+	this->sampleRate = this->configIO->GetValue("SampleRate", XSFConfig::initSampleRate);
+	this->titleFormat = this->configIO->GetValue("TitleFormat", XSFConfig::initTitleFormat);
 
 	this->LoadSpecificConfig();
 }
 
 void XSFConfig::SaveConfig()
 {
-	this->configIO->SetValue(L"PlayInfinitely", this->playInfinitely);
-	this->configIO->SetValue(L"SkipSilenceOnStartSec", ConvertFuncs::MSToWString(this->skipSilenceOnStartSec));
-	this->configIO->SetValue(L"DetectSilenceSec", ConvertFuncs::MSToWString(this->detectSilenceSec));
-	this->configIO->SetValue(L"DefaultLength", ConvertFuncs::MSToWString(this->defaultLength));
-	this->configIO->SetValue(L"DefaultFade", ConvertFuncs::MSToWString(this->defaultFade));
-	this->configIO->SetValue(L"Volume", this->volume);
-	this->configIO->SetValue(L"VolumeType", this->volumeType);
-	this->configIO->SetValue(L"PeakType", this->peakType);
-	this->configIO->SetValue(L"SampleRate", this->sampleRate);
-	this->configIO->SetValue(L"TitleFormat", this->titleFormat);
+	this->configIO->SetValue("PlayInfinitely", this->playInfinitely);
+	this->configIO->SetValue("SkipSilenceOnStartSec", ConvertFuncs::MSToString(this->skipSilenceOnStartSec));
+	this->configIO->SetValue("DetectSilenceSec", ConvertFuncs::MSToString(this->detectSilenceSec));
+	this->configIO->SetValue("DefaultLength", ConvertFuncs::MSToString(this->defaultLength));
+	this->configIO->SetValue("DefaultFade", ConvertFuncs::MSToString(this->defaultFade));
+	this->configIO->SetValue("Volume", this->volume);
+	this->configIO->SetValue("VolumeType", this->volumeType);
+	this->configIO->SetValue("PeakType", this->peakType);
+	this->configIO->SetValue("SampleRate", this->sampleRate);
+	this->configIO->SetValue("TitleFormat", this->titleFormat);
 
 	this->SaveSpecificConfig();
 }
@@ -119,7 +118,7 @@
 	this->infoDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(200, 54).WithRelativePositionToSibling(RelativePosition::FROM_TOPRIGHT, Point<short>(5, -3)).IsLeftJustified().WithAutoVScroll().WithBorder().
 		WithTabStop().WithID(idInfoComment).WithVerticalScrollbar().WithWantReturn().IsMultiline());
 
-	this->configDialog = DialogBuilder().WithTitle(XSFConfig::commonName + L" v" + XSFConfig::versionNumber).IsPopup().WithBorder().WithDialogFrame().WithDialogModalFrame().WithSystemMenu().WithFont(L"MS Shell Dlg", 8);
+	this->configDialog = DialogBuilder().WithTitle(ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber)).IsPopup().WithBorder().WithDialogFrame().WithDialogModalFrame().WithSystemMenu().WithFont(L"MS Shell Dlg", 8);
 	this->configDialog.AddGroupControl(DialogGroupBuilder(L"General").WithRelativePositionToParent(RelativePositionToParent::FROM_TOPLEFT, Point<short>(7, 7)));
 	this->configDialog.AddCheckBoxControl(DialogCheckBoxBuilder(L"Play infinitely").WithSize(60, 10).InGroup(L"General").WithRelativePositionToParent(RelativePosition::FROM_TOPLEFT, Point<short>(6, 11)).WithTabStop().
 		WithID(idPlayInfinitely));
@@ -247,7 +246,7 @@
 				if (this->sampleRate == rate)
 					SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_SETCURSEL, x, 0);
 			}
-			SetWindowTextW(GetDlgItem(hwndDlg, idTitleFormat), this->titleFormat.c_str());
+			SetWindowTextW(GetDlgItem(hwndDlg, idTitleFormat), ConvertFuncs::StringToWString(this->titleFormat).c_str());
 			break;
 		case WM_COMMAND:
 			switch (GET_WM_COMMAND_ID(wParam, lParam))
@@ -283,14 +282,14 @@
 			EndDialog(hwndDlg, IDCANCEL);
 			break;
 		case WM_INITDIALOG:
-			SetWindowTextW(hwndDlg, xSFFileInInfo->GetFilename().GetWStrC());
-			SetWindowTextW(GetDlgItem(hwndDlg, idInfoTitle), xSFFileInInfo->GetTagValue("title").GetWStrC());
-			SetWindowTextW(GetDlgItem(hwndDlg, idInfoArtist), xSFFileInInfo->GetTagValue("artist").GetWStrC());
-			SetWindowTextW(GetDlgItem(hwndDlg, idInfoGame), xSFFileInInfo->GetTagValue("game").GetWStrC());
-			SetWindowTextW(GetDlgItem(hwndDlg, idInfoYear), xSFFileInInfo->GetTagValue("year").GetWStrC());
-			SetWindowTextW(GetDlgItem(hwndDlg, idInfoGenre), xSFFileInInfo->GetTagValue("genre").GetWStrC());
-			SetWindowTextW(GetDlgItem(hwndDlg, idInfoCopyright), xSFFileInInfo->GetTagValue("copyright").GetWStrC());
-			SetWindowTextW(GetDlgItem(hwndDlg, idInfoComment), xSFFileInInfo->GetTagValue("comment").GetWStrC());
+			SetWindowTextW(hwndDlg, ConvertFuncs::StringToWString(xSFFileInInfo->GetFilename()).c_str());
+			SetWindowTextW(GetDlgItem(hwndDlg, idInfoTitle), ConvertFuncs::StringToWString(xSFFileInInfo->GetTagValue("title")).c_str());
+			SetWindowTextW(GetDlgItem(hwndDlg, idInfoArtist), ConvertFuncs::StringToWString(xSFFileInInfo->GetTagValue("artist")).c_str());
+			SetWindowTextW(GetDlgItem(hwndDlg, idInfoGame), ConvertFuncs::StringToWString(xSFFileInInfo->GetTagValue("game")).c_str());
+			SetWindowTextW(GetDlgItem(hwndDlg, idInfoYear), ConvertFuncs::StringToWString(xSFFileInInfo->GetTagValue("year")).c_str());
+			SetWindowTextW(GetDlgItem(hwndDlg, idInfoGenre), ConvertFuncs::StringToWString(xSFFileInInfo->GetTagValue("genre")).c_str());
+			SetWindowTextW(GetDlgItem(hwndDlg, idInfoCopyright), ConvertFuncs::StringToWString(xSFFileInInfo->GetTagValue("copyright")).c_str());
+			SetWindowTextW(GetDlgItem(hwndDlg, idInfoComment), ConvertFuncs::StringToWString(xSFFileInInfo->GetTagValue("comment")).c_str());
 			break;
 		case WM_COMMAND:
 			switch (GET_WM_COMMAND_ID(wParam, lParam))
@@ -333,16 +332,16 @@
 void XSFConfig::ResetConfigDefaults(HWND hwndDlg)
 {
 	SendMessageW(GetDlgItem(hwndDlg, idPlayInfinitely), BM_SETCHECK, XSFConfig::initPlayInfinitely ? BST_CHECKED : BST_UNCHECKED, 0);
-	SetWindowTextW(GetDlgItem(hwndDlg, idDefaultLength), XSFConfig::initDefaultLength.c_str());
-	SetWindowTextW(GetDlgItem(hwndDlg, idDefaultFade), XSFConfig::initDefaultFade.c_str());
-	SetWindowTextW(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec), XSFConfig::initSkipSilenceOnStartSec.c_str());
-	SetWindowTextW(GetDlgItem(hwndDlg, idDetectSilenceSec), XSFConfig::initDetectSilenceSec.c_str());
+	SetWindowTextW(GetDlgItem(hwndDlg, idDefaultLength), ConvertFuncs::StringToWString(XSFConfig::initDefaultLength).c_str());
+	SetWindowTextW(GetDlgItem(hwndDlg, idDefaultFade), ConvertFuncs::StringToWString(XSFConfig::initDefaultFade).c_str());
+	SetWindowTextW(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec), ConvertFuncs::StringToWString(XSFConfig::initSkipSilenceOnStartSec).c_str());
+	SetWindowTextW(GetDlgItem(hwndDlg, idDetectSilenceSec), ConvertFuncs::StringToWString(XSFConfig::initDetectSilenceSec).c_str());
 	SetWindowTextW(GetDlgItem(hwndDlg, idVolume), wstringify(XSFConfig::initVolume).c_str());
 	SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_SETCURSEL, XSFConfig::initVolumeType, 0);
 	SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_SETCURSEL, XSFConfig::initPeakType, 0);
 	auto found = std::find(this->supportedSampleRates.begin(), this->supportedSampleRates.end(), XSFConfig::initSampleRate);
 	SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_SETCURSEL, found - this->supportedSampleRates.begin(), 0);
-	SetWindowTextW(GetDlgItem(hwndDlg, idTitleFormat), XSFConfig::initTitleFormat.c_str());
+	SetWindowTextW(GetDlgItem(hwndDlg, idTitleFormat), ConvertFuncs::StringToWString(XSFConfig::initTitleFormat).c_str());
 
 	this->ResetSpecificConfigDefaults(hwndDlg);
 }
@@ -358,7 +357,7 @@
 	this->volumeType = static_cast<VolumeType>(SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_GETCURSEL, 0, 0));
 	this->peakType = static_cast<PeakType>(SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_GETCURSEL, 0, 0));
 	this->sampleRate = XSFConfig::supportedSampleRates[SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_GETCURSEL, 0, 0)];
-	this->titleFormat = this->GetTextFromWindow(GetDlgItem(hwndDlg, idTitleFormat));
+	this->titleFormat = ConvertFuncs::WStringToString(this->GetTextFromWindow(GetDlgItem(hwndDlg, idTitleFormat)));
 
 	this->SaveSpecificConfigDialog(hwndDlg);
 }
@@ -411,7 +410,7 @@
 	return this->peakType;
 }
 
-const std::wstring &XSFConfig::GetTitleFormat() const
+const std::string &XSFConfig::GetTitleFormat() const
 {
 	return this->titleFormat;
 }

--- a/src/in_xsf_framework/XSFConfig.h
+++ b/src/in_xsf_framework/XSFConfig.h
@@ -1,7 +1,7 @@
 /*
  * xSF - Core configuration handler
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-08
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
@@ -24,12 +24,12 @@
 	static XSFConfigIO *Create();
 
 	virtual ~XSFConfigIO() { }
-	virtual void SetValueString(const std::wstring &name, const std::wstring &value) = 0;
-	template<typename T> void SetValue(const std::wstring &name, const T &value) { this->SetValueString(name, wstringify(value)); }
-	void SetValue(const std::wstring &name, const std::wstring &value) { this->SetValueString(name, value); }
-	virtual std::wstring GetValueString(const std::wstring &name, const std::wstring &defaultValue) = 0;
-	template<typename T> T GetValue(const std::wstring &name, const T &defaultValue) { return convertTo<T>(this->GetValueString(name, wstringify(defaultValue))); }
-	std::wstring GetValue(const std::wstring &name, const std::wstring &defaultValue) { return this->GetValueString(name, defaultValue); }
+	virtual void SetValueString(const std::string &name, const std::string &value) = 0;
+	template<typename T> void SetValue(const std::string &name, const T &value) { this->SetValueString(name, stringify(value)); }
+	void SetValue(const std::string &name, const std::string &value) { this->SetValueString(name, value); }
+	virtual std::string GetValueString(const std::string &name, const std::string &defaultValue) = 0;
+	template<typename T> T GetValue(const std::string &name, const T &defaultValue) { return convertTo<T>(this->GetValueString(name, stringify(defaultValue))); }
+	std::string GetValue(const std::string &name, const std::string &defaultValue) { return this->GetValueString(name, defaultValue); }
 };
 
 class XSFConfig
@@ -41,7 +41,7 @@
 	VolumeType volumeType;
 	PeakType peakType;
 	unsigned sampleRate;
-	std::wstring titleFormat;
+	std::string titleFormat;
 	DialogTemplate configDialog, configDialogProperty, infoDialog;
 	std::vector<unsigned> supportedSampleRates;
 	std::unique_ptr<XSFConfigIO> configIO;
@@ -58,17 +58,17 @@
 	virtual void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) = 0;
 public:
 	static bool initPlayInfinitely;
-	static std::wstring initSkipSilenceOnStartSec, initDetectSilenceSec, initDefaultLength, initDefaultFade, initTitleFormat;
+	static std::string initSkipSilenceOnStartSec, initDetectSilenceSec, initDefaultLength, initDefaultFade, initTitleFormat;
 	static double initVolume;
 	static VolumeType initVolumeType;
 	static PeakType initPeakType;
 	// These are not defined in XSFConfig.cpp, they should be defined in your own config's source.
 	static unsigned initSampleRate;
-	static std::wstring commonName;
-	static std::wstring versionNumber;
+	static std::string commonName;
+	static std::string versionNumber;
 	// The Create function is not defined in XSFConfig.cpp, it should be defined in your own config's source and return a pointer to your config's class.
 	static XSFConfig *Create();
-	static const String &CommonNameWithVersion();
+	static const std::string &CommonNameWithVersion();
 
 	virtual ~XSFConfig() { }
 	void LoadConfig();
@@ -92,6 +92,6 @@
 	double GetVolume() const;
 	VolumeType GetVolumeType() const;
 	PeakType GetPeakType() const;
-	const std::wstring &GetTitleFormat() const;
+	const std::string &GetTitleFormat() const;
 };
 

--- a/src/in_xsf_framework/XSFConfig_Winamp.cpp
+++ b/src/in_xsf_framework/XSFConfig_Winamp.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - Winamp-specification configuration handler
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2013-04-23
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
@@ -21,8 +21,8 @@
 
 	XSFConfigIO_Winamp();
 public:
-	void SetValueString(const std::wstring &name, const std::wstring &value);
-	std::wstring GetValueString(const std::wstring &name, const std::wstring &defaultValue);
+	void SetValueString(const std::string &name, const std::string &value);
+	std::string GetValueString(const std::string &name, const std::string &defaultValue);
 };
 
 XSFConfigIO *XSFConfigIO::Create()
@@ -33,7 +33,7 @@
 XSFConfigIO_Winamp::XSFConfigIO_Winamp() : iniFilename(L"")
 {
 	if (SendMessage(inMod.hMainWindow, WM_WA_IPC, 0, IPC_GETVERSION) >= 0x2900)
-		this->iniFilename = String(reinterpret_cast<char *>(SendMessage(inMod.hMainWindow, WM_WA_IPC, 0, IPC_GETINIFILE))).GetWStr();
+		this->iniFilename = ConvertFuncs::StringToWString(reinterpret_cast<char *>(SendMessage(inMod.hMainWindow, WM_WA_IPC, 0, IPC_GETINIFILE)));
 	else
 	{
 		auto executablePath = std::vector<wchar_t>(MAX_PATH / 2);
@@ -52,12 +52,12 @@
 	}
 }
 
-void XSFConfigIO_Winamp::SetValueString(const std::wstring &name, const std::wstring &value)
+void XSFConfigIO_Winamp::SetValueString(const std::string &name, const std::string &value)
 {
-	WritePrivateProfileStringW(XSFConfig::commonName.c_str(), name.c_str(), value.c_str(), this->iniFilename.c_str());
+	WritePrivateProfileStringW(ConvertFuncs::StringToWString(XSFConfig::commonName).c_str(), ConvertFuncs::StringToWString(name).c_str(), ConvertFuncs::StringToWString(value).c_str(), this->iniFilename.c_str());
 }
 
-std::wstring XSFConfigIO_Winamp::GetValueString(const std::wstring &name, const std::wstring &defaultValue)
+std::string XSFConfigIO_Winamp::GetValueString(const std::string &name, const std::string &defaultValue)
 {
 	auto value = std::vector<wchar_t>(MAX_PATH / 2);
 
@@ -65,12 +65,12 @@
 	do
 	{
 		value.resize(value.size() * 2);
-		result = GetPrivateProfileStringW(XSFConfig::commonName.c_str(), name.c_str(), defaultValue.c_str(), &value[0], value.size(), this->iniFilename.c_str());
+		result = GetPrivateProfileStringW(ConvertFuncs::StringToWString(XSFConfig::commonName).c_str(), ConvertFuncs::StringToWString(name).c_str(), ConvertFuncs::StringToWString(defaultValue).c_str(), &value[0], value.size(), this->iniFilename.c_str());
 	} while (result + 1 == value.size());
 
 	if (!result)
 		throw std::runtime_error("Unable to get value from INI file.");
 
-	return std::wstring(value.begin(), value.begin() + result);
+	return ConvertFuncs::WStringToString(std::wstring(value.begin(), value.begin() + result));
 }
 

--- a/src/in_xsf_framework/XSFFile.cpp
+++ b/src/in_xsf_framework/XSFFile.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - File structure
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
@@ -64,13 +64,13 @@
 	this->ReadXSF(filename, programSizeOffset, programHeaderSize);
 }
 
-#ifdef _MSC_VER
-XSFFile::XSFFile(const std::wstring &filename) : xSFType(0), hasFile(false), rawData(), reservedSection(), programSection(), tags(), fileName(filename)
+#ifdef _WIN32
+XSFFile::XSFFile(const std::wstring &filename) : xSFType(0), hasFile(false), rawData(), reservedSection(), programSection(), tags(), fileName(ConvertFuncs::WStringToString(filename))
 {
 	this->ReadXSF(filename, 0, 0, true);
 }
 
-XSFFile::XSFFile(const std::wstring &filename, uint32_t programSizeOffset, uint32_t programHeaderSize) : xSFType(0), hasFile(false), rawData(), reservedSection(), programSection(), tags(), fileName(filename)
+XSFFile::XSFFile(const std::wstring &filename, uint32_t programSizeOffset, uint32_t programHeaderSize) : xSFType(0), hasFile(false), rawData(), reservedSection(), programSection(), tags(), fileName(ConvertFuncs::WStringToString(filename))
 {
 	this->ReadXSF(filename, programSizeOffset, programHeaderSize);
 }
@@ -86,19 +86,27 @@
 	xSF.open(filename.c_str(), std::ifstream::in | std::ifstream::binary);
 
 	this->ReadXSF(xSF, programSizeOffset, programHeaderSize, readTagsOnly);
-}
-
-#ifdef _MSC_VER
+
+	xSF.close();
+}
+
+#ifdef _WIN32
 void XSFFile::ReadXSF(const std::wstring &filename, uint32_t programSizeOffset, uint32_t programHeaderSize, bool readTagsOnly)
 {
 	if (!FileExists(filename))
-		throw std::logic_error("File " + String(filename).GetAnsi() + " does not exist.");
-
+		throw std::logic_error("File " + ConvertFuncs::WStringToString(filename) + " does not exist.");
+
+#if defined(_WIN32) && !defined(_MSC_VER)
+	ifstream_wfopen xSF;
+#else
 	std::ifstream xSF;
+#endif
 	xSF.exceptions(std::ifstream::failbit | std::ifstream::badbit);
 	xSF.open(filename.c_str(), std::ifstream::in | std::ifstream::binary);
 
 	this->ReadXSF(xSF, programSizeOffset, programHeaderSize, readTagsOnly);
+
+	xSF.close();
 }
 #endif
 
@@ -214,8 +222,6 @@
 		}
 	}
 
-	xSF.close();
-
 	this->hasFile = true;
 }
 
@@ -268,9 +274,14 @@
 	this->tags = newTags;
 }
 
-void XSFFile::SetTag(const std::string &name, const String &value)
-{
-	this->tags[name] = value.GetStr();
+void XSFFile::SetTag(const std::string &name, const std::string &value)
+{
+	this->tags[name] = value;
+}
+
+void XSFFile::SetTag(const std::string &name, const std::wstring &value)
+{
+	this->tags[name] = ConvertFuncs::WStringToString(value);
 }
 
 bool XSFFile::GetTagExists(const std::string &name) const
@@ -278,17 +289,17 @@
 	return this->tags.Exists(name);
 }
 
-String XSFFile::GetTagValue(const std::string &name) const
-{
-	return String(this->GetTagExists(name) ? this->tags[name] : "", this->GetTagExists("utf8"));
+std::string XSFFile::GetTagValue(const std::string &name) const
+{
+	return this->GetTagExists(name) ? this->tags[name] : "";
 }
 
 unsigned long XSFFile::GetLengthMS(unsigned long defaultLength) const
 {
 	unsigned long length = 0;
-	String value = this->GetTagValue("length");
+	std::string value = this->GetTagValue("length");
 	if (!value.empty())
-		length = ConvertFuncs::StringToMS(value.GetAnsi());
+		length = ConvertFuncs::StringToMS(value);
 	if (!length)
 		length = defaultLength;
 	return length;
@@ -297,9 +308,9 @@
 unsigned long XSFFile::GetFadeMS(unsigned long defaultFade) const
 {
 	unsigned long fade = defaultFade;
-	String value = this->GetTagValue("fade");
+	std::string value = this->GetTagValue("fade");
 	if (!value.empty())
-		fade = ConvertFuncs::StringToMS(value.GetAnsi());
+		fade = ConvertFuncs::StringToMS(value);
 	return fade;
 }
 
@@ -307,49 +318,49 @@
 {
 	if (preferredVolumeType == VOLUMETYPE_NONE)
 		return 1.0;
-	String replaygain_album_gain = this->GetTagValue("replaygain_album_gain"), replaygain_album_peak = this->GetTagValue("replaygain_album_peak");
-	String replaygain_track_gain = this->GetTagValue("replaygain_track_gain"), replaygain_track_peak = this->GetTagValue("replaygain_track_peak");
-	String volume = this->GetTagValue("volume");
+	std::string replaygain_album_gain = this->GetTagValue("replaygain_album_gain"), replaygain_album_peak = this->GetTagValue("replaygain_album_peak");
+	std::string replaygain_track_gain = this->GetTagValue("replaygain_track_gain"), replaygain_track_peak = this->GetTagValue("replaygain_track_peak");
+	std::string volume = this->GetTagValue("volume");
 	double gain = 0.0;
 	bool hadReplayGain = false;
 	if (preferredVolumeType == VOLUMETYPE_REPLAYGAIN_ALBUM && !replaygain_album_gain.empty())
 	{
-		gain = convertTo<double>(replaygain_album_gain.GetAnsi(), false);
+		gain = convertTo<double>(replaygain_album_gain, false);
 		hadReplayGain = true;
 	}
 	if (!hadReplayGain && preferredVolumeType != VOLUMETYPE_VOLUME && !replaygain_track_gain.empty())
 	{
-		gain = convertTo<double>(replaygain_track_gain.GetAnsi(), false);
+		gain = convertTo<double>(replaygain_track_gain, false);
 		hadReplayGain = true;
 	}
 	if (hadReplayGain)
 	{
 		double vol = std::pow(10.0, gain / 20.0), peak = 1.0;
 		if (preferredPeakType == PEAKTYPE_REPLAYGAIN_ALBUM && !replaygain_album_peak.empty())
-			peak = convertTo<double>(replaygain_album_peak.GetAnsi(), false);
+			peak = convertTo<double>(replaygain_album_peak, false);
 		else if (preferredPeakType != PEAKTYPE_NONE && !replaygain_track_peak.empty())
-			peak = convertTo<double>(replaygain_track_peak.GetAnsi(), false);
+			peak = convertTo<double>(replaygain_track_peak, false);
 		return !fEqual(peak, 1.0) ? std::min(vol, 1.0 / peak) : vol;
 	}
-	return volume.empty() ? 1.0 : convertTo<double>(volume.GetAnsi(), false);
-}
-
-String XSFFile::FormattedTitleOptionalBlock(const std::wstring &block, bool &hadReplacement, unsigned level) const
-{
-	String formattedBlock;
+	return volume.empty() ? 1.0 : convertTo<double>(volume, false);
+}
+
+std::string XSFFile::FormattedTitleOptionalBlock(const std::string &block, bool &hadReplacement, unsigned level) const
+{
+	std::string formattedBlock;
 	for (size_t x = 0, len = block.length(); x < len; ++x)
 	{
-		wchar_t c = block[x];
-		if (c == L'%')
+		char c = block[x];
+		if (c == '%')
 		{
 			size_t origX = x;
 			for (++x; x < len; ++x)
-				if (block[x] == L'%')
+				if (block[x] == '%')
 					break;
 			if (x != len)
 			{
-				std::wstring tagname = block.substr(origX + 1, x - origX - 1);
-				String value = this->GetTagValue(String(tagname).GetAnsi());
+				std::string tagname = block.substr(origX + 1, x - origX - 1);
+				std::string value = this->GetTagValue(tagname);
 				if (!value.empty())
 				{
 					formattedBlock += value;
@@ -358,15 +369,15 @@
 			}
 			continue;
 		}
-		if (c == L'[' && level + 1 < 10)
+		if (c == '[' && level + 1 < 10)
 		{
 			size_t origX = x;
 			unsigned nests = 0;
 			for (++x; x < len; ++x)
 			{
-				if (block[x] == L'[')
+				if (block[x] == '[')
 					++nests;
-				else if (block[x] == L']')
+				else if (block[x] == ']')
 				{
 					if (!nests)
 						break;
@@ -375,9 +386,9 @@
 			}
 			if (x != len)
 			{
-				std::wstring innerBlock = block.substr(origX + 1, x - origX - 1);
+				std::string innerBlock = block.substr(origX + 1, x - origX - 1);
 				bool hadInnerReplacement = false;
-				String replacedBlock = this->FormattedTitleOptionalBlock(innerBlock, hadInnerReplacement, level + 1);
+				std::string replacedBlock = this->FormattedTitleOptionalBlock(innerBlock, hadInnerReplacement, level + 1);
 				if (hadInnerReplacement)
 					formattedBlock += replacedBlock;
 			}
@@ -388,37 +399,37 @@
 	return formattedBlock;
 }
 
-String XSFFile::GetFormattedTitle(const std::wstring &format) const
-{
-	String formattedTitle;
+std::string XSFFile::GetFormattedTitle(const std::string &format) const
+{
+	std::string formattedTitle;
 	for (size_t x = 0, len = format.length(); x < len; ++x)
 	{
-		wchar_t c = format[x];
-		if (c == L'%')
+		char c = format[x];
+		if (c == '%')
 		{
 			size_t origX = x;
 			for (++x; x < len; ++x)
-				if (format[x] == L'%')
+				if (format[x] == '%')
 					break;
 			if (x != len)
 			{
-				std::wstring tagname = format.substr(origX + 1, x - origX - 1);
-				String value = this->GetTagValue(String(tagname).GetAnsi());
+				std::string tagname = format.substr(origX + 1, x - origX - 1);
+				std::string value = this->GetTagValue(tagname);
 				if (value.empty())
 					formattedTitle += "???";
 				else
 					formattedTitle += value;
 			}
 		}
-		else if (c == L'[')
+		else if (c == '[')
 		{
 			size_t origX = x;
 			unsigned nests = 0;
 			for (++x; x < len; ++x)
 			{
-				if (format[x] == L'[')
+				if (format[x] == '[')
 					++nests;
-				else if (format[x] == L']')
+				else if (format[x] == ']')
 				{
 					if (!nests)
 						break;
@@ -427,9 +438,9 @@
 			}
 			if (x != len)
 			{
-				std::wstring block = format.substr(origX + 1, x - origX - 1);
+				std::string block = format.substr(origX + 1, x - origX - 1);
 				bool hadReplacement = false;
-				String replacedBlock = this->FormattedTitleOptionalBlock(block, hadReplacement, 1);
+				std::string replacedBlock = this->FormattedTitleOptionalBlock(block, hadReplacement, 1);
 				if (hadReplacement)
 					formattedTitle += replacedBlock;
 			}
@@ -440,24 +451,28 @@
 	return formattedTitle;
 }
 
-String XSFFile::GetFilename() const
+std::string XSFFile::GetFilename() const
 {
 	return this->fileName;
 }
 
-String XSFFile::GetFilenameWithoutPath() const
-{
-	return ExtractFilenameFromPath(this->fileName.GetStr());
+std::string XSFFile::GetFilenameWithoutPath() const
+{
+	return ExtractFilenameFromPath(this->fileName);
 }
 
 void XSFFile::SaveFile() const
 {
+#if defined(_WIN32) && !defined(_MSC_VER)
+	ofstream_wfopen xSF;
+#else
 	std::ofstream xSF;
+#endif
 	xSF.exceptions(std::ofstream::failbit);
-#ifdef _MSC_VER
-	xSF.open(this->fileName.GetWStrC(), std::ofstream::out | std::ofstream::binary);
+#ifdef _WIN32
+	xSF.open(ConvertFuncs::StringToWString(this->fileName).c_str(), std::ofstream::out | std::ofstream::binary);
 #else
-	xSF.open(this->fileName.GetStrC(), std::ofstream::out | std::ofstream::binary);
+	xSF.open(this->fileName.c_str(), std::ofstream::out | std::ofstream::binary);
 #endif
 
 	xSF.write(reinterpret_cast<const char *>(&this->rawData[0]), this->rawData.size());

--- a/src/in_xsf_framework/XSFFile.h
+++ b/src/in_xsf_framework/XSFFile.h
@@ -1,7 +1,7 @@
 /*
  * xSF - File structure
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
@@ -11,7 +11,6 @@
 #include <cstdint>
 #include "convert.h"
 #include "TagList.h"
-#include "BigSString.h"
 
 enum VolumeType
 {
@@ -35,18 +34,18 @@
 	bool hasFile;
 	std::vector<uint8_t> rawData, reservedSection, programSection;
 	TagList tags;
-	String fileName;
+	std::string fileName;
 	void ReadXSF(const std::string &filename, uint32_t programSizeOffset, uint32_t programHeaderSize, bool readTagsOnly = false);
-#ifdef _MSC_VER
+#ifdef _WIN32
 	void ReadXSF(const std::wstring &filename, uint32_t programSizeOffset, uint32_t programHeaderSize, bool readTagsOnly = false);
 #endif
 	void ReadXSF(std::ifstream &xSF, uint32_t programSizeOffset, uint32_t programHeaderSize, bool readTagsOnly = false);
-	String FormattedTitleOptionalBlock(const std::wstring &block, bool &hadReplacement, unsigned level) const;
+	std::string FormattedTitleOptionalBlock(const std::string &block, bool &hadReplacement, unsigned level) const;
 public:
 	XSFFile();
 	XSFFile(const std::string &filename);
 	XSFFile(const std::string &filename, uint32_t programSizeOffset, uint32_t programHeaderSize);
-#ifdef _MSC_VER
+#ifdef _WIN32
 	XSFFile(const std::wstring &filename);
 	XSFFile(const std::wstring &filename, uint32_t programSizeOffset, uint32_t programHeaderSize);
 #endif
@@ -59,19 +58,20 @@
 	std::vector<uint8_t> GetProgramSection() const;
 	const TagList &GetAllTags() const;
 	void SetAllTags(const TagList &newTags);
-	void SetTag(const std::string &name, const String &value);
+	void SetTag(const std::string &name, const std::string &value);
+	void SetTag(const std::string &name, const std::wstring &value);
 	bool GetTagExists(const std::string &name) const;
-	String GetTagValue(const std::string &name) const;
+	std::string GetTagValue(const std::string &name) const;
 	template<typename T> T GetTagValue(const std::string &name, const T &defaultValue) const
 	{
-		return this->GetTagExists(name) ? convertTo<T>(this->GetTagValue(name).GetAnsi(), false) : defaultValue;
+		return this->GetTagExists(name) ? convertTo<T>(this->GetTagValue(name), false) : defaultValue;
 	}
 	unsigned long GetLengthMS(unsigned long defaultLength) const;
 	unsigned long GetFadeMS(unsigned long defaultFade) const;
 	double GetVolume(VolumeType preferredVolumeType, PeakType preferredPeakType) const;
-	String GetFormattedTitle(const std::wstring &format) const;
-	String GetFilename() const;
-	String GetFilenameWithoutPath() const;
+	std::string GetFormattedTitle(const std::string &format) const;
+	std::string GetFilename() const;
+	std::string GetFilenameWithoutPath() const;
 	void SaveFile() const;
 };
 

--- a/src/in_xsf_framework/XSFPlayer.cpp
+++ b/src/in_xsf_framework/XSFPlayer.cpp
@@ -1,7 +1,7 @@
 /*
  * xSF - Core Player
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-08
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */

--- a/src/in_xsf_framework/XSFPlayer.h
+++ b/src/in_xsf_framework/XSFPlayer.h
@@ -1,7 +1,7 @@
 /*
  * xSF - Core Player
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
@@ -37,7 +37,7 @@
 	static const char *WinampDescription;
 	static const char *WinampExts;
 	static XSFPlayer *Create(const std::string &fn);
-#ifdef _MSC_VER
+#ifdef _WIN32
 	static XSFPlayer *Create(const std::wstring &fn);
 #endif
 

--- /dev/null
+++ b/src/in_xsf_framework/codecvt.h
@@ -1,1 +1,2099 @@
-
+// This comes from llvm's libcxx project. I've copied the code from there (with very minor modifications) for use with GCC and Clang when libcxx isn't being used.
+
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(_LIBCPP_VERSION)
+#pragma once
+
+#include <locale>
+
+namespace std
+{
+
+enum codecvt_mode
+{
+	consume_header = 4,
+	generate_header = 2,
+	little_endian = 1
+};
+
+//                                     Valid UTF ranges
+//     UTF-32               UTF-16                          UTF-8               # of code points
+//                     first      second       first   second    third   fourth
+// 000000 - 00007F  0000 - 007F               00 - 7F                                 127
+// 000080 - 0007FF  0080 - 07FF               C2 - DF, 80 - BF                       1920
+// 000800 - 000FFF  0800 - 0FFF               E0 - E0, A0 - BF, 80 - BF              2048
+// 001000 - 00CFFF  1000 - CFFF               E1 - EC, 80 - BF, 80 - BF             49152
+// 00D000 - 00D7FF  D000 - D7FF               ED - ED, 80 - 9F, 80 - BF              2048
+// 00D800 - 00DFFF                invalid
+// 00E000 - 00FFFF  E000 - FFFF               EE - EF, 80 - BF, 80 - BF              8192
+// 010000 - 03FFFF  D800 - D8BF, DC00 - DFFF  F0 - F0, 90 - BF, 80 - BF, 80 - BF   196608
+// 040000 - 0FFFFF  D8C0 - DBBF, DC00 - DFFF  F1 - F3, 80 - BF, 80 - BF, 80 - BF   786432
+// 100000 - 10FFFF  DBC0 - DBFF, DC00 - DFFF  F4 - F4, 80 - 8F, 80 - BF, 80 - BF    65536
+
+namespace UnicodeConverters
+{
+	inline codecvt_base::result utf16_to_utf8(const uint16_t *frm, const uint16_t *frm_end, const uint16_t *&frm_nxt, uint8_t *to, uint8_t *to_end, uint8_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if (mode & generate_header)
+		{
+			if (to_end - to_nxt < 3)
+				return codecvt_base::partial;
+			*to_nxt++ = 0xEF;
+			*to_nxt++ = 0xBB;
+			*to_nxt++ = 0xBF;
+		}
+		for (; frm_nxt < frm_end; ++frm_nxt)
+		{
+			uint16_t wc1 = *frm_nxt;
+			if (wc1 > Maxcode)
+				return codecvt_base::error;
+			if (wc1 < 0x0080)
+			{
+				if (to_end - to_nxt < 1)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(wc1);
+			}
+			else if (wc1 < 0x0800)
+			{
+				if (to_end - to_nxt < 2)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
+			}
+			else if (wc1 < 0xD800)
+			{
+				if (to_end - to_nxt < 3)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
+			}
+			else if (wc1 < 0xDC00)
+			{
+				if (frm_end - frm_nxt < 2)
+					return codecvt_base::partial;
+				uint16_t wc2 = frm_nxt[1];
+				if ((wc2 & 0xFC00) != 0xDC00)
+					return codecvt_base::error;
+				if (to_end - to_nxt < 4)
+					return codecvt_base::partial;
+				if (((((static_cast<unsigned long>(wc1) & 0x03C0) >> 6) + 1) << 16) + ((static_cast<unsigned long>(wc1) & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
+					return codecvt_base::error;
+				++frm_nxt;
+				uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
+				*to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
+			}
+			else if (wc1 < 0xE000)
+				return codecvt_base::error;
+			else
+			{
+				if (to_end - to_nxt < 3)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
+			}
+		}
+		return codecvt_base::ok;
+	}
+
+	inline codecvt_base::result utf16_to_utf8(const uint32_t *frm, const uint32_t *frm_end, const uint32_t *&frm_nxt, uint8_t *to, uint8_t *to_end, uint8_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if (mode & generate_header)
+		{
+			if (to_end - to_nxt < 3)
+				return codecvt_base::partial;
+			*to_nxt++ = 0xEF;
+			*to_nxt++ = 0xBB;
+			*to_nxt++ = 0xBF;
+		}
+		for (; frm_nxt < frm_end; ++frm_nxt)
+		{
+			uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
+			if (wc1 > Maxcode)
+				return codecvt_base::error;
+			if (wc1 < 0x0080)
+			{
+				if (to_end - to_nxt < 1)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(wc1);
+			}
+			else if (wc1 < 0x0800)
+			{
+				if (to_end - to_nxt < 2)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
+			}
+			else if (wc1 < 0xD800)
+			{
+				if (to_end - to_nxt < 3)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
+			}
+			else if (wc1 < 0xDC00)
+			{
+				if (frm_end - frm_nxt < 2)
+					return codecvt_base::partial;
+				uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
+				if ((wc2 & 0xFC00) != 0xDC00)
+					return codecvt_base::error;
+				if (to_end - to_nxt < 4)
+					return codecvt_base::partial;
+				if (((((static_cast<unsigned long>(wc1) & 0x03C0) >> 6) + 1) << 16) + ((static_cast<unsigned long>(wc1) & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
+					return codecvt_base::error;
+				++frm_nxt;
+				uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
+				*to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
+			}
+			else if (wc1 < 0xE000)
+				return codecvt_base::error;
+			else
+			{
+				if (to_end - to_nxt < 3)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
+			}
+		}
+		return codecvt_base::ok;
+	}
+
+	inline codecvt_base::result utf8_to_utf16(const uint8_t *frm, const uint8_t *frm_end, const uint8_t *&frm_nxt, uint16_t *to, uint16_t *to_end, uint16_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
+			frm_nxt += 3;
+		for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
+		{
+			uint8_t c1 = *frm_nxt;
+			if (c1 > Maxcode)
+				return codecvt_base::error;
+			if (c1 < 0x80)
+			{
+				*to_nxt = static_cast<uint16_t>(c1);
+				++frm_nxt;
+			}
+			else if (c1 < 0xC2)
+				return codecvt_base::error;
+			else if (c1 < 0xE0)
+			{
+				if (frm_end - frm_nxt < 2)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				if ((c2 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = t;
+				frm_nxt += 2;
+			}
+			else if (c1 < 0xF0)
+			{
+				if (frm_end - frm_nxt < 3)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				switch (c1)
+				{
+					case 0xE0:
+						if ((c2 & 0xE0) != 0xA0)
+							return codecvt_base::error;
+						break;
+					case 0xED:
+						if ((c2 & 0xE0) != 0x80)
+							return codecvt_base::error;
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return codecvt_base::error;
+				}
+				if ((c3 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = t;
+				frm_nxt += 3;
+			}
+			else if (c1 < 0xF5)
+			{
+				if (frm_end - frm_nxt < 4)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				uint8_t c4 = frm_nxt[3];
+				switch (c1)
+				{
+					case 0xF0:
+						if (c2 < 0x90 || c2 > 0xBF)
+							return codecvt_base::error;
+						break;
+					case 0xF4:
+						if ((c2 & 0xF0) != 0x80)
+							return codecvt_base::error;
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return codecvt_base::error;
+				}
+				if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				if (to_end - to_nxt < 2)
+					return codecvt_base::partial;
+				if ((((static_cast<unsigned long>(c1) & 7) << 18) + ((static_cast<unsigned long>(c2) & 0x3F) << 12) + ((static_cast<unsigned long>(c3) & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = static_cast<uint16_t>(0xD800 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) | ((c2 & 0x0F) << 2) | ((c3 & 0x30) >> 4));
+				*++to_nxt = static_cast<uint16_t>(0xDC00 | ((c3 & 0x0F) << 6) | (c4 & 0x3F));
+				frm_nxt += 4;
+			}
+			else
+				return codecvt_base::error;
+		}
+		return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
+	}
+
+	inline codecvt_base::result utf8_to_utf16(const uint8_t *frm, const uint8_t *frm_end, const uint8_t *&frm_nxt, uint32_t *to, uint32_t *to_end, uint32_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
+			frm_nxt += 3;
+		for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
+		{
+			uint8_t c1 = *frm_nxt;
+			if (c1 > Maxcode)
+				return codecvt_base::error;
+			if (c1 < 0x80)
+			{
+				*to_nxt = static_cast<uint32_t>(c1);
+				++frm_nxt;
+			}
+			else if (c1 < 0xC2)
+				return codecvt_base::error;
+			else if (c1 < 0xE0)
+			{
+				if (frm_end - frm_nxt < 2)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				if ((c2 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = static_cast<uint32_t>(t);
+				frm_nxt += 2;
+			}
+			else if (c1 < 0xF0)
+			{
+				if (frm_end - frm_nxt < 3)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				switch (c1)
+				{
+					case 0xE0:
+						if ((c2 & 0xE0) != 0xA0)
+							return codecvt_base::error;
+						break;
+					case 0xED:
+						if ((c2 & 0xE0) != 0x80)
+							return codecvt_base::error;
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return codecvt_base::error;
+				}
+				if ((c3 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = static_cast<uint32_t>(t);
+				frm_nxt += 3;
+			}
+			else if (c1 < 0xF5)
+			{
+				if (frm_end - frm_nxt < 4)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				uint8_t c4 = frm_nxt[3];
+				switch (c1)
+				{
+					case 0xF0:
+						if (c2 < 0x90 || c2 > 0xBF)
+							return codecvt_base::error;
+						break;
+					case 0xF4:
+						if ((c2 & 0xF0) != 0x80)
+							return codecvt_base::error;
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return codecvt_base::error;
+				}
+				if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				if (to_end - to_nxt < 2)
+					return codecvt_base::partial;
+				if ((((static_cast<unsigned long>(c1) & 7) << 18) + ((static_cast<unsigned long>(c2) & 0x3F) << 12) + ((static_cast<unsigned long>(c3) & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = static_cast<uint32_t>(0xD800 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) | ((c2 & 0x0F) << 2) | ((c3 & 0x30) >> 4));
+				*++to_nxt = static_cast<uint32_t>( 0xDC00 | ((c3 & 0x0F) << 6) | (c4 & 0x3F));
+				frm_nxt += 4;
+			}
+			else
+				return codecvt_base::error;
+		}
+		return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
+	}
+
+	inline int utf8_to_utf16_length(const uint8_t *frm, const uint8_t *frm_end, size_t mx, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		auto frm_nxt = frm;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
+			frm_nxt += 3;
+		for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
+		{
+			uint8_t c1 = *frm_nxt;
+			if (c1 > Maxcode)
+				break;
+			if (c1 < 0x80)
+				++frm_nxt;
+			else if (c1 < 0xC2)
+				break;
+			else if (c1 < 0xE0)
+			{
+				if (frm_end - frm_nxt < 2 || (frm_nxt[1] & 0xC0) != 0x80)
+					break;
+				uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
+				if (t > Maxcode)
+					break;
+				frm_nxt += 2;
+			}
+			else if (c1 < 0xF0)
+			{
+				if (frm_end - frm_nxt < 3)
+					break;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				switch (c1)
+				{
+					case 0xE0:
+						if ((c2 & 0xE0) != 0xA0)
+							return static_cast<int>(frm_nxt - frm);
+						break;
+					case 0xED:
+						if ((c2 & 0xE0) != 0x80)
+							return static_cast<int>(frm_nxt - frm);
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return static_cast<int>(frm_nxt - frm);
+				}
+				if ((c3 & 0xC0) != 0x80)
+					break;
+				if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
+					break;
+				frm_nxt += 3;
+			}
+			else if (c1 < 0xF5)
+			{
+				if (frm_end - frm_nxt < 4 || mx - nchar16_t < 2)
+					break;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				uint8_t c4 = frm_nxt[3];
+				switch (c1)
+				{
+					case 0xF0:
+						if (c2 < 0x90 || c2 > 0xBF)
+							return static_cast<int>(frm_nxt - frm);
+						break;
+					case 0xF4:
+						if ((c2 & 0xF0) != 0x80)
+							return static_cast<int>(frm_nxt - frm);
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return static_cast<int>(frm_nxt - frm);
+				}
+				if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
+					break;
+				if ((((static_cast<unsigned long>(c1) & 7) << 18) + ((static_cast<unsigned long>(c2) & 0x3F) << 12) + ((static_cast<unsigned long>(c3) & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
+					break;
+				++nchar16_t;
+				frm_nxt += 4;
+			}
+			else
+				break;
+		}
+		return static_cast<int>(frm_nxt - frm);
+	}
+
+	inline codecvt_base::result ucs4_to_utf8(const uint32_t *frm, const uint32_t *frm_end, const uint32_t *&frm_nxt, uint8_t *to, uint8_t *to_end, uint8_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if (mode & generate_header)
+		{
+			if (to_end - to_nxt < 3)
+				return codecvt_base::partial;
+			*to_nxt++ = 0xEF;
+			*to_nxt++ = 0xBB;
+			*to_nxt++ = 0xBF;
+		}
+		for (; frm_nxt < frm_end; ++frm_nxt)
+		{
+			uint32_t wc = *frm_nxt;
+			if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
+				return codecvt_base::error;
+			if (wc < 0x000080)
+			{
+				if (to_end - to_nxt < 1)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(wc);
+			}
+			else if (wc < 0x000800)
+			{
+				if (to_end - to_nxt < 2)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
+			}
+			else if (wc < 0x010000)
+			{
+				if (to_end - to_nxt < 3)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
+			}
+			else // if (wc < 0x110000)
+			{
+				if (to_end - to_nxt < 4)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
+			}
+		}
+		return codecvt_base::ok;
+	}
+
+	inline codecvt_base::result utf8_to_ucs4(const uint8_t *frm, const uint8_t *frm_end, const uint8_t *&frm_nxt, uint32_t *to, uint32_t *to_end, uint32_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
+			frm_nxt += 3;
+		for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
+		{
+			uint8_t c1 = *frm_nxt;
+			if (c1 < 0x80)
+			{
+				if (c1 > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = static_cast<uint32_t>(c1);
+				++frm_nxt;
+			}
+			else if (c1 < 0xC2)
+				return codecvt_base::error;
+			else if (c1 < 0xE0)
+			{
+				if (frm_end - frm_nxt < 2)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				if ((c2 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = t;
+				frm_nxt += 2;
+			}
+			else if (c1 < 0xF0)
+			{
+				if (frm_end - frm_nxt < 3)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				switch (c1)
+				{
+					case 0xE0:
+						if ((c2 & 0xE0) != 0xA0)
+							return codecvt_base::error;
+						break;
+					case 0xED:
+						if ((c2 & 0xE0) != 0x80)
+							return codecvt_base::error;
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return codecvt_base::error;
+				}
+				if ((c3 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) |  (c3 & 0x3F));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = t;
+				frm_nxt += 3;
+			}
+			else if (c1 < 0xF5)
+			{
+				if (frm_end - frm_nxt < 4)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				uint8_t c4 = frm_nxt[3];
+				switch (c1)
+				{
+					case 0xF0:
+						if (c2 < 0x90 || c2 > 0xBF)
+							return codecvt_base::error;
+						break;
+					case 0xF4:
+						if ((c2 & 0xF0) != 0x80)
+							return codecvt_base::error;
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return codecvt_base::error;
+				}
+				if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) |  (c4 & 0x3F));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = t;
+				frm_nxt += 4;
+			}
+			else
+				return codecvt_base::error;
+		}
+		return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
+	}
+
+	inline int utf8_to_ucs4_length(const uint8_t *frm, const uint8_t *frm_end, size_t mx, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		auto frm_nxt = frm;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
+			frm_nxt += 3;
+		for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
+		{
+			uint8_t c1 = *frm_nxt;
+			if (c1 < 0x80)
+			{
+				if (c1 > Maxcode)
+					break;
+				++frm_nxt;
+			}
+			else if (c1 < 0xC2)
+				break;
+			else if (c1 < 0xE0)
+			{
+				if (frm_end - frm_nxt < 2 || (frm_nxt[1] & 0xC0) != 0x80)
+					break;
+				if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
+					break;
+				frm_nxt += 2;
+			}
+			else if (c1 < 0xF0)
+			{
+				if (frm_end - frm_nxt < 3)
+					break;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				switch (c1)
+				{
+					case 0xE0:
+						if ((c2 & 0xE0) != 0xA0)
+							return static_cast<int>(frm_nxt - frm);
+						break;
+					case 0xED:
+						if ((c2 & 0xE0) != 0x80)
+							return static_cast<int>(frm_nxt - frm);
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return static_cast<int>(frm_nxt - frm);
+				}
+				if ((c3 & 0xC0) != 0x80)
+					break;
+				if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
+					break;
+				frm_nxt += 3;
+			}
+			else if (c1 < 0xF5)
+			{
+				if (frm_end - frm_nxt < 4)
+					break;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				uint8_t c4 = frm_nxt[3];
+				switch (c1)
+				{
+					case 0xF0:
+						if (c2 < 0x90 || c2 > 0xBF)
+							return static_cast<int>(frm_nxt - frm);
+						break;
+					case 0xF4:
+						if ((c2 & 0xF0) != 0x80)
+							return static_cast<int>(frm_nxt - frm);
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return static_cast<int>(frm_nxt - frm);
+				}
+				if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
+					break;
+				if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) | ((c3 & 0x3Fu) << 6)  |  (c4 & 0x3Fu)) > Maxcode)
+					break;
+				frm_nxt += 4;
+			}
+			else
+				break;
+		}
+		return static_cast<int>(frm_nxt - frm);
+	}
+
+	inline codecvt_base::result ucs2_to_utf8(const uint16_t *frm, const uint16_t *frm_end, const uint16_t *&frm_nxt, uint8_t *to, uint8_t *to_end, uint8_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if (mode & generate_header)
+		{
+			if (to_end - to_nxt < 3)
+				return codecvt_base::partial;
+			*to_nxt++ = 0xEF;
+			*to_nxt++ = 0xBB;
+			*to_nxt++ = 0xBF;
+		}
+		for (; frm_nxt < frm_end; ++frm_nxt)
+		{
+			uint16_t wc = *frm_nxt;
+			if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
+				return codecvt_base::error;
+			if (wc < 0x0080)
+			{
+				if (to_end - to_nxt < 1)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(wc);
+			}
+			else if (wc < 0x0800)
+			{
+				if (to_end - to_nxt < 2)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
+			}
+			else // if (wc <= 0xFFFF)
+			{
+				if (to_end - to_nxt < 3)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
+				*to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
+			}
+		}
+		return codecvt_base::ok;
+	}
+
+	inline codecvt_base::result utf8_to_ucs2(const uint8_t *frm, const uint8_t *frm_end, const uint8_t *&frm_nxt, uint16_t *to, uint16_t *to_end, uint16_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
+			frm_nxt += 3;
+		for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
+		{
+			uint8_t c1 = *frm_nxt;
+			if (c1 < 0x80)
+			{
+				if (c1 > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = static_cast<uint16_t>(c1);
+				++frm_nxt;
+			}
+			else if (c1 < 0xC2)
+				return codecvt_base::error;
+			else if (c1 < 0xE0)
+			{
+				if (frm_end - frm_nxt < 2)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				if ((c2 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = t;
+				frm_nxt += 2;
+			}
+			else if (c1 < 0xF0)
+			{
+				if (frm_end - frm_nxt < 3)
+					return codecvt_base::partial;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				switch (c1)
+				{
+					case 0xE0:
+						if ((c2 & 0xE0) != 0xA0)
+							return codecvt_base::error;
+						break;
+					case 0xED:
+						if ((c2 & 0xE0) != 0x80)
+							return codecvt_base::error;
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return codecvt_base::error;
+				}
+				if ((c3 & 0xC0) != 0x80)
+					return codecvt_base::error;
+				uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) |  (c3 & 0x3F));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = t;
+				frm_nxt += 3;
+			}
+			else
+				return codecvt_base::error;
+		}
+		return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
+	}
+
+	inline int utf8_to_ucs2_length(const uint8_t *frm, const uint8_t *frm_end, size_t mx, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		auto frm_nxt = frm;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
+			frm_nxt += 3;
+		for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
+		{
+			uint8_t c1 = *frm_nxt;
+			if (c1 < 0x80)
+			{
+				if (c1 > Maxcode)
+					break;
+				++frm_nxt;
+			}
+			else if (c1 < 0xC2)
+				break;
+			else if (c1 < 0xE0)
+			{
+				if (frm_end - frm_nxt < 2 || (frm_nxt[1] & 0xC0) != 0x80)
+					break;
+				if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
+					break;
+				frm_nxt += 2;
+			}
+			else if (c1 < 0xF0)
+			{
+				if (frm_end - frm_nxt < 3)
+					break;
+				uint8_t c2 = frm_nxt[1];
+				uint8_t c3 = frm_nxt[2];
+				switch (c1)
+				{
+					case 0xE0:
+						if ((c2 & 0xE0) != 0xA0)
+							return static_cast<int>(frm_nxt - frm);
+						break;
+					case 0xED:
+						if ((c2 & 0xE0) != 0x80)
+							return static_cast<int>(frm_nxt - frm);
+						break;
+					default:
+						if ((c2 & 0xC0) != 0x80)
+							return static_cast<int>(frm_nxt - frm);
+				}
+				if ((c3 & 0xC0) != 0x80)
+					break;
+				if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
+					break;
+				frm_nxt += 3;
+			}
+			else
+				break;
+		}
+		return static_cast<int>(frm_nxt - frm);
+	}
+
+	inline codecvt_base::result ucs4_to_utf16be(const uint32_t *frm, const uint32_t *frm_end, const uint32_t *&frm_nxt, uint8_t *to, uint8_t *to_end, uint8_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if (mode & generate_header)
+		{
+			if (to_end - to_nxt < 2)
+				return codecvt_base::partial;
+			*to_nxt++ = 0xFE;
+			*to_nxt++ = 0xFF;
+		}
+		for (; frm_nxt < frm_end; ++frm_nxt)
+		{
+			uint32_t wc = *frm_nxt;
+			if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
+				return codecvt_base::error;
+			if (wc < 0x010000)
+			{
+				if (to_end - to_nxt < 2)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(wc >> 8);
+				*to_nxt++ = static_cast<uint8_t>(wc);
+			}
+			else
+			{
+				if (to_end - to_nxt < 4)
+					return codecvt_base::partial;
+				uint16_t t = static_cast<uint16_t>(0xD800 | ((((wc & 0x1F0000) >> 16) - 1) << 6) | ((wc & 0x00FC00) >> 10));
+				*to_nxt++ = static_cast<uint8_t>(t >> 8);
+				*to_nxt++ = static_cast<uint8_t>(t);
+				t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
+				*to_nxt++ = static_cast<uint8_t>(t >> 8);
+				*to_nxt++ = static_cast<uint8_t>(t);
+			}
+		}
+		return codecvt_base::ok;
+	}
+
+	inline codecvt_base::result utf16be_to_ucs4(const uint8_t *frm, const uint8_t *frm_end, const uint8_t *&frm_nxt, uint32_t *to, uint32_t *to_end, uint32_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
+			frm_nxt += 2;
+		for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
+		{
+			uint16_t c1 = static_cast<uint16_t>((frm_nxt[0] << 8) | frm_nxt[1]);
+			if ((c1 & 0xFC00) == 0xDC00)
+				return codecvt_base::error;
+			if ((c1 & 0xFC00) != 0xD800)
+			{
+				if (c1 > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = static_cast<uint32_t>(c1);
+				frm_nxt += 2;
+			}
+			else
+			{
+				if (frm_end - frm_nxt < 4)
+					return codecvt_base::partial;
+				uint16_t c2 = static_cast<uint16_t>((frm_nxt[2] << 8) | frm_nxt[3]);
+				if ((c2 & 0xFC00) != 0xDC00)
+					return codecvt_base::error;
+				uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = t;
+				frm_nxt += 4;
+			}
+		}
+		return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
+	}
+
+	inline int utf16be_to_ucs4_length(const uint8_t *frm, const uint8_t *frm_end, size_t mx, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		auto frm_nxt = frm;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
+			frm_nxt += 2;
+		for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
+		{
+			uint16_t c1 = static_cast<uint16_t>((frm_nxt[0] << 8) | frm_nxt[1]);
+			if ((c1 & 0xFC00) == 0xDC00)
+				break;
+			if ((c1 & 0xFC00) != 0xD800)
+			{
+				if (c1 > Maxcode)
+					break;
+				frm_nxt += 2;
+			}
+			else
+			{
+				if (frm_end - frm_nxt < 4)
+					break;
+				uint16_t c2 = static_cast<uint16_t>((frm_nxt[2] << 8) | frm_nxt[3]);
+				if ((c2 & 0xFC00) != 0xDC00)
+					break;
+				uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF));
+				if (t > Maxcode)
+					break;
+				frm_nxt += 4;
+			}
+		}
+		return static_cast<int>(frm_nxt - frm);
+	}
+
+	inline codecvt_base::result ucs4_to_utf16le(const uint32_t *frm, const uint32_t *frm_end, const uint32_t *&frm_nxt, uint8_t *to, uint8_t *to_end, uint8_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if (mode & generate_header)
+		{
+			if (to_end - to_nxt < 2)
+				return codecvt_base::partial;
+			*to_nxt++ = 0xFF;
+			*to_nxt++ = 0xFE;
+		}
+		for (; frm_nxt < frm_end; ++frm_nxt)
+		{
+			uint32_t wc = *frm_nxt;
+			if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
+				return codecvt_base::error;
+			if (wc < 0x010000)
+			{
+				if (to_end - to_nxt < 2)
+					return codecvt_base::partial;
+				*to_nxt++ = static_cast<uint8_t>(wc);
+				*to_nxt++ = static_cast<uint8_t>(wc >> 8);
+			}
+			else
+			{
+				if (to_end - to_nxt < 4)
+					return codecvt_base::partial;
+				uint16_t t = static_cast<uint16_t>(0xD800 | ((((wc & 0x1F0000) >> 16) - 1) << 6) | ((wc & 0x00FC00) >> 10));
+				*to_nxt++ = static_cast<uint8_t>(t);
+				*to_nxt++ = static_cast<uint8_t>(t >> 8);
+				t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
+				*to_nxt++ = static_cast<uint8_t>(t);
+				*to_nxt++ = static_cast<uint8_t>(t >> 8);
+			}
+		}
+		return codecvt_base::ok;
+	}
+
+	inline codecvt_base::result utf16le_to_ucs4(const uint8_t *frm, const uint8_t *frm_end, const uint8_t *&frm_nxt, uint32_t *to, uint32_t *to_end, uint32_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
+			frm_nxt += 2;
+		for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
+		{
+			uint16_t c1 = static_cast<uint16_t>((frm_nxt[1] << 8) | frm_nxt[0]);
+			if ((c1 & 0xFC00) == 0xDC00)
+				return codecvt_base::error;
+			if ((c1 & 0xFC00) != 0xD800)
+			{
+				if (c1 > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = static_cast<uint32_t>(c1);
+				frm_nxt += 2;
+			}
+			else
+			{
+				if (frm_end - frm_nxt < 4)
+					return codecvt_base::partial;
+				uint16_t c2 = static_cast<uint16_t>((frm_nxt[3] << 8) | frm_nxt[2]);
+				if ((c2 & 0xFC00) != 0xDC00)
+					return codecvt_base::error;
+				uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF));
+				if (t > Maxcode)
+					return codecvt_base::error;
+				*to_nxt = t;
+				frm_nxt += 4;
+			}
+		}
+		return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
+	}
+
+	inline int utf16le_to_ucs4_length(const uint8_t *frm, const uint8_t *frm_end, size_t mx, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		auto frm_nxt = frm;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
+			frm_nxt += 2;
+		for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
+		{
+			uint16_t c1 = static_cast<uint16_t>((frm_nxt[1] << 8) | frm_nxt[0]);
+			if ((c1 & 0xFC00) == 0xDC00)
+				break;
+			if ((c1 & 0xFC00) != 0xD800)
+			{
+				if (c1 > Maxcode)
+					break;
+				frm_nxt += 2;
+			}
+			else
+			{
+				if (frm_end - frm_nxt < 4)
+					break;
+				uint16_t c2 = static_cast<uint16_t>((frm_nxt[3] << 8) | frm_nxt[2]);
+				if ((c2 & 0xFC00) != 0xDC00)
+					break;
+				uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF));
+				if (t > Maxcode)
+					break;
+				frm_nxt += 4;
+			}
+		}
+		return static_cast<int>(frm_nxt - frm);
+	}
+
+	inline codecvt_base::result ucs2_to_utf16be(const uint16_t *frm, const uint16_t *frm_end, const uint16_t *&frm_nxt, uint8_t *to, uint8_t *to_end, uint8_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if (mode & generate_header)
+		{
+			if (to_end - to_nxt < 2)
+				return codecvt_base::partial;
+			*to_nxt++ = 0xFE;
+			*to_nxt++ = 0xFF;
+		}
+		for (; frm_nxt < frm_end; ++frm_nxt)
+		{
+			uint16_t wc = *frm_nxt;
+			if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
+				return codecvt_base::error;
+			if (to_end - to_nxt < 2)
+				return codecvt_base::partial;
+			*to_nxt++ = static_cast<uint8_t>(wc >> 8);
+			*to_nxt++ = static_cast<uint8_t>(wc);
+		}
+		return codecvt_base::ok;
+	}
+
+	inline codecvt_base::result utf16be_to_ucs2(const uint8_t *frm, const uint8_t *frm_end, const uint8_t *&frm_nxt, uint16_t *to, uint16_t *to_end, uint16_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
+			frm_nxt += 2;
+		for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
+		{
+			uint16_t c1 = static_cast<uint16_t>((frm_nxt[0] << 8) | frm_nxt[1]);
+			if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
+				return codecvt_base::error;
+			*to_nxt = c1;
+			frm_nxt += 2;
+		}
+		return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
+	}
+
+	inline int utf16be_to_ucs2_length(const uint8_t *frm, const uint8_t *frm_end, size_t mx, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		auto frm_nxt = frm;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
+			frm_nxt += 2;
+		for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
+		{
+			uint16_t c1 = static_cast<uint16_t>((frm_nxt[0] << 8) | frm_nxt[1]);
+			if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
+				break;
+			frm_nxt += 2;
+		}
+		return static_cast<int>(frm_nxt - frm);
+	}
+
+	inline codecvt_base::result ucs2_to_utf16le(const uint16_t *frm, const uint16_t *frm_end, const uint16_t *&frm_nxt, uint8_t *to, uint8_t *to_end, uint8_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if (mode & generate_header)
+		{
+			if (to_end - to_nxt < 2)
+				return codecvt_base::partial;
+			*to_nxt++ = 0xFF;
+			*to_nxt++ = 0xFE;
+		}
+		for (; frm_nxt < frm_end; ++frm_nxt)
+		{
+			uint16_t wc = *frm_nxt;
+			if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
+				return codecvt_base::error;
+			if (to_end - to_nxt < 2)
+				return codecvt_base::partial;
+			*to_nxt++ = static_cast<uint8_t>(wc);
+			*to_nxt++ = static_cast<uint8_t>(wc >> 8);
+		}
+		return codecvt_base::ok;
+	}
+
+	inline codecvt_base::result utf16le_to_ucs2(const uint8_t *frm, const uint8_t *frm_end, const uint8_t *&frm_nxt, uint16_t *to, uint16_t *to_end, uint16_t *&to_nxt, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		frm_nxt = frm;
+		to_nxt = to;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
+			frm_nxt += 2;
+		for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
+		{
+			uint16_t c1 = static_cast<uint16_t>((frm_nxt[1] << 8) | frm_nxt[0]);
+			if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
+				return codecvt_base::error;
+			*to_nxt = c1;
+			frm_nxt += 2;
+		}
+		return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
+	}
+
+	inline int utf16le_to_ucs2_length(const uint8_t *frm, const uint8_t *frm_end, size_t mx, unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = static_cast<codecvt_mode>(0))
+	{
+		auto frm_nxt = frm;
+		if ((mode & consume_header) && frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
+			frm_nxt += 2;
+		for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
+		{
+			uint16_t c1 = static_cast<uint16_t>((frm_nxt[1] << 8) | frm_nxt[0]);
+			if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
+				break;
+			frm_nxt += 2;
+		}
+		return static_cast<int>(frm_nxt - frm);
+	}
+}
+
+template<> class codecvt<char16_t, char, mbstate_t> : public locale::facet, public codecvt_base
+{
+public:
+	typedef char16_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit codecvt(size_t __refs = 0) : locale::facet(__refs) { }
+
+	result out(state_type &__st, const intern_type *__frm, const intern_type *__frm_end, const intern_type *&__frm_nxt, extern_type *__to, extern_type *__to_end, extern_type *&__to_nxt) const
+	{
+		return this->do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
+	}
+
+	result unshift(state_type &__st, extern_type *__to, extern_type *__to_end, extern_type *&__to_nxt) const
+	{
+		return this->do_unshift(__st, __to, __to_end, __to_nxt);
+	}
+
+	result in(state_type &__st, const extern_type *__frm, const extern_type *__frm_end, const extern_type *&__frm_nxt, intern_type *__to, intern_type *__to_end, intern_type *&__to_nxt) const
+	{
+		return this->do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
+	}
+
+	int encoding() const throw()
+	{
+		return this->do_encoding();
+	}
+
+	bool always_noconv() const throw()
+	{
+		return this->do_always_noconv();
+	}
+
+	int length(state_type &__st, const extern_type *__frm, const extern_type *__end, size_t __mx) const
+	{
+		return this->do_length(__st, __frm, __end, __mx);
+	}
+
+	int max_length() const throw()
+	{
+		return this->do_max_length();
+	}
+
+	static locale::id id;
+
+protected:
+	explicit codecvt(const char *, size_t __refs = 0) : locale::facet(__refs) { }
+
+	~codecvt() { }
+
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint16_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint16_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint16_t *>(to);
+		auto _to_end = reinterpret_cast<uint16_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf8_to_utf16_length(_frm, _frm_end, mx);
+	}
+	virtual int do_max_length() const throw() { return 4; }
+};
+
+template<> class codecvt<char32_t, char, mbstate_t> : public locale::facet, public codecvt_base
+{
+public:
+	typedef char32_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit codecvt(size_t __refs = 0) : locale::facet(__refs) { }
+
+	result out(state_type &__st, const intern_type *__frm, const intern_type *__frm_end, const intern_type *&__frm_nxt, extern_type *__to, extern_type *__to_end, extern_type *&__to_nxt) const
+	{
+		return this->do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
+	}
+
+	result unshift(state_type &__st, extern_type *__to, extern_type *__to_end, extern_type *&__to_nxt) const
+	{
+		return this->do_unshift(__st, __to, __to_end, __to_nxt);
+	}
+
+	result in(state_type &__st, const extern_type *__frm, const extern_type *__frm_end, const extern_type *&__frm_nxt, intern_type *__to, intern_type *__to_end, intern_type *&__to_nxt) const
+	{
+		return this->do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
+	}
+
+	int encoding() const throw()
+	{
+		return this->do_encoding();
+	}
+
+	bool always_noconv() const throw()
+	{
+		return this->do_always_noconv();
+	}
+
+	int length(state_type &__st, const extern_type *__frm, const extern_type *__end, size_t __mx) const
+	{
+		return this->do_length(__st, __frm, __end, __mx);
+	}
+
+	int max_length() const throw()
+	{
+		return this->do_max_length();
+	}
+
+	static locale::id id;
+
+protected:
+	explicit codecvt(const char *, size_t __refs = 0) : locale::facet(__refs) { }
+
+	~codecvt() { }
+
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint32_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint32_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint32_t *>(to);
+		auto _to_end = reinterpret_cast<uint32_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf8_to_ucs4_length(_frm, _frm_end, mx);
+	}
+	virtual int do_max_length() const throw() { return 4; }
+};
+
+template<class _Elem> class __codecvt_utf8;
+
+template<> class __codecvt_utf8<wchar_t> : public codecvt<wchar_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef wchar_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<wchar_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+#ifdef _WIN32
+		auto _frm = reinterpret_cast<const uint16_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint16_t *>(frm_end);
+#else
+		auto _frm = reinterpret_cast<const uint32_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint32_t *>(frm_end);
+#endif
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::
+#ifdef _WIN32
+			ucs2_to_utf8
+#else
+			ucs4_to_utf8
+#endif
+			(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+#ifdef _WIN32
+		auto _to = reinterpret_cast<uint16_t *>(to);
+		auto _to_end = reinterpret_cast<uint16_t *>(to_end);
+#else
+		auto _to = reinterpret_cast<uint32_t *>(to);
+		auto _to_end = reinterpret_cast<uint32_t *>(to_end);
+#endif
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::
+#ifdef _WIN32
+			utf8_to_ucs2
+#else
+			utf8_to_ucs4
+#endif
+			(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf8_to_ucs4_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 7;
+		return 4;
+	}
+};
+
+template<> class __codecvt_utf8<char16_t> : public codecvt<char16_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef char16_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<char16_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint16_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint16_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint16_t *>(to);
+		auto _to_end = reinterpret_cast<uint16_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf8_to_ucs2_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 6;
+		return 3;
+	}
+};
+
+template<> class __codecvt_utf8<char32_t> : public codecvt<char32_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef char32_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<char32_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint32_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint32_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint32_t *>(to);
+		auto _to_end = reinterpret_cast<uint32_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf8_to_ucs4_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 7;
+		return 4;
+	}
+};
+
+template<class _Elem, unsigned long _Maxcode = 0x10ffff, codecvt_mode _Mode = static_cast<codecvt_mode>(0)> class codecvt_utf8 : public __codecvt_utf8<_Elem>
+{
+public:
+	explicit codecvt_utf8(size_t __refs = 0) : __codecvt_utf8<_Elem>(__refs, _Maxcode, _Mode) { }
+
+	~codecvt_utf8() { }
+};
+
+template<class _Elem, bool _LittleEndian> class __codecvt_utf16;
+
+template<> class __codecvt_utf16<wchar_t, false> : public codecvt<wchar_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef wchar_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<wchar_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint32_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint32_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint32_t *>(to);
+		auto _to_end = reinterpret_cast<uint32_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf16be_to_ucs4_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 6;
+		return 4;
+	}
+};
+
+template<> class __codecvt_utf16<wchar_t, true> : public codecvt<wchar_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef wchar_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<wchar_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint32_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint32_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint32_t *>(to);
+		auto _to_end = reinterpret_cast<uint32_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf16le_to_ucs4_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 6;
+		return 4;
+	}
+};
+
+template<> class __codecvt_utf16<char16_t, false> : public codecvt<char16_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef char16_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<char16_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint16_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint16_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint16_t *>(to);
+		auto _to_end = reinterpret_cast<uint16_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf16be_to_ucs2_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 4;
+		return 2;
+	}
+};
+
+template<> class __codecvt_utf16<char16_t, true> : public codecvt<char16_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef char16_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<char16_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint16_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint16_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint16_t *>(to);
+		auto _to_end = reinterpret_cast<uint16_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf16le_to_ucs2_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 4;
+		return 2;
+	}
+};
+
+template<> class __codecvt_utf16<char32_t, false> : public codecvt<char32_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef char32_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<char32_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint32_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint32_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint32_t *>(to);
+		auto _to_end = reinterpret_cast<uint32_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf16be_to_ucs4_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 6;
+		return 4;
+	}
+};
+
+template<> class __codecvt_utf16<char32_t, true> : public codecvt<char32_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef char32_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<char32_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint32_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint32_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint32_t *>(to);
+		auto _to_end = reinterpret_cast<uint32_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf16le_to_ucs4_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 6;
+		return 4;
+	}
+};
+
+template<class _Elem, unsigned long _Maxcode = 0x10ffff, codecvt_mode _Mode = static_cast<codecvt_mode>(0)> class codecvt_utf16 : public __codecvt_utf16<_Elem, _Mode & little_endian>
+{
+public:
+	explicit codecvt_utf16(size_t __refs = 0) : __codecvt_utf16<_Elem, _Mode & little_endian>(__refs, _Maxcode, _Mode) { }
+
+	~codecvt_utf16() { }
+};
+
+template<class _Elem> class __codecvt_utf8_utf16;
+
+template<> class __codecvt_utf8_utf16<wchar_t> : public codecvt<wchar_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef wchar_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<wchar_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint32_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint32_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint32_t *>(to);
+		auto _to_end = reinterpret_cast<uint32_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf8_to_utf16_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 7;
+		return 4;
+	}
+};
+
+template<> class __codecvt_utf8_utf16<char32_t> : public codecvt<char32_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef char32_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<char32_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint32_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint32_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint32_t *>(to);
+		auto _to_end = reinterpret_cast<uint32_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf8_to_utf16_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 7;
+		return 4;
+	}
+};
+
+template<> class __codecvt_utf8_utf16<char16_t> : public codecvt<char16_t, char, mbstate_t>
+{
+	unsigned long _Maxcode_;
+	codecvt_mode _Mode_;
+public:
+	typedef char16_t intern_type;
+	typedef char extern_type;
+	typedef mbstate_t state_type;
+
+	explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt<char16_t, char, mbstate_t>(__refs), _Maxcode_(_Maxcode), _Mode_(_Mode) { }
+protected:
+	virtual result do_out(state_type &, const intern_type *frm, const intern_type *frm_end, const intern_type *&frm_nxt, extern_type *to, extern_type *to_end, extern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint16_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint16_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint8_t *>(to);
+		auto _to_end = reinterpret_cast<uint8_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_in(state_type &, const extern_type *frm, const extern_type *frm_end, const extern_type *&frm_nxt, intern_type *to, intern_type *to_end, intern_type *&to_nxt) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		auto _frm_nxt = _frm;
+		auto _to = reinterpret_cast<uint16_t *>(to);
+		auto _to_end = reinterpret_cast<uint16_t *>(to_end);
+		auto _to_nxt = _to;
+		auto r = UnicodeConverters::utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, this->_Maxcode_, this->_Mode_);
+		frm_nxt = frm + (_frm_nxt - _frm);
+		to_nxt = to + (_to_nxt - _to);
+		return r;
+	}
+	virtual result do_unshift(state_type &, extern_type *to, extern_type *, extern_type *&to_nxt) const
+	{
+		to_nxt = to;
+		return noconv;
+	}
+	virtual int do_encoding() const throw() { return 0; }
+	virtual bool do_always_noconv() const throw() { return false; }
+	virtual int do_length(state_type &, const extern_type *frm, const extern_type *frm_end, size_t mx) const
+	{
+		auto _frm = reinterpret_cast<const uint8_t *>(frm);
+		auto _frm_end = reinterpret_cast<const uint8_t *>(frm_end);
+		return UnicodeConverters::utf8_to_utf16_length(_frm, _frm_end, mx, this->_Maxcode_, this->_Mode_);
+	}
+	virtual int do_max_length() const throw()
+	{
+		if (this->_Mode_ & consume_header)
+			return 7;
+		return 4;
+	}
+};
+
+template<class _Elem, unsigned long _Maxcode = 0x10ffff, codecvt_mode _Mode = static_cast<codecvt_mode>(0)> class codecvt_utf8_utf16 : public __codecvt_utf8_utf16<_Elem>
+{
+public:
+	explicit codecvt_utf8_utf16(size_t __refs = 0) : __codecvt_utf8_utf16<_Elem>(__refs, _Maxcode, _Mode) { }
+
+	~codecvt_utf8_utf16() {}
+};
+
+};
+#endif
+

--- a/src/in_xsf_framework/convert.h
+++ b/src/in_xsf_framework/convert.h
@@ -1,7 +1,7 @@
 /*
  * Common conversion functions
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-17
+ * Last modification on 2014-09-24
  */
 
 #pragma once
@@ -11,10 +11,15 @@
 #include <sstream>
 #include <typeinfo>
 #include <locale>
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(_LIBCPP_VERSION)
+# include "wstring_convert.h"
+# include "codecvt.h"
+#else
+# include <codecvt>
+#endif
 #include <vector>
 #include <memory>
 #include <cmath>
-#include "BigSString.h"
 
 /*
  * The following exception class and the *stringify and convert* functions are
@@ -130,7 +135,7 @@
 
 	static unsigned long StringToMS(const std::wstring &time)
 	{
-		return ConvertFuncs::StringToMS(String(time).GetAnsi());
+		return ConvertFuncs::StringToMS(ConvertFuncs::WStringToString(time));
 	}
 
 	static std::string MSToString(unsigned long time)
@@ -149,7 +154,19 @@
 
 	static std::wstring MSToWString(unsigned long time)
 	{
-		return String(ConvertFuncs::MSToString(time)).GetWStr();
+		return ConvertFuncs::StringToWString(ConvertFuncs::MSToString(time));
+	}
+
+	static std::wstring StringToWString(const std::string &str)
+	{
+		static std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
+		return conv.from_bytes(str);
+	}
+
+	static std::string WStringToString(const std::wstring &wstr)
+	{
+		static std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
+		return conv.to_bytes(wstr);
 	}
 };
 

--- /dev/null
+++ b/src/in_xsf_framework/fstream_wfopen.h
@@ -1,1 +1,764 @@
-
+// This comes from llvm's libcxx project. I've copied the code from there (with heavy modifications) for use with MinGW to support opening Windows "Unicode" filenames.
+
+#if defined(_WIN32) && !defined(_MSC_VER)
+#pragma once
+
+#include <streambuf>
+#include <locale>
+#include <memory>
+#include <fstream>
+
+class filebuf_wfopen : public std::filebuf
+{
+public:
+	typedef typename traits_type::state_type state_type;
+
+	// 27.9.1.2 Constructors/destructor:
+	filebuf_wfopen() : __extbuf_(nullptr), __extbufnext_(nullptr), __extbufend_(nullptr), __ebs_(0),
+		__intbuf_(nullptr), __ibs_(0), __file_(nullptr), __cv_(nullptr), __st_(), __st_last_(),
+		__om_(static_cast<std::ios_base::openmode>(0)), __cm_(static_cast<std::ios_base::openmode>(0)),
+		__owns_eb_(false), __owns_ib_(false), __always_noconv_(false)
+	{
+		if (std::has_facet<std::codecvt<char, char, state_type>>(this->getloc()))
+		{
+			this->__cv_ = &std::use_facet<std::codecvt<char, char, state_type>>(this->getloc());
+			this->__always_noconv_ = this->__cv_->always_noconv();
+		}
+		this->setbuf(nullptr, 4096);
+	}
+
+	virtual ~filebuf_wfopen()
+	{
+		try
+		{
+			this->close();
+		}
+		catch (...)
+		{
+		}
+		if (this->__owns_eb_)
+			delete[] this->__extbuf_;
+		if (this->__owns_ib_)
+			delete[] this->__intbuf_;
+	}
+
+	// 27.9.1.4 Members:
+	bool is_open() const
+	{
+		return !!this->__file_;
+	}
+	filebuf_wfopen *open(const char *__s, std::ios_base::openmode __mode)
+	{
+		filebuf_wfopen *__rt = nullptr;
+		if (!this->__file_)
+		{
+			__rt = this;
+			const char *__mdstr;
+			switch (__mode & ~std::ios_base::ate)
+			{
+				case std::ios_base::out:
+				case std::ios_base::out | std::ios_base::trunc:
+					__mdstr = "w";
+					break;
+				case std::ios_base::out | std::ios_base::app:
+				case std::ios_base::app:
+					__mdstr = "a";
+					break;
+				case std::ios_base::in:
+					__mdstr = "r";
+					break;
+				case std::ios_base::in | std::ios_base::out:
+					__mdstr = "r+";
+					break;
+				case std::ios_base::in | std::ios_base::out | std::ios_base::trunc:
+					__mdstr = "w+";
+					break;
+				case std::ios_base::in | std::ios_base::out | std::ios_base::app:
+				case std::ios_base::in | std::ios_base::app:
+					__mdstr = "a+";
+					break;
+				case std::ios_base::out | std::ios_base::binary:
+				case std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
+					__mdstr = "wb";
+					break;
+				case std::ios_base::out | std::ios_base::app | std::ios_base::binary:
+				case std::ios_base::app | std::ios_base::binary:
+					__mdstr = "ab";
+					break;
+				case std::ios_base::in | std::ios_base::binary:
+					__mdstr = "rb";
+					break;
+				case std::ios_base::in | std::ios_base::out | std::ios_base::binary:
+					__mdstr = "r+b";
+					break;
+				case std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
+					__mdstr = "w+b";
+					break;
+				case std::ios_base::in | std::ios_base::out | std::ios_base::app | std::ios_base::binary:
+				case std::ios_base::in | std::ios_base::app | std::ios_base::binary:
+					__mdstr = "a+b";
+					break;
+				default:
+					__rt = nullptr;
+			}
+			if (__rt)
+			{
+				this->__file_ = fopen(__s, __mdstr);
+				if (this->__file_)
+				{
+					this->__om_ = __mode;
+					if ((__mode & std::ios_base::ate) && fseek(this->__file_, 0, SEEK_END))
+					{
+						fclose(this->__file_);
+						this->__file_ = nullptr;
+						__rt = nullptr;
+					}
+				}
+				else
+					__rt = nullptr;
+			}
+		}
+		return __rt;
+	}
+	filebuf_wfopen *open(const std::string &__s, std::ios_base::openmode __mode)
+	{
+		return this->open(__s.c_str(), __mode);
+	}
+	filebuf_wfopen *open(const wchar_t *__s, std::ios_base::openmode __mode)
+	{
+		filebuf_wfopen *__rt = nullptr;
+		if (!this->__file_)
+		{
+			__rt = this;
+			const wchar_t *__mdstr;
+			switch (__mode & ~std::ios_base::ate)
+			{
+				case std::ios_base::out:
+				case std::ios_base::out | std::ios_base::trunc:
+					__mdstr = L"w";
+					break;
+				case std::ios_base::out | std::ios_base::app:
+				case std::ios_base::app:
+					__mdstr = L"a";
+					break;
+				case std::ios_base::in:
+					__mdstr = L"r";
+					break;
+				case std::ios_base::in | std::ios_base::out:
+					__mdstr = L"r+";
+					break;
+				case std::ios_base::in | std::ios_base::out | std::ios_base::trunc:
+					__mdstr = L"w+";
+					break;
+				case std::ios_base::in | std::ios_base::out | std::ios_base::app:
+				case std::ios_base::in | std::ios_base::app:
+					__mdstr = L"a+";
+					break;
+				case std::ios_base::out | std::ios_base::binary:
+				case std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
+					__mdstr = L"wb";
+					break;
+				case std::ios_base::out | std::ios_base::app | std::ios_base::binary:
+				case std::ios_base::app | std::ios_base::binary:
+					__mdstr = L"ab";
+					break;
+				case std::ios_base::in | std::ios_base::binary:
+					__mdstr = L"rb";
+					break;
+				case std::ios_base::in | std::ios_base::out | std::ios_base::binary:
+					__mdstr = L"r+b";
+					break;
+				case std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
+					__mdstr = L"w+b";
+					break;
+				case std::ios_base::in | std::ios_base::out | std::ios_base::app | std::ios_base::binary:
+				case std::ios_base::in | std::ios_base::app | std::ios_base::binary:
+					__mdstr = L"a+b";
+					break;
+				default:
+					__rt = nullptr;
+			}
+			if (__rt)
+			{
+				this->__file_ = _wfopen(__s, __mdstr);
+				if (this->__file_)
+				{
+					this->__om_ = __mode;
+					if ((__mode & std::ios_base::ate) && fseek(this->__file_, 0, SEEK_END))
+					{
+						fclose(this->__file_);
+						this->__file_ = nullptr;
+						__rt = nullptr;
+					}
+				}
+				else
+					__rt = nullptr;
+			}
+		}
+		return __rt;
+	}
+	filebuf_wfopen *open(const std::wstring &__s, std::ios_base::openmode __mode)
+	{
+		return this->open(__s.c_str(), __mode);
+	}
+	filebuf_wfopen *close()
+	{
+		filebuf_wfopen *__rt = nullptr;
+		if (this->__file_)
+		{
+			__rt = this;
+			std::unique_ptr<FILE, int (*)(FILE *)> __h(this->__file_, fclose);
+			if (this->sync())
+				__rt = nullptr;
+			if (!fclose(__h.release()))
+				this->__file_ = nullptr;
+			else
+				__rt = nullptr;
+		}
+		return __rt;
+	}
+
+protected:
+	// 27.9.1.5 Overridden virtual functions:
+	virtual int_type underflow()
+	{
+		if (!this->__file_)
+			return traits_type::eof();
+		bool __initial = this->__read_mode();
+		char __1buf;
+		if (!this->gptr())
+			this->setg(&__1buf, &__1buf + 1, &__1buf + 1);
+		const size_t __unget_sz = __initial ? 0 : std::min<size_t>((this->egptr() - this->eback()) / 2, 4);
+		int_type __c = traits_type::eof();
+		if (this->gptr() == this->egptr())
+		{
+			memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz);
+			if (this->__always_noconv_)
+			{
+				size_t __nmemb = static_cast<size_t>(this->egptr() - this->eback() - __unget_sz);
+				__nmemb = fread(this->eback() + __unget_sz, 1, __nmemb, this->__file_);
+				if (__nmemb)
+				{
+					this->setg(this->eback(), this->eback() + __unget_sz, this->eback() + __unget_sz + __nmemb);
+					__c = traits_type::to_int_type(*this->gptr());
+				}
+			}
+			else
+			{
+				memmove(this->__extbuf_, this->__extbufnext_, this->__extbufend_ - this->__extbufnext_);
+				this->__extbufnext_ = this->__extbuf_ + (this->__extbufend_ - this->__extbufnext_);
+				this->__extbufend_ = this->__extbuf_ +
+					(this->__extbuf_ == this->__extbuf_min_ ? sizeof(this->__extbuf_min_) : this->__ebs_);
+				size_t __nmemb = std::min<size_t>(this->__ibs_ - __unget_sz,
+					this->__extbufend_ - this->__extbufnext_);
+				std::codecvt_base::result __r;
+				this->__st_last_ = this->__st_;
+				size_t __nr = fread(const_cast<char *>(this->__extbufnext_), 1, __nmemb, this->__file_);
+				if (__nr)
+				{
+					if (!this->__cv_)
+						throw std::bad_cast();
+					this->__extbufend_ = this->__extbufnext_ + __nr;
+					char *__inext;
+					__r = this->__cv_->in(this->__st_, this->__extbuf_, this->__extbufend_, this->__extbufnext_,
+						this->eback() + __unget_sz, this->eback() + this->__ibs_, __inext);
+					if (__r == std::codecvt_base::noconv)
+					{
+						this->setg(this->__extbuf_, this->__extbuf_, const_cast<char *>(this->__extbufend_));
+						__c = traits_type::to_int_type(*this->gptr());
+					}
+					else if (__inext != this->eback() + __unget_sz)
+					{
+						this->setg(this->eback(), this->eback() + __unget_sz, __inext);
+						__c = traits_type::to_int_type(*this->gptr());
+					}
+				}
+			}
+		}
+		else
+			__c = traits_type::to_int_type(*this->gptr());
+		if (this->eback() == &__1buf)
+			this->setg(nullptr, nullptr, nullptr);
+		return __c;
+	}
+	virtual int_type pbackfail(int_type __c = traits_type::eof())
+	{
+		if (this->__file_ && this->eback() < this->gptr())
+		{
+			if (traits_type::eq_int_type(__c, traits_type::eof()))
+			{
+				this->gbump(-1);
+				return traits_type::not_eof(__c);
+			}
+			if ((this->__om_ & std::ios_base::out) ||
+				traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
+			{
+				this->gbump(-1);
+				*this->gptr() = traits_type::to_char_type(__c);
+				return __c;
+			}
+		}
+		return traits_type::eof();
+	}
+	virtual int_type overflow (int_type __c = traits_type::eof())
+	{
+		if (!this->__file_)
+			return traits_type::eof();
+		this->__write_mode();
+		char __1buf;
+		char *__pb_save = this->pbase();
+		char *__epb_save = this->epptr();
+		if (!traits_type::eq_int_type(__c, traits_type::eof()))
+		{
+			if (!this->pptr())
+				this->setp(&__1buf, &__1buf + 1);
+			*this->pptr() = traits_type::to_char_type(__c);
+			this->pbump(1);
+		}
+		if (this->pptr() != this->pbase())
+		{
+			if (this->__always_noconv_)
+			{
+				size_t __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
+				if (fwrite(this->pbase(), 1, __nmemb, __file_) != __nmemb)
+					return traits_type::eof();
+			}
+			else
+			{
+				char *__extbe = this->__extbuf_;
+				std::codecvt_base::result __r;
+				do
+				{
+					if (!this->__cv_)
+						throw std::bad_cast();
+					const char *__e;
+					__r = this->__cv_->out(this->__st_, this->pbase(), this->pptr(), __e, this->__extbuf_,
+						this->__extbuf_ + this->__ebs_, __extbe);
+					if (__e == this->pbase())
+						return traits_type::eof();
+					if (__r == std::codecvt_base::noconv)
+					{
+						size_t __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
+						if (fwrite(this->pbase(), 1, __nmemb, this->__file_) != __nmemb)
+							return traits_type::eof();
+					}
+					else if (__r == std::codecvt_base::ok || __r == std::codecvt_base::partial)
+					{
+						size_t __nmemb = static_cast<size_t>(__extbe - this->__extbuf_);
+						if (fwrite(this->__extbuf_, 1, __nmemb, this->__file_) != __nmemb)
+							return traits_type::eof();
+						if (__r == std::codecvt_base::partial)
+						{
+							this->setp(const_cast<char *>(__e), this->pptr());
+							this->pbump(this->epptr() - this->pbase());
+						}
+					}
+					else
+						return traits_type::eof();
+				} while (__r == std::codecvt_base::partial);
+			}
+			this->setp(__pb_save, __epb_save);
+		}
+		return traits_type::not_eof(__c);
+	}
+	virtual std::streambuf *setbuf(char *__s, std::streamsize __n)
+	{
+		this->setg(nullptr, nullptr, nullptr);
+		this->setp(nullptr, nullptr);
+		if (this->__owns_eb_)
+			delete[] this->__extbuf_;
+		if (this->__owns_ib_)
+			delete[] this->__intbuf_;
+		this->__ebs_ = __n;
+		if (this->__ebs_ > sizeof(this->__extbuf_min_))
+		{
+			if (this->__always_noconv_ && __s)
+			{
+				this->__extbuf_ = __s;
+				this->__owns_eb_ = false;
+			}
+			else
+			{
+				this->__extbuf_ = new char[this->__ebs_];
+				this->__owns_eb_ = true;
+			}
+		}
+		else
+		{
+			this->__extbuf_ = this->__extbuf_min_;
+			this->__ebs_ = sizeof(this->__extbuf_min_);
+			this->__owns_eb_ = false;
+		}
+		if (!this->__always_noconv_)
+		{
+			this->__ibs_ = std::max<std::streamsize>(__n, sizeof(this->__extbuf_min_));
+			if (__s && this->__ibs_ >= sizeof(this->__extbuf_min_))
+			{
+				this->__intbuf_ = __s;
+				this->__owns_ib_ = false;
+			}
+			else
+			{
+				this->__intbuf_ = new char[this->__ibs_];
+				this->__owns_ib_ = true;
+			}
+		}
+		else
+		{
+			this->__ibs_ = 0;
+			this->__intbuf_ = nullptr;
+			this->__owns_ib_ = false;
+		}
+		return this;
+	}
+	virtual pos_type seekoff(off_type __off, std::ios_base::seekdir __way,
+		std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
+	{
+		if (!this->__cv_)
+			throw std::bad_cast();
+		int __width = this->__cv_->encoding();
+		if (!this->__file_ || (__width <= 0 && __off) || this->sync())
+			return pos_type(off_type(-1));
+		// __width > 0 || __off == 0
+		int __whence;
+		switch (__way)
+		{
+			case std::ios_base::beg:
+				__whence = SEEK_SET;
+				break;
+			case std::ios_base::cur:
+				__whence = SEEK_CUR;
+				break;
+			case std::ios_base::end:
+				__whence = SEEK_END;
+				break;
+			default:
+				return pos_type(off_type(-1));
+		}
+		if (fseek(this->__file_, __width > 0 ? __width * __off : 0, __whence))
+			return pos_type(off_type(-1));
+		pos_type __r = ftell(this->__file_);
+		__r.state(this->__st_);
+		return __r;
+	}
+	virtual pos_type seekpos(pos_type __sp,
+		std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
+	{
+		if (!this->__file_ || this->sync())
+			return pos_type(off_type(-1));
+		if (fseek(this->__file_, __sp, SEEK_SET))
+			return pos_type(off_type(-1));
+		this->__st_ = __sp.state();
+		return __sp;
+	}
+	virtual int sync()
+	{
+		if (!this->__file_)
+			return 0;
+		if (!this->__cv_)
+			throw std::bad_cast();
+		if (this->__cm_ & std::ios_base::out)
+		{
+			if (this->pptr() != this->pbase() && this->overflow() == traits_type::eof())
+				return -1;
+			std::codecvt_base::result __r;
+			do
+			{
+				char *__extbe;
+				__r = this->__cv_->unshift(this->__st_, this->__extbuf_, this->__extbuf_ + this->__ebs_,
+					__extbe);
+				size_t __nmemb = static_cast<size_t>(__extbe - this->__extbuf_);
+				if (fwrite(this->__extbuf_, 1, __nmemb, this->__file_) != __nmemb)
+					return -1;
+			} while (__r == std::codecvt_base::partial);
+			if (__r == std::codecvt_base::error)
+				return -1;
+			if (fflush(this->__file_))
+				return -1;
+		}
+		else if (this->__cm_ & std::ios_base::in)
+		{
+			off_type __c;
+			state_type __state = this->__st_last_;
+			bool __update_st = false;
+			if (this->__always_noconv_)
+				__c = this->egptr() - this->gptr();
+			else
+			{
+				int __width = this->__cv_->encoding();
+				__c = this->__extbufend_ - this->__extbufnext_;
+				if (__width > 0)
+					__c += __width * (this->egptr() - this->gptr());
+				else if (this->gptr() != this->egptr())
+				{
+					int __off =  this->__cv_->length(__state, this->__extbuf_, this->__extbufnext_,
+						this->gptr() - this->eback());
+					__c += this->__extbufnext_ - this->__extbuf_ - __off;
+					__update_st = true;
+				}
+			}
+			if (fseek(this->__file_, -__c, SEEK_CUR))
+				return -1;
+			if (__update_st)
+				this->__st_ = __state;
+			this->__extbufnext_ = this->__extbufend_ = this->__extbuf_;
+			this->setg(nullptr, nullptr, nullptr);
+			this->__cm_ = static_cast<std::ios_base::openmode>(0);
+		}
+		return 0;
+	}
+	virtual void imbue(const std::locale &__loc)
+	{
+		this->sync();
+		this->__cv_ = &std::use_facet<std::codecvt<char, char, state_type>>(__loc);
+		bool __old_anc = this->__always_noconv_;
+		this->__always_noconv_ = this->__cv_->always_noconv();
+		if (__old_anc != this->__always_noconv_)
+		{
+			this->setg(nullptr, nullptr, nullptr);
+			this->setp(nullptr, nullptr);
+			// invariant, char_type is char, else we couldn't get here
+			if (this->__always_noconv_) // need to dump __intbuf_
+			{
+				if (this->__owns_eb_)
+					delete[] this->__extbuf_;
+				this->__owns_eb_ = this->__owns_ib_;
+				this->__ebs_ = this->__ibs_;
+				this->__extbuf_ = this->__intbuf_;
+				this->__ibs_ = 0;
+				this->__intbuf_ = nullptr;
+				this->__owns_ib_ = false;
+			}
+			// need to obtain an __intbuf_.
+			else if (!this->__owns_eb_ && this->__extbuf_ != this->__extbuf_min_)
+				// If __extbuf_ is user-supplied, use it, else new __intbuf_
+			{
+				this->__ibs_ = this->__ebs_;
+				this->__intbuf_ = this->__extbuf_;
+				this->__owns_ib_ = false;
+				this->__extbuf_ = new char[this->__ebs_];
+				this->__owns_eb_ = true;
+			}
+			else
+			{
+				this->__ibs_ = this->__ebs_;
+				this->__intbuf_ = new char[this->__ibs_];
+				this->__owns_ib_ = true;
+			}
+		}
+	}
+
+private:
+	char *__extbuf_;
+	const char *__extbufnext_;
+	const char *__extbufend_;
+	char __extbuf_min_[8];
+	size_t __ebs_;
+	char *__intbuf_;
+	size_t __ibs_;
+	FILE *__file_;
+	const std::codecvt<char, char, state_type> *__cv_;
+	state_type __st_;
+	state_type __st_last_;
+	std::ios_base::openmode __om_;
+	std::ios_base::openmode __cm_;
+	bool __owns_eb_;
+	bool __owns_ib_;
+	bool __always_noconv_;
+
+	bool __read_mode()
+	{
+		if (!(this->__cm_ & std::ios_base::in))
+		{
+			this->setp(nullptr, nullptr);
+			if (this->__always_noconv_)
+				this->setg(this->__extbuf_, this->__extbuf_ + this->__ebs_, this->__extbuf_ + this->__ebs_);
+			else
+				this->setg(this->__intbuf_, this->__intbuf_ + this->__ibs_, this->__intbuf_ + this->__ibs_);
+			this->__cm_ = std::ios_base::in;
+			return true;
+		}
+		return false;
+	}
+	void __write_mode()
+	{
+		if (!(this->__cm_ & std::ios_base::out))
+		{
+			this->setg(nullptr, nullptr, nullptr);
+			if (this->__ebs_ > sizeof(this->__extbuf_min_))
+			{
+				if (this->__always_noconv_)
+					this->setp(this->__extbuf_, this->__extbuf_ + (this->__ebs_ - 1));
+				else
+					this->setp(this->__intbuf_, this->__intbuf_ + (this->__ibs_ - 1));
+			}
+			else
+				this->setp(nullptr, nullptr);
+			this->__cm_ = std::ios_base::out;
+		}
+	}
+};
+
+// basic_ifstream
+
+class ifstream_wfopen : public std::ifstream
+{
+public:
+	ifstream_wfopen() { std::ios::rdbuf(&this->__sb_); }
+	explicit ifstream_wfopen(const char *__s, std::ios_base::openmode __mode = std::ios_base::in)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::in))
+			std::ios::rdbuf(&this->__sb_);
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	explicit ifstream_wfopen(const std::string &__s, std::ios_base::openmode __mode = std::ios_base::in)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::in))
+			std::ios::rdbuf(&this->__sb_);
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	explicit ifstream_wfopen(const wchar_t *__s, std::ios_base::openmode __mode = std::ios_base::in)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::in))
+			std::ios::rdbuf(&this->__sb_);
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	explicit ifstream_wfopen(const std::wstring &__s, std::ios_base::openmode __mode = std::ios_base::in)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::in))
+			std::ios::rdbuf(&this->__sb_);
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+
+	std::filebuf *rdbuf() const
+	{
+		return const_cast<std::filebuf *>(static_cast<const std::filebuf *>(&this->__sb_));
+	}
+	bool is_open() const
+	{
+		return this->__sb_.is_open();
+	}
+	void open(const char *__s, std::ios_base::openmode __mode = std::ios_base::in)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::in))
+			this->clear();
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	void open(const std::string &__s, std::ios_base::openmode __mode = std::ios_base::in)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::in))
+			this->clear();
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	void open(const wchar_t *__s, std::ios_base::openmode __mode = std::ios_base::in)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::in))
+			this->clear();
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	void open(const std::wstring &__s, std::ios_base::openmode __mode = std::ios_base::in)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::in))
+			this->clear();
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	void close()
+	{
+		if (!this->__sb_.close())
+			this->setstate(std::ios_base::failbit);
+	}
+
+private:
+	filebuf_wfopen __sb_;
+};
+
+// basic_ofstream
+
+class ofstream_wfopen : public std::ofstream
+{
+public:
+	ofstream_wfopen() { std::ios::rdbuf(&this->__sb_); }
+	explicit ofstream_wfopen(const char *__s, std::ios_base::openmode __mode = std::ios_base::out)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::out))
+			std::ios::rdbuf(&this->__sb_);
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	explicit ofstream_wfopen(const std::string &__s, std::ios_base::openmode __mode = std::ios_base::out)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::out))
+			std::ios::rdbuf(&this->__sb_);
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	explicit ofstream_wfopen(const wchar_t *__s, std::ios_base::openmode __mode = std::ios_base::out)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::out))
+			std::ios::rdbuf(&this->__sb_);
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	explicit ofstream_wfopen(const std::wstring &__s, std::ios_base::openmode __mode = std::ios_base::out)
+	{
+		if (!this->__sb_.open(__s, __mode | std::ios_base::out))
+			std::ios::rdbuf(&this->__sb_);
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+
+	std::filebuf *rdbuf() const
+	{
+		return const_cast<std::filebuf *>(static_cast<const std::filebuf *>(&this->__sb_));
+	}
+	bool is_open() const
+	{
+		return this->__sb_.is_open();
+	}
+	void open(const char *__s, std::ios_base::openmode __mode = std::ios_base::out)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::out))
+			this->clear();
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	void open(const std::string &__s, std::ios_base::openmode __mode = std::ios_base::out)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::out))
+			this->clear();
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	void open(const wchar_t *__s, std::ios_base::openmode __mode = std::ios_base::out)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::out))
+			this->clear();
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	void open(const std::wstring &__s, std::ios_base::openmode __mode = std::ios_base::out)
+	{
+		if (this->__sb_.open(__s, __mode | std::ios_base::out))
+			this->clear();
+		else
+			this->setstate(std::ios_base::failbit);
+	}
+	void close()
+	{
+		if (!this->__sb_.close())
+			this->setstate(std::ios_base::failbit);
+	}
+
+private:
+	filebuf_wfopen __sb_;
+};
+#endif
+

--- a/src/in_xsf_framework/in_xsf.cpp
+++ b/src/in_xsf_framework/in_xsf.cpp
@@ -1,16 +1,22 @@
 /*
  * xSF - Winamp plugin
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
- * Last modification on 2014-09-18
+ * Last modification on 2014-09-24
  *
  * Partially based on the vio*sf framework
  */
 
 #include "XSFPlayer.h"
 #include "XSFConfig.h"
+#include "XSFCommon.h"
 #include "windowsh_wrapper.h"
 #include <winamp/in2.h>
 #include <winamp/wa_ipc.h>
+
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(_LIBCPP_VERSION)
+std::locale::id std::codecvt<char16_t, char, mbstate_t>::id;
+std::locale::id std::codecvt<char32_t, char, mbstate_t>::id;
+#endif
 
 extern In_Module inMod;
 const XSFFile *xSFFile = nullptr;
@@ -110,7 +116,7 @@
 		catch (const std::exception &)
 		{
 			if (title)
-				String("").CopyToString(title);
+				CopyToString("", title);
 			if (length_in_ms)
 				*length_in_ms = -1000;
 			return;
@@ -118,10 +124,7 @@
 		toFree = true;
 	}
 	if (title)
-	{
-		String formattedTitle = xSF->GetFormattedTitle(xSFConfig->GetTitleFormat()).Substring(0, GETFILEINFO_TITLE_LENGTH - 1);
-		formattedTitle.CopyToString(title);
-	}
+		CopyToString(xSF->GetFormattedTitle(xSFConfig->GetTitleFormat()).substr(0, GETFILEINFO_TITLE_LENGTH - 1), title);
 	if (length_in_ms)
 		*length_in_ms = xSF->GetLengthMS(xSFConfig->GetDefaultLength()) + xSF->GetFadeMS(xSFConfig->GetDefaultFade());
 	if (toFree)
@@ -148,17 +151,16 @@
 	// TODO: Eventually make a dialog box for editing the info
 	/*xSFFileInInfo = xSF.get();
 	xSFConfig->CallInfoDialog(inMod.hDllInstance, hwndParent);*/
-	bool utf8 = xSF->GetTagExists("utf8");
 	auto tags = xSF->GetAllTags();
 	auto keys = tags.GetKeys();
-	String info;
+	std::wstring info;
 	for (unsigned x = 0, numTags = keys.size(); x < numTags; ++x)
 	{
 		if (x)
-			info += "\n";
-		info += String(keys[x] + "=") + String(tags[keys[x]], utf8);
-	}
-	MessageBoxW(hwndParent, info.GetWStrC(), xSF->GetFilenameWithoutPath().GetWStrC(), MB_OK);
+			info += L"\n";
+		info += ConvertFuncs::StringToWString(keys[x] + "=" + tags[keys[x]]);
+	}
+	MessageBoxW(hwndParent, info.c_str(), ConvertFuncs::StringToWString(xSF->GetFilenameWithoutPath()).c_str(), MB_OK);
 	return INFOBOX_EDITED;
 }
 
@@ -271,7 +273,7 @@
 In_Module inMod =
 {
 	IN_VER,
-	const_cast<char *>(XSFConfig::CommonNameWithVersion().GetStrC()), /* Unsafe but Winamp's SDK requires this */
+	const_cast<char *>(XSFConfig::CommonNameWithVersion().c_str()), /* Unsafe but Winamp's SDK requires this */
 	nullptr, /* Filled by Winamp */
 	nullptr, /* Filled by Winamp */
 	const_cast<char *>(XSFPlayer::WinampExts), /* Unsafe but Winamp's SDK requires this */
@@ -317,9 +319,7 @@
 		return 1;
 	}
 	else if (eqstr(data, "family"))
-	{
-		return 0;
-	}
+		return 0;
 	else
 	{
 		try
@@ -327,6 +327,7 @@
 			std::string tagToGet = data;
 			if (eqstr(data, "album"))
 				tagToGet = "game";
+			std::string tag = "";
 			if (!file.GetTagExists(tagToGet))
 			{
 				if (eqstr(tagToGet, "replaygain_track_gain"))
@@ -334,11 +335,10 @@
 				return 0;
 			}
 			else if (eqstr(tagToGet, "length"))
-			{
-				String(stringify(file.GetLengthMS(xSFConfig->GetDefaultLength()) + file.GetFadeMS(xSFConfig->GetDefaultFade()))).Substring(0, destlen - 1).CopyToString(dest, true);
-				return 1;
-			}
-			file.GetTagValue(tagToGet).Substring(0, destlen - 1).CopyToString(dest, true);
+				tag = stringify(file.GetLengthMS(xSFConfig->GetDefaultLength()) + file.GetFadeMS(xSFConfig->GetDefaultFade()));
+			else
+				tag = file.GetTagValue(tagToGet);
+			CopyToString(tag.substr(0, destlen - 1), dest);
 			return 1;
 		}
 		catch (const std::exception &)
@@ -361,7 +361,6 @@
 	}
 }
 
-#ifdef _MSC_VER
 extern "C" __declspec(dllexport) int winampGetExtendedFileInfoW(const wchar_t *fn, const char *data, wchar_t *dest, size_t destlen)
 {
 	try
@@ -374,7 +373,6 @@
 		return 0;
 	}
 }
-#endif
 
 std::unique_ptr<XSFFile> extendedXSFFile;
 
@@ -388,7 +386,7 @@
 {
 	try
 	{
-		if (!extendedXSFFile || extendedXSFFile->GetFilename().GetStr() != fn)
+		if (!extendedXSFFile || extendedXSFFile->GetFilename() != fn)
 			extendedXSFFile.reset(new XSFFile(fn));
 		return wrapperWinampSetExtendedFileInfo(data, val);
 	}
@@ -398,12 +396,11 @@
 	}
 }
 
-#ifdef _MSC_VER
 extern "C" __declspec(dllexport) int winampSetExtendedFileInfoW(const wchar_t *fn, const char *data, const wchar_t *val)
 {
 	try
 	{
-		if (!extendedXSFFile || extendedXSFFile->GetFilename().GetWStr() != fn)
+		if (!extendedXSFFile || ConvertFuncs::StringToWString(extendedXSFFile->GetFilename()) != fn)
 			extendedXSFFile.reset(new XSFFile(fn));
 		return wrapperWinampSetExtendedFileInfo(data, val);
 	}
@@ -412,7 +409,6 @@
 		return 0;
 	}
 }
-#endif
 
 extern "C" __declspec(dllexport) int winampWriteExtendedFileInfo()
 {
@@ -422,12 +418,10 @@
 	return 1;
 }
 
-#ifdef _MSC_VER
 extern "C" __declspec(dllexport) int winampClearExtendedFileInfoW(const wchar_t *)
 {
 	return 0;
 }
-#endif
 
 intptr_t wrapperWinampGetExtendedRead_open(std::unique_ptr<XSFPlayer> tmpxSFPlayer, int *size, int *bps, int *nch, int *srate)
 {
@@ -460,7 +454,6 @@
 	}
 }
 
-#ifdef _MSC_VER
 extern "C" __declspec(dllexport) intptr_t winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
 {
 	try
@@ -473,7 +466,6 @@
 		return 0;
 	}
 }
-#endif
 
 int extendedSeekNeeded = -1;
 

--- a/src/in_xsf_framework/in_xsf_framework.vcxproj
+++ b/src/in_xsf_framework/in_xsf_framework.vcxproj
@@ -71,15 +71,11 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClInclude Include="BigSString.h" />
     <ClInclude Include="convert.h" />
-    <ClInclude Include="ConvertUTF.h" />
     <ClInclude Include="DialogBuilder.h" />
     <ClInclude Include="eqstr.h" />
     <ClInclude Include="ltstr.h" />
     <ClInclude Include="TagList.h" />
-    <ClInclude Include="UtfConverter.h" />
-    <ClInclude Include="UTFEncodeDecode.h" />
     <ClInclude Include="windowsh_wrapper.h" />
     <ClInclude Include="XSFCommon.h" />
     <ClInclude Include="XSFConfig.h" />
@@ -87,12 +83,9 @@
     <ClInclude Include="XSFPlayer.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="ConvertUTF.cpp" />
     <ClCompile Include="DialogBuilder.cpp" />
     <ClCompile Include="in_xsf.cpp" />
     <ClCompile Include="TagList.cpp" />
-    <ClCompile Include="UtfConverter.cpp" />
-    <ClCompile Include="UTFEncodeDecode.cpp" />
     <ClCompile Include="XSFConfig.cpp" />
     <ClCompile Include="XSFConfig_Winamp.cpp" />
     <ClCompile Include="XSFFile.cpp" />

--- a/src/in_xsf_framework/in_xsf_framework.vcxproj.filters
+++ b/src/in_xsf_framework/in_xsf_framework.vcxproj.filters
@@ -15,25 +15,13 @@
     </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="BigSString.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="convert.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="ConvertUTF.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="DialogBuilder.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="eqstr.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="UtfConverter.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="UTFEncodeDecode.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="windowsh_wrapper.h">
@@ -59,19 +47,10 @@
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="ConvertUTF.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="DialogBuilder.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="in_xsf.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="UtfConverter.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="UTFEncodeDecode.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="XSFConfig.cpp">

--- /dev/null
+++ b/src/in_xsf_framework/wstring_convert.h
@@ -1,1 +1,184 @@
+// This comes from llvm's libcxx project. I've copied the code from there (with very minor modifications) for use with GCC and Clang when libcxx isn't being used.
 
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(_LIBCPP_VERSION)
+#pragma once
+
+#include <memory>
+#include <string>
+#include <locale>
+
+namespace std
+{
+
+template<class _Codecvt, class _Elem = wchar_t, class _Wide_alloc = allocator<_Elem>, class _Byte_alloc = allocator<char>> class wstring_convert
+{
+public:
+	typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
+	typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
+	typedef typename _Codecvt::state_type state_type;
+	typedef typename wide_string::traits_type::int_type int_type;
+
+private:
+	byte_string __byte_err_string_;
+	wide_string __wide_err_string_;
+	_Codecvt *__cvtptr_;
+	state_type __cvtstate_;
+	size_t __cvtcount_;
+
+	wstring_convert(const wstring_convert &__wc);
+	wstring_convert& operator=(const wstring_convert &__wc);
+public:
+	wstring_convert(_Codecvt *__pcvt = new _Codecvt) : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0) { }
+	wstring_convert(_Codecvt *__pcvt, state_type __state) : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0) { }
+	wstring_convert(const byte_string &__byte_err, const wide_string &__wide_err = wide_string()) : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err), __cvtptr_(new _Codecvt), __cvtstate_(), __cvtcount_(0) { }
+	wstring_convert(wstring_convert &&__wc) : __byte_err_string_(move(__wc.__byte_err_string_)), __wide_err_string_(move(__wc.__wide_err_string_)), __cvtptr_(__wc.__cvtptr_), __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
+	{
+		__wc.__cvtptr_ = nullptr;
+	}
+	~wstring_convert() { delete this->__cvtptr_; }
+
+	wide_string from_bytes(char __byte) { return from_bytes(&__byte, &__byte + 1); }
+	wide_string from_bytes(const char *__ptr) { return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr)); }
+	wide_string from_bytes(const byte_string &__str) { return from_bytes(__str.data(), __str.data() + __str.size()); }
+	wide_string from_bytes(const char *__frm, const char *__frm_end)
+	{
+		this->__cvtcount_ = 0;
+		if (this->__cvtptr_)
+		{
+			wide_string __ws(2 * (__frm_end - __frm), _Elem());
+			if (__frm != __frm_end)
+				__ws.resize(__ws.capacity());
+			auto __r = codecvt_base::ok;
+			auto __st = this->__cvtstate_;
+			if (__frm != __frm_end)
+			{
+				auto __to = &__ws[0];
+				auto __to_end = __to + __ws.size();
+				const char *__frm_nxt;
+				do
+				{
+					_Elem *__to_nxt;
+					__r = this->__cvtptr_->in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
+					this->__cvtcount_ += __frm_nxt - __frm;
+					if (__frm_nxt == __frm)
+						__r = codecvt_base::error;
+					else if (__r == codecvt_base::noconv)
+					{
+						__ws.resize(__to - &__ws[0]);
+						// This only gets executed if _Elem is char
+						__ws.append(reinterpret_cast<const _Elem *>(__frm), reinterpret_cast<const _Elem *>(__frm_end));
+						__frm = __frm_nxt;
+						__r = codecvt_base::ok;
+					}
+					else if (__r == codecvt_base::ok)
+					{
+						__ws.resize(__to_nxt - &__ws[0]);
+						__frm = __frm_nxt;
+					}
+					else if (__r == codecvt_base::partial)
+					{
+						ptrdiff_t __s = __to_nxt - &__ws[0];
+						__ws.resize(2 * __s);
+						__to = &__ws[0] + __s;
+						__to_end = &__ws[0] + __ws.size();
+						__frm = __frm_nxt;
+					}
+				} while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
+			}
+			if (__r == codecvt_base::ok)
+				return __ws;
+		}
+		if (this->__wide_err_string_.empty())
+			throw range_error("wstring_convert: from_bytes error");
+		return this->__wide_err_string_;
+	}
+
+	byte_string to_bytes(_Elem __wchar) { return to_bytes(&__wchar, &__wchar + 1); }
+	byte_string to_bytes(const _Elem *__wptr) { return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr)); }
+	byte_string to_bytes(const wide_string &__wstr) { return to_bytes(__wstr.data(), __wstr.data() + __wstr.size()); }
+	byte_string to_bytes(const _Elem *__frm, const _Elem *__frm_end)
+	{
+		this->__cvtcount_ = 0;
+		if (this->__cvtptr_)
+		{
+			byte_string __bs(2 * (__frm_end - __frm), char());
+			if (__frm != __frm_end)
+				__bs.resize(__bs.capacity());
+			auto __r = codecvt_base::ok;
+			auto __st = this->__cvtstate_;
+			if (__frm != __frm_end)
+			{
+				auto __to = &__bs[0];
+				auto __to_end = __to + __bs.size();
+				const _Elem *__frm_nxt;
+				do
+				{
+					char *__to_nxt;
+					__r = this->__cvtptr_->out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
+					this->__cvtcount_ += __frm_nxt - __frm;
+					if (__frm_nxt == __frm)
+						__r = codecvt_base::error;
+					else if (__r == codecvt_base::noconv)
+					{
+						__bs.resize(__to - &__bs[0]);
+						// This only gets executed if _Elem is char
+						__bs.append(reinterpret_cast<const char *>(__frm), reinterpret_cast<const char *>(__frm_end));
+						__frm = __frm_nxt;
+						__r = codecvt_base::ok;
+					}
+					else if (__r == codecvt_base::ok)
+					{
+						__bs.resize(__to_nxt - &__bs[0]);
+						__frm = __frm_nxt;
+					}
+					else if (__r == codecvt_base::partial)
+					{
+						ptrdiff_t __s = __to_nxt - &__bs[0];
+						__bs.resize(2 * __s);
+						__to = &__bs[0] + __s;
+						__to_end = &__bs[0] + __bs.size();
+						__frm = __frm_nxt;
+					}
+				} while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
+			}
+			if (__r == codecvt_base::ok)
+			{
+				auto __s = __bs.size();
+				__bs.resize(__bs.capacity());
+				auto __to = &__bs[0] + __s;
+				auto __to_end = __to + __bs.size();
+				do
+				{
+					char *__to_nxt;
+					__r = this->__cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
+					if (__r == codecvt_base::noconv)
+					{
+						__bs.resize(__to - &__bs[0]);
+						__r = codecvt_base::ok;
+					}
+					else if (__r == codecvt_base::ok)
+						__bs.resize(__to_nxt - &__bs[0]);
+					else if (__r == codecvt_base::partial)
+					{
+						ptrdiff_t __sp = __to_nxt - &__bs[0];
+						__bs.resize(2 * __sp);
+						__to = &__bs[0] + __sp;
+						__to_end = &__bs[0] + __bs.size();
+					}
+				} while (__r == codecvt_base::partial);
+				if (__r == codecvt_base::ok)
+					return __bs;
+			}
+		}
+		if (this->__byte_err_string_.empty())
+			throw range_error("wstring_convert: to_bytes error");
+		return this->__byte_err_string_;
+	}
+
+	size_t converted() const throw() { return this->__cvtcount_; }
+	state_type state() const { return this->__cvtstate_; }
+};
+
+};
+#endif
+