Index: source/lib/os_path.h =================================================================== --- source/lib/os_path.h +++ source/lib/os_path.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -41,14 +41,7 @@ static inline std::string OsString(const OsPath& path) { - const Path::String& wstring = path.string(); - std::string string(wstring.length(), '\0'); - for(size_t i = 0; i < wstring.length(); i++) - { - ENSURE((unsigned)wstring[i] <= (unsigned)UCHAR_MAX); - string[i] = (char)wstring[i]; - } - return string; + return utf8_from_wstring(path.string()); } #endif Index: source/lib/path.h =================================================================== --- source/lib/path.h +++ source/lib/path.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -89,9 +89,7 @@ } Path(const char* p) - : path((const unsigned char*)p, (const unsigned char*)p+strlen(p)) - // interpret bytes as unsigned; makes no difference for ASCII, - // and ensures OsPath on Unix will only contain values 0 <= c < 0x100 + : path(wstring_from_utf8(p)) { DetectSeparator(); } @@ -103,7 +101,7 @@ } Path(const std::string& s) - : path((const unsigned char*)s.c_str(), (const unsigned char*)s.c_str()+s.length()) + : path(wstring_from_utf8(s)) { DetectSeparator(); } @@ -139,20 +137,8 @@ */ std::string string8() const { - Status err; -#if !OS_WIN - // On Unix, assume paths consisting of 8-bit charactes saved in this wide string. - std::string spath(path.begin(), path.end()); - - // Return it if it's valid UTF-8 - wstring_from_utf8(spath, &err); - if(err == INFO::OK) - return spath; - - // Otherwise assume ISO-8859-1 and let utf8_from_wstring treat each character as a Unicode code point. -#endif - // On Windows, paths are UTF-16 strings. We don't support non-BMP characters so we can assume it's simply a wstring. - return utf8_from_wstring(path, &err); + // We don't support non-BMP characters so we can assume it's simply a wstring. + return utf8_from_wstring(path); } bool operator<(const Path& rhs) const Index: source/lib/path.cpp =================================================================== --- source/lib/path.cpp +++ source/lib/path.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -98,15 +98,12 @@ /*static*/ Status Path::Validate(String::value_type c) { - if(c < 32) + if (c < 0x001F // C0 control codes + || (c > 0x0080 && c < 0x009F) // C1 control codes + || (c > 0xFFF0 && c < 0xFFFF)) // "Specials", including the "Not a Character" code. return ERR::PATH_CHARACTER_UNSAFE; -#if !OS_WIN - if(c >= UCHAR_MAX) - return ERR::PATH_CHARACTER_UNSAFE; -#endif - - switch(c) + switch (c) { case '\\': case '/': Index: source/lib/tests/test_path.h =================================================================== --- source/lib/tests/test_path.h +++ source/lib/tests/test_path.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -31,10 +31,9 @@ void test_ctor() { const char* s1 = "a/b/c"; - const char* s2 = "a/b/\xEF\xBF\xBF"; + const char* s2 = "a/b/\xE7\x81\xAB"; // "a/b/" const wchar_t* w1 = L"a/b/c"; - const wchar_t w2[] = { 'a', '/', 'b', '/', 0xEF, 0xBF, 0xBF, 0 }; - const wchar_t w3[] = { 'a', '/', 'b', '/', 0xFFFF, 0 }; + const wchar_t w2[] = { 'a', '/', 'b', '/', 0x706B, 0 }; // ['a', '/', 'b', '/', , NULL] // Empty strings Path p0a; @@ -51,10 +50,8 @@ Path ps2b = Path(std::string(s2)); Path pw1a = Path(w1); Path pw2a = Path(w2); - Path pw3a = Path(w3); Path pw1b = Path(std::wstring(w1)); Path pw2b = Path(std::wstring(w2)); - Path pw3b = Path(std::wstring(w3)); TS_ASSERT_WSTR_EQUALS(ps1a.string(), w1); TS_ASSERT_WSTR_EQUALS(ps1b.string(), w1); @@ -66,15 +63,10 @@ TS_ASSERT_WSTR_EQUALS(pw2a.string(), w2); TS_ASSERT_WSTR_EQUALS(pw2b.string(), w2); - TS_ASSERT_WSTR_EQUALS(pw3a.string(), w3); - TS_ASSERT_WSTR_EQUALS(pw3b.string(), w3); - #if OS_WIN TS_ASSERT_WSTR_EQUALS(OsString(pw2a), w2); - TS_ASSERT_WSTR_EQUALS(OsString(pw3a), w3); #else TS_ASSERT_STR_EQUALS(OsString(pw2a), s2); - // OsString(pw3a) causes an intentional assertion failure, but we can't test that #endif } }; Index: source/lib/utf8.cpp =================================================================== --- source/lib/utf8.cpp +++ source/lib/utf8.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -33,7 +33,9 @@ STATUS_ADD_DEFINITIONS(utf8StatusDefinitions); -// adapted from http://unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c +// Adapted from http://unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c +// (which is no longer accessible but a backup can can be found at: +// https://web.archive.org/web/20090523031611/http://www.unicode.org:80/Public/PROGRAMS/CVTUTF/ConvertUTF.c ) // which bears the following notice: /* * Copyright 2001-2004 Unicode, Inc. Index: source/network/NetClientTurnManager.cpp =================================================================== --- source/network/NetClientTurnManager.cpp +++ source/network/NetClientTurnManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -148,6 +148,6 @@ "players", playerNamesStrings, "expectedHash", expectedHashHex, "hash", Hexify(hash), - "path_oos_dump", wstring_from_utf8(oosdumpPath.string8()), - "path_replay", wstring_from_utf8(m_Replay.GetDirectory().string8())); + "path_oos_dump", oosdumpPath.string(), + "path_replay", m_Replay.GetDirectory().string()); } Index: source/ps/Game.cpp =================================================================== --- source/ps/Game.cpp +++ source/ps/Game.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -182,7 +182,7 @@ SetTurnManager(new CReplayTurnManager(*m_Simulation2, GetReplayLogger())); m_ReplayPath = replayPath; - m_ReplayStream = new std::ifstream(OsString(replayPath).c_str()); + m_ReplayStream = new std::ifstream(OsString(replayPath)); std::string type; ENSURE((*m_ReplayStream >> type).good() && type == "start"); Index: source/ps/Replay.cpp =================================================================== --- source/ps/Replay.cpp +++ source/ps/Replay.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -148,7 +148,7 @@ { ENSURE(!m_Stream); - m_Stream = new std::ifstream(OsString(path).c_str()); + m_Stream = new std::ifstream(OsString(path)); ENSURE(m_Stream->good()); } Index: source/ps/VisualReplay.cpp =================================================================== --- source/ps/VisualReplay.cpp +++ source/ps/VisualReplay.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -348,7 +348,7 @@ if (fileSize == 0) return JS::NullValue(); - std::ifstream* replayStream = new std::ifstream(OsString(replayFile).c_str()); + std::ifstream* replayStream = new std::ifstream(OsString(replayFile)); CStr type; if (!(*replayStream >> type).good()) @@ -438,7 +438,7 @@ return attribs; // Open file - std::istream* replayStream = new std::ifstream(OsString(replayFile).c_str()); + std::istream* replayStream = new std::ifstream(OsString(replayFile)); CStr type, line; ENSURE((*replayStream >> type).good() && type == "start"); @@ -490,7 +490,7 @@ ScriptRequest rq(pCmptPrivate->pScriptInterface); JS::RootedValue metadata(rq.cx); - std::ifstream* stream = new std::ifstream(OsString(GetDirectoryPath() / directoryName / L"metadata.json").c_str()); + std::ifstream* stream = new std::ifstream(OsString(GetDirectoryPath() / directoryName / L"metadata.json")); ENSURE(stream->good()); CStr line; std::getline(*stream, line); Index: source/ps/scripting/JSInterface_VisualReplay.cpp =================================================================== --- source/ps/scripting/JSInterface_VisualReplay.cpp +++ source/ps/scripting/JSInterface_VisualReplay.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -60,7 +60,7 @@ CStrW JSI_VisualReplay::GetReplayDirectoryName(ScriptInterface::CmptPrivate* UNUSED(pCmptPrivate), const CStrW& directoryName) { - return wstring_from_utf8(OsPath(VisualReplay::GetDirectoryPath() / directoryName).string8()); + return OsPath(VisualReplay::GetDirectoryPath() / directoryName).string(); } void JSI_VisualReplay::RegisterScriptFunctions(const ScriptInterface& scriptInterface)