]> git.sesse.net Git - casparcg/commitdiff
Merged latin1 fallback support to 2.1
authorhellgore <hellgore@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 4 Sep 2012 14:11:46 +0000 (14:11 +0000)
committerhellgore <hellgore@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 4 Sep 2012 14:11:46 +0000 (14:11 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.1.0@3230 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

protocol/amcp/AMCPCommandsImpl.cpp

index 01567a43bb2d4c2a71732be6d3e5c7286758a7d3..38211a84d1717c832bc3e15ea42afc1c9d4c4863 100644 (file)
@@ -60,6 +60,7 @@
 #include <algorithm>\r
 #include <locale>\r
 #include <fstream>\r
+#include <memory>\r
 #include <cctype>\r
 #include <io.h>\r
 \r
 #include <boost/lexical_cast.hpp>\r
 #include <boost/algorithm/string.hpp>\r
 #include <boost/filesystem.hpp>\r
+#include <boost/filesystem/fstream.hpp>\r
 #include <boost/regex.hpp>\r
 #include <boost/property_tree/xml_parser.hpp>\r
+#include <boost/locale.hpp>\r
+#include <boost/range/adaptor/transformed.hpp>\r
+#include <boost/range/algorithm/copy.hpp>\r
 \r
 #include <tbb/concurrent_unordered_map.h>\r
 \r
@@ -98,6 +103,76 @@ namespace caspar { namespace protocol {
 \r
 using namespace core;\r
 \r
+std::wstring read_utf8_file(const boost::filesystem::wpath& file)\r
+{\r
+       std::wstringstream result;\r
+       boost::filesystem::wifstream filestream(file);\r
+\r
+       if (filestream) \r
+       {\r
+               // Consume BOM first\r
+               filestream.get();\r
+               // read all data\r
+               result << filestream.rdbuf();\r
+       }\r
+\r
+       return result.str();\r
+}\r
+\r
+std::wstring read_latin1_file(const boost::filesystem::wpath& file)\r
+{\r
+       boost::locale::generator gen;\r
+       gen.locale_cache_enabled(true);\r
+       gen.categories(boost::locale::codepage_facet);\r
+\r
+       std::stringstream result_stream;\r
+       boost::filesystem::ifstream filestream(file);\r
+       filestream.imbue(gen("en_US.ISO8859-1"));\r
+\r
+       if (filestream)\r
+       {\r
+               // read all data\r
+               result_stream << filestream.rdbuf();\r
+       }\r
+\r
+       std::string result = result_stream.str();\r
+       std::wstring widened_result;\r
+\r
+       // The first 255 codepoints in unicode is the same as in latin1\r
+       auto from_signed_to_signed = std::function<unsigned char(char)>(\r
+               [] (char c) { return static_cast<unsigned char>(c); }\r
+       );\r
+       boost::copy(\r
+               result | boost::adaptors::transformed(from_signed_to_signed),\r
+               std::back_inserter(widened_result));\r
+\r
+       return widened_result;\r
+}\r
+\r
+std::wstring read_file(const boost::filesystem::wpath& file)\r
+{\r
+       static const uint8_t BOM[] = {0xef, 0xbb, 0xbf};\r
+\r
+       if (!boost::filesystem::exists(file))\r
+       {\r
+               return L"";\r
+       }\r
+\r
+       if (boost::filesystem::file_size(file) >= 3)\r
+       {\r
+               boost::filesystem::ifstream bom_stream(file);\r
+\r
+               char header[3];\r
+               bom_stream.read(header, 3);\r
+               bom_stream.close();\r
+\r
+               if (std::memcmp(BOM, header, 3) == 0)\r
+                       return read_utf8_file(file);\r
+       }\r
+\r
+       return read_latin1_file(file);\r
+}\r
+\r
 std::wstring MediaInfo(const boost::filesystem::path& path)\r
 {\r
        if(boost::filesystem::is_regular_file(path))\r
@@ -980,18 +1055,8 @@ bool CGCommand::DoExecuteAdd() {
                        filename.append(dataString);\r
                        filename.append(TEXT(".ftd"));\r
 \r
-                       //open file\r
-                       std::wifstream datafile(filename.c_str());\r
-                       if(datafile) \r
-                       {\r
-                               //read all data\r
-                               data << datafile.rdbuf();\r
-                               datafile.close();\r
-\r
-                               //extract data to _parameters\r
-                               dataFromFile = data.str();\r
-                               pDataString = dataFromFile.c_str();\r
-                       }\r
+                       dataFromFile = read_file(boost::filesystem::wpath(filename));\r
+                       pDataString = dataFromFile.c_str();\r
                }\r
        }\r
 \r
@@ -1128,18 +1193,7 @@ bool CGCommand::DoExecuteUpdate()
                        filename.append(dataString);\r
                        filename.append(TEXT(".ftd"));\r
 \r
-                       //open file\r
-                       std::wifstream datafile(filename.c_str());\r
-                       if(datafile) \r
-                       {\r
-                               std::wstringstream data;\r
-                               //read all data\r
-                               data << datafile.rdbuf();\r
-                               datafile.close();\r
-\r
-                               //extract data to _parameters\r
-                               dataString = data.str();\r
-                       }\r
+                       dataString = read_file(boost::filesystem::wpath(filename));\r
                }               \r
 \r
                int layer = _ttoi(_parameters.at(1).c_str());\r
@@ -1242,7 +1296,8 @@ bool DataCommand::DoExecuteStore()
                return false;\r
        }\r
 \r
-       datafile << _parameters2[2];\r
+       datafile << static_cast<wchar_t>(65279); // UTF-8 BOM character\r
+       datafile << _parameters2[2] << std::flush;\r
        datafile.close();\r
 \r
        std::wstring replyString = TEXT("202 DATA STORE OK\r\n");\r
@@ -1262,27 +1317,17 @@ bool DataCommand::DoExecuteRetrieve()
        filename.append(_parameters[1]);\r
        filename.append(TEXT(".ftd"));\r
 \r
-       std::wifstream datafile(filename.c_str());\r
-       if(!datafile) \r
+       std::wstring file_contents = read_file(boost::filesystem::wpath(filename));\r
+\r
+       if (file_contents.empty()) \r
        {\r
                SetReplyString(TEXT("404 DATA RETRIEVE ERROR\r\n"));\r
                return false;\r
        }\r
 \r
        std::wstringstream reply(TEXT("201 DATA RETRIEVE OK\r\n"));\r
-       std::wstring line;\r
-       bool bFirstLine = true;\r
-       while(std::getline(datafile, line))\r
-       {\r
-               if(!bFirstLine)\r
-                       reply << "\\n";\r
-               else\r
-                       bFirstLine = false;\r
-\r
-               reply << line;\r
-       }\r
-       datafile.close();\r
 \r
+       reply << file_contents;\r
        reply << "\r\n";\r
        SetReplyString(reply.str());\r
        return true;\r