#include <boost/log/utility/init/common_attributes.hpp>\r
#include <boost/log/utility/empty_deleter.hpp>\r
#include <boost/lambda/lambda.hpp>\r
+#include <boost/bind.hpp>\r
\r
namespace caspar { namespace log {\r
\r
using namespace boost;\r
\r
-void my_formatter(std::wostream& strm, boost::log::basic_record<wchar_t> const& rec)\r
+void my_formatter(bool print_all_characters, std::wostream& strm, boost::log::basic_record<wchar_t> const& rec)\r
{\r
namespace lambda = boost::lambda;\r
\r
strm << L" ";\r
}\r
\r
- strm << replace_nonprintable_copy(rec.message(), L'?');\r
+ if (print_all_characters)\r
+ {\r
+ strm << rec.message();\r
+ }\r
+ else\r
+ {\r
+ strm << replace_nonprintable_copy(rec.message(), L'?');\r
+ }\r
}\r
\r
namespace internal{\r
// stream_sink->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= debug);\r
//#endif\r
\r
- stream_sink->locked_backend()->set_formatter(&my_formatter);\r
+ stream_sink->locked_backend()->set_formatter(boost::bind(my_formatter, false, _1, _2));\r
\r
boost::log::wcore::get()->add_sink(stream_sink);\r
}\r
boost::log::keywords::auto_flush = true,\r
boost::log::keywords::open_mode = std::ios::app\r
);\r
- \r
- file_sink->locked_backend()->set_formatter(&my_formatter);\r
+\r
+ // TODO: does not seem to affect the character set only date formatting\r
+ file_sink->locked_backend()->imbue(caspar::get_narrow_locale());\r
+ // TODO: when UTF-8 log file output is fixed we can enable this\r
+ bool print_all_characters = false;\r
+\r
+ file_sink->locked_backend()->set_formatter(boost::bind(my_formatter, print_all_characters, _1, _2));\r
\r
//#ifdef NDEBUG\r
// file_sink->set_filter(boost::log::filters::attr<severity_level>(boost::log::sources::aux::severity_attribute_name<wchar_t>::get()) >= debug);\r
inline void replace_nonprintable(std::basic_string<T, std::char_traits<T>, std::allocator<T>>& str, T with)\r
{\r
std::locale loc;\r
- std::replace_if(str.begin(), str.end(), [&](T c)->bool { return !std::isprint(c, loc) && c != '\r' && c != '\n'; }, with);\r
+ std::replace_if(str.begin(), str.end(), [&](T c)->bool {\r
+ return \r
+ (!std::isprint(c, loc) \r
+ && c != '\r' \r
+ && c != '\n')\r
+ || c > static_cast<T>(127);\r
+ }, with);\r
}\r
\r
template<typename T>\r
\r
#include "../stdafx.h"\r
\r
+#include <boost/locale.hpp>\r
+\r
#include "utf8conv.h"\r
\r
namespace caspar {\r
return str ;\r
}\r
\r
+std::locale get_narrow_locale()\r
+{\r
+ boost::locale::generator gen;\r
+\r
+ gen.locale_cache_enabled(true);\r
+\r
+ // TODO: make configurable?\r
+ return gen.generate("en_GB.UTF-8");\r
+}\r
+\r
}
\ No newline at end of file
#pragma once\r
\r
#include <string>\r
+#include <locale>\r
#include <boost/lexical_cast.hpp>\r
\r
namespace caspar {\r
std::wstring widen(const std::wstring& str);\r
std::string narrow(const std::wstring& str); \r
std::string narrow(const std::string& str);\r
+std::locale get_narrow_locale();\r
\r
template <typename T>\r
inline T lexical_cast_or_default(const std::wstring str, T fail_value = T())\r
#include <common/diagnostics/graph.h>\r
#include <common/os/windows/current_version.h>\r
#include <common/os/windows/system_info.h>\r
+#include <common/utility/string.h>\r
\r
#include <core/producer/frame_producer.h>\r
#include <core/video_format.h>\r
\r
//open file\r
std::wifstream datafile(filename.c_str());\r
+ datafile.imbue(caspar::get_narrow_locale());\r
+\r
if(datafile) \r
{\r
//read all data\r
\r
//open file\r
std::wifstream datafile(filename.c_str());\r
+ datafile.imbue(caspar::get_narrow_locale());\r
+\r
if(datafile) \r
{\r
std::wstringstream data;\r
filename.append(_parameters[1]);\r
filename.append(TEXT(".ftd"));\r
\r
- std::wofstream datafile(filename.c_str());\r
+ std::wofstream datafile;\r
+\r
+ datafile.imbue(caspar::get_narrow_locale());\r
+ datafile.open(filename.c_str());\r
+\r
if(!datafile) \r
{\r
SetReplyString(TEXT("501 DATA STORE FAILED\r\n"));\r
filename.append(TEXT(".ftd"));\r
\r
std::wifstream datafile(filename.c_str());\r
+\r
+ datafile.imbue(caspar::get_narrow_locale());\r
+\r
if(!datafile) \r
{\r
SetReplyString(TEXT("404 DATA RETRIEVE ERROR\r\n"));\r
\r
void AMCPProtocolStrategy::ProcessMessage(const std::wstring& message, ClientInfoPtr& pClientInfo)\r
{ \r
- CASPAR_LOG(info) << L"Received message from " << pClientInfo->print() << ": " << log::replace_nonprintable_copy(message, L'?') + L"\\r\\n";\r
+ CASPAR_LOG(info) << L"Received message from " << pClientInfo->print() << ": " << message << L"\\r\\n";\r
\r
bool bError = true;\r
MessageParserState state = New;\r
\r
void CIIProtocolStrategy::ProcessMessage(const std::wstring& message, IO::ClientInfoPtr pClientInfo)\r
{ \r
- CASPAR_LOG(info) << L"Received message from " << pClientInfo->print() << ": " << log::replace_nonprintable_copy(message, L'?') + L"\\r\\n";\r
+ CASPAR_LOG(info) << L"Received message from " << pClientInfo->print() << ": " << message << L"\\r\\n";\r
\r
std::vector<std::wstring> tokens;\r
int tokenCount = TokenizeMessage(message, &tokens);\r
#include <string>\r
#include <iostream>\r
\r
+#include <common/log/log.h>\r
+\r
namespace caspar { namespace IO {\r
\r
class ClientInfo \r
{\r
void Send(const std::wstring& data)\r
{\r
- std::wcout << (L"#" + data);\r
+ std::wcout << (L"#" + caspar::log::replace_nonprintable_copy(data, L'?'));\r
}\r
void Disconnect(){}\r
virtual std::wstring print() const {return L"Console";}\r