Mostly purge wxWidgets from non-UI stuff
Use boost::filesystem::path for all paths, and std::string for all other strings, converting to/from wxString as close to the actual uses of wx as possible. Where possible, replace the uses of non-UI wxWidgets functionality with the additions to the standard library in C++11, or the equivalents in boost. Move the path token management logic to libaegisub (and rewrite it in the process). Add a basic thread pool based on asio and std::thread to libaegisub. This touches nearly every file in the project and a nontrivial amount of code had to be rewritten entirely, so there's probably a lot of broken stuff.
This commit is contained in:
parent
10e06ac3f9
commit
1e0f08c0ed
297 changed files with 5702 additions and 6573 deletions
|
@ -134,7 +134,6 @@
|
|||
<ClInclude Include="$(SrcDir)avisynth_wrap.h" />
|
||||
<ClInclude Include="$(SrcDir)base_grid.h" />
|
||||
<ClInclude Include="$(SrcDir)block_cache.h" />
|
||||
<ClInclude Include="$(SrcDir)charset_conv.h" />
|
||||
<ClInclude Include="$(SrcDir)charset_detect.h" />
|
||||
<ClInclude Include="$(SrcDir)colorspace.h" />
|
||||
<ClInclude Include="$(SrcDir)colour_button.h" />
|
||||
|
@ -321,7 +320,6 @@
|
|||
<ClCompile Include="$(SrcDir)auto4_lua_scriptreader.cpp" />
|
||||
<ClCompile Include="$(SrcDir)avisynth_wrap.cpp" />
|
||||
<ClCompile Include="$(SrcDir)base_grid.cpp" />
|
||||
<ClCompile Include="$(SrcDir)charset_conv.cpp" />
|
||||
<ClCompile Include="$(SrcDir)charset_detect.cpp" />
|
||||
<ClCompile Include="$(SrcDir)colorspace.cpp" />
|
||||
<ClCompile Include="$(SrcDir)colour_button.cpp" />
|
||||
|
|
|
@ -525,9 +525,6 @@
|
|||
<ClInclude Include="$(SrcDir)charset_detect.h">
|
||||
<Filter>Features\Import</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)charset_conv.h">
|
||||
<Filter>Features\Import</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)help_button.h">
|
||||
<Filter>Features\Help</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1076,9 +1073,6 @@
|
|||
<ClCompile Include="$(SrcDir)subs_grid.cpp">
|
||||
<Filter>Main UI\Grid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)charset_conv.cpp">
|
||||
<Filter>Features\Import</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)charset_detect.cpp">
|
||||
<Filter>Features\Import</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -17,20 +17,27 @@
|
|||
<!-- Project specific configuration -->
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(SrcDir);$(SrcDir)include;$(AegisubContribBase)iconv\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>
|
||||
$(SrcDir);
|
||||
$(SrcDir)include;
|
||||
$(AegisubContribBase)iconv\include;
|
||||
%(AdditionalIncludeDirectories)
|
||||
</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>
|
||||
NOMINMAX;
|
||||
_WIN32_WINNT=0x0501;
|
||||
%(PreprocessorDefinitions)
|
||||
</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>lagi_pre.h</PrecompiledHeaderFile>
|
||||
<ForcedIncludeFiles>lagi_pre.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- Source files -->
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(SrcDir)lagi_pre.h" />
|
||||
<ClInclude Include="$(SrcDir)config.h" />
|
||||
<ClInclude Include="$(SrcDir)common\charset_6937.h" />
|
||||
<ClInclude Include="$(SrcDir)common\charset_ucd.h" />
|
||||
<ClInclude Include="$(SrcDir)common\option_visit.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\access.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\charset.h" />
|
||||
|
@ -64,8 +71,13 @@
|
|||
<ClInclude Include="$(SrcDir)include\libaegisub\background_runner.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\color.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\spellchecker.h" />
|
||||
<ClInclude Include="..\..\libaegisub\include\libaegisub\calltip_provider.h" />
|
||||
<ClInclude Include="..\..\libaegisub\include\libaegisub\of_type_adaptor.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\calltip_provider.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\fs.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\of_type_adaptor.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\path.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\fs_fwd.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\dispatch.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\split.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(SrcDir)windows\lagi_pre.cpp">
|
||||
|
@ -78,7 +90,6 @@
|
|||
<ClCompile Include="$(SrcDir)common\charset.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\charset_6937.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\charset_conv.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\charset_ucd.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\hotkey.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\json.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\keyframe.cpp" />
|
||||
|
@ -96,8 +107,13 @@
|
|||
<ClCompile Include="$(SrcDir)ass\dialogue_parser.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\color.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\parser.cpp" />
|
||||
<ClCompile Include="..\..\libaegisub\common\calltip_provider.cpp" />
|
||||
<ClCompile Include="..\..\libaegisub\common\io.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\calltip_provider.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\fs.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\io.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\path.cpp" />
|
||||
<ClCompile Include="$(SrcDir)windows\fs.cpp" />
|
||||
<ClCompile Include="$(SrcDir)windows\path_win.cpp" />
|
||||
<ClCompile Include="$(SrcDir)common\dispatch.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="$(SrcDir)include\libaegisub\charsets.def" />
|
||||
|
|
|
@ -26,9 +26,6 @@
|
|||
<ClInclude Include="$(SrcDir)common\charset_6937.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)common\charset_ucd.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)common\option_visit.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -134,10 +131,25 @@
|
|||
<ClInclude Include="$(SrcDir)common\parser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\libaegisub\include\libaegisub\of_type_adaptor.h">
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\of_type_adaptor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\libaegisub\include\libaegisub\calltip_provider.h">
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\calltip_provider.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\path.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\fs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\fs_fwd.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\dispatch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\split.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
@ -160,9 +172,6 @@
|
|||
<ClCompile Include="$(SrcDir)windows\charset_conv_win.cpp">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)common\charset_ucd.cpp">
|
||||
<Filter>Source Files\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)windows\log_win.cpp">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClCompile>
|
||||
|
@ -220,10 +229,25 @@
|
|||
<ClCompile Include="$(SrcDir)common\parser.cpp">
|
||||
<Filter>Source Files\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\libaegisub\common\io.cpp">
|
||||
<ClCompile Include="$(SrcDir)common\io.cpp">
|
||||
<Filter>Source Files\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\libaegisub\common\calltip_provider.cpp">
|
||||
<ClCompile Include="$(SrcDir)common\calltip_provider.cpp">
|
||||
<Filter>Source Files\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)common\path.cpp">
|
||||
<Filter>Source Files\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)windows\path_win.cpp">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)windows\fs.cpp">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)common\fs.cpp">
|
||||
<Filter>Source Files\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)common\dispatch.cpp">
|
||||
<Filter>Source Files\Common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
@ -232,4 +256,4 @@
|
|||
<Filter>Header Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -25,23 +25,27 @@ SRC += \
|
|||
common/charset.cpp \
|
||||
common/charset_6937.cpp \
|
||||
common/charset_conv.cpp \
|
||||
common/charset_ucd.cpp \
|
||||
common/color.cpp \
|
||||
common/dispatch.cpp \
|
||||
common/fs.cpp \
|
||||
common/hotkey.cpp \
|
||||
common/io.cpp \
|
||||
common/json.cpp \
|
||||
common/keyframe.cpp \
|
||||
common/log.cpp \
|
||||
common/mru.cpp \
|
||||
common/option.cpp \
|
||||
common/option_visit.cpp \
|
||||
common/parser.cpp \
|
||||
common/util.cpp \
|
||||
common/log.cpp \
|
||||
common/path.cpp \
|
||||
common/thesaurus.cpp \
|
||||
common/util.cpp \
|
||||
common/vfr.cpp \
|
||||
unix/util.cpp \
|
||||
unix/access.cpp \
|
||||
unix/log.cpp
|
||||
unix/fs.cpp \
|
||||
unix/log.cpp \
|
||||
unix/path.cpp \
|
||||
unix/util.cpp
|
||||
|
||||
ifeq (yes, $(BUILD_DARWIN))
|
||||
SRC += osx/util.mm
|
||||
|
|
|
@ -16,18 +16,118 @@
|
|||
/// @brief Character set detection and manipulation utilities.
|
||||
/// @ingroup libaegisub
|
||||
|
||||
#include "charset_ucd.h"
|
||||
#include "libaegisub/charset.h"
|
||||
|
||||
namespace agi {
|
||||
namespace charset {
|
||||
#include "libaegisub/io.h"
|
||||
|
||||
std::string Detect(const std::string &file) {
|
||||
return UCDetect(file).Single();
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#ifndef _WIN32
|
||||
#define _X86_ 1
|
||||
#endif
|
||||
|
||||
#include "../../universalchardet/nscore.h"
|
||||
#include "../../universalchardet/nsUniversalDetector.h"
|
||||
#include "../../universalchardet/nsMBCSGroupProber.h"
|
||||
#include "../../universalchardet/nsCharSetProber.h"
|
||||
|
||||
namespace {
|
||||
using namespace agi::charset;
|
||||
|
||||
class UCDetect : public nsUniversalDetector {
|
||||
/// List of detected character sets
|
||||
CharsetListDetected list;
|
||||
|
||||
void Report(const char* aCharset) {}
|
||||
|
||||
public:
|
||||
/// @brief Detect character set of a file using UniversalCharDetect
|
||||
/// @param file File to check
|
||||
UCDetect(agi::fs::path const& file)
|
||||
: nsUniversalDetector(NS_FILTER_ALL)
|
||||
{
|
||||
{
|
||||
std::unique_ptr<std::ifstream> fp(agi::io::Open(file, true));
|
||||
|
||||
// If it's over 100 MB it's either binary or big enough that we won't
|
||||
// be able to do anything useful with it anyway
|
||||
fp->seekg(0, std::ios::end);
|
||||
if (fp->tellg() > 100 * 1024 * 1024) {
|
||||
list.emplace_back(1.f, "binary");
|
||||
return;
|
||||
}
|
||||
fp->seekg(0, std::ios::beg);
|
||||
|
||||
std::streamsize binaryish = 0;
|
||||
std::streamsize bytes = 0;
|
||||
|
||||
while (!mDone && *fp) {
|
||||
char buf[4096];
|
||||
fp->read(buf, sizeof(buf));
|
||||
std::streamsize read = fp->gcount();
|
||||
HandleData(buf, (PRUint32)read);
|
||||
|
||||
// A dumb heuristic to detect binary files
|
||||
if (!mDone) {
|
||||
bytes += read;
|
||||
for (std::streamsize i = 0; i < read; ++i) {
|
||||
if ((unsigned char)buf[i] < 32 && (buf[i] != '\r' && buf[i] != '\n' && buf[i] != '\t'))
|
||||
++binaryish;
|
||||
}
|
||||
|
||||
if (binaryish > bytes / 8) {
|
||||
list.emplace_back(1.f, "binary");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataEnd();
|
||||
|
||||
if (mDetectedCharset)
|
||||
list.emplace_back(1.f, mDetectedCharset);
|
||||
else {
|
||||
switch (mInputState) {
|
||||
case eHighbyte: {
|
||||
for (PRInt32 i=0; i<NUM_OF_CHARSET_PROBERS; i++) {
|
||||
if (!mCharSetProbers[i]) continue;
|
||||
|
||||
float conf = mCharSetProbers[i]->GetConfidence();
|
||||
if (conf > 0.01f)
|
||||
list.emplace_back(conf, mCharSetProbers[i]->GetCharSetName());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ePureAscii:
|
||||
list.emplace_back(1.f, "US-ASCII");
|
||||
break;
|
||||
|
||||
default:
|
||||
throw UnknownCharset("Unknown character set.");
|
||||
}
|
||||
|
||||
if (list.empty() && (mInputState == eHighbyte))
|
||||
throw UnknownCharset("Unknown character set.");
|
||||
|
||||
typedef std::pair<float, std::string> const& result;
|
||||
sort(begin(list), end(list), [](result lft, result rgt) { return lft.first > rgt.first; });
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Detect character set of a file using UniversalCharDet
|
||||
CharsetListDetected List() const { return list; }
|
||||
};
|
||||
}
|
||||
|
||||
CharsetListDetected DetectAll(const std::string& file) {
|
||||
return UCDetect(file).List();
|
||||
}
|
||||
namespace agi { namespace charset {
|
||||
std::string Detect(agi::fs::path const& file) {
|
||||
return DetectAll(file).front().second;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace agi
|
||||
CharsetListDetected DetectAll(agi::fs::path const& file) {
|
||||
return UCDetect(file).List();
|
||||
}
|
||||
} }
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/// @file charset_ucd.cpp
|
||||
/// @brief Character set detection using Universalchardet
|
||||
/// @ingroup libaegisub
|
||||
|
||||
#include "charset_ucd.h"
|
||||
|
||||
#include "libaegisub/io.h"
|
||||
#include "libaegisub/scoped_ptr.h"
|
||||
|
||||
#include "../../universalchardet/nsCharSetProber.h"
|
||||
|
||||
namespace agi {
|
||||
namespace charset {
|
||||
|
||||
UCDetect::UCDetect(const std::string &file)
|
||||
: nsUniversalDetector(NS_FILTER_ALL)
|
||||
{
|
||||
{
|
||||
agi::scoped_ptr<std::ifstream> fp(io::Open(file, true));
|
||||
|
||||
// If it's over 100 MB it's either binary or big enough that we won't
|
||||
// be able to do anything useful with it anyway
|
||||
fp->seekg(0, std::ios::end);
|
||||
if (fp->tellg() > 100 * 1024 * 1024) {
|
||||
list.emplace_back(1.f, "binary");
|
||||
return;
|
||||
}
|
||||
fp->seekg(0, std::ios::beg);
|
||||
|
||||
std::streamsize binaryish = 0;
|
||||
std::streamsize bytes = 0;
|
||||
|
||||
while (!mDone && *fp) {
|
||||
char buf[4096];
|
||||
fp->read(buf, sizeof(buf));
|
||||
std::streamsize read = fp->gcount();
|
||||
HandleData(buf, (PRUint32)read);
|
||||
|
||||
// A dumb heuristic to detect binary files
|
||||
if (!mDone) {
|
||||
bytes += read;
|
||||
for (std::streamsize i = 0; i < read; ++i) {
|
||||
if ((unsigned char)buf[i] < 32 && (buf[i] != '\r' && buf[i] != '\n' && buf[i] != '\t'))
|
||||
++binaryish;
|
||||
}
|
||||
|
||||
if (binaryish > bytes / 8) {
|
||||
list.emplace_back(1.f, "binary");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataEnd();
|
||||
|
||||
if (mDetectedCharset)
|
||||
list.emplace_back(1.f, mDetectedCharset);
|
||||
else {
|
||||
switch (mInputState) {
|
||||
case eHighbyte: {
|
||||
for (PRInt32 i=0; i<NUM_OF_CHARSET_PROBERS; i++) {
|
||||
if (!mCharSetProbers[i]) continue;
|
||||
|
||||
float conf = mCharSetProbers[i]->GetConfidence();
|
||||
if (conf > 0.01f)
|
||||
list.emplace_back(conf, mCharSetProbers[i]->GetCharSetName());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ePureAscii:
|
||||
list.emplace_back(1.f, "US-ASCII");
|
||||
break;
|
||||
|
||||
default:
|
||||
throw UnknownCharset("Unknown character set.");
|
||||
}
|
||||
|
||||
if (list.empty() && (mInputState == eHighbyte))
|
||||
throw UnknownCharset("Unknown character set.");
|
||||
|
||||
typedef std::pair<float, std::string> const& result;
|
||||
sort(begin(list), end(list), [](result lft, result rgt) { return lft.first > rgt.first; });
|
||||
}
|
||||
}
|
||||
|
||||
std::string UCDetect::Single() const {
|
||||
return list.front().second;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace agi
|
|
@ -1,56 +0,0 @@
|
|||
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/// @file charset_ucd.h
|
||||
/// @brief Character set detection using Universalchardet
|
||||
/// @ingroup libaegisub
|
||||
|
||||
#include "libaegisub/charset.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef _WIN32
|
||||
#define _X86_ 1
|
||||
#endif
|
||||
|
||||
#include "../../universalchardet/nscore.h"
|
||||
#include "../../universalchardet/nsUniversalDetector.h"
|
||||
#include "../../universalchardet/nsMBCSGroupProber.h"
|
||||
|
||||
namespace agi {
|
||||
namespace charset {
|
||||
|
||||
class UCDetect : public nsUniversalDetector {
|
||||
/// List of detected character sets.
|
||||
CharsetListDetected list;
|
||||
|
||||
/// Stub.
|
||||
void Report(const char* aCharset) {};
|
||||
|
||||
public:
|
||||
|
||||
/// @brief Detect character set of a file using UniversalCharDetect
|
||||
/// @param file File to check
|
||||
UCDetect(const std::string &file);
|
||||
|
||||
/// @brief Detect character set of a file using UniversalCharDet
|
||||
CharsetListDetected List() const { return list; }
|
||||
|
||||
/// @brief Return a single character set (highest confidence)
|
||||
/// @return Character set
|
||||
std::string Single() const;
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
} // namespace agi
|
98
aegisub/libaegisub/common/dispatch.cpp
Normal file
98
aegisub/libaegisub/common/dispatch.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
// Aegisub Project http://www.aegisub.org/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libaegisub/dispatch.h"
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
namespace {
|
||||
boost::asio::io_service *service;
|
||||
std::function<void (agi::dispatch::Thunk)> invoke_main;
|
||||
|
||||
class MainQueue : public agi::dispatch::Queue {
|
||||
void DoInvoke(agi::dispatch::Thunk thunk) {
|
||||
invoke_main(thunk);
|
||||
}
|
||||
};
|
||||
|
||||
class BackgroundQueue : public agi::dispatch::Queue {
|
||||
void DoInvoke(agi::dispatch::Thunk thunk) {
|
||||
service->post(thunk);
|
||||
}
|
||||
};
|
||||
|
||||
class SerialQueue : public agi::dispatch::Queue {
|
||||
boost::asio::io_service::strand strand;
|
||||
|
||||
void DoInvoke(agi::dispatch::Thunk thunk) {
|
||||
strand.post(thunk);
|
||||
}
|
||||
public:
|
||||
SerialQueue() : strand(*service) { }
|
||||
};
|
||||
}
|
||||
|
||||
namespace agi { namespace dispatch {
|
||||
|
||||
void Init(std::function<void (Thunk)> invoke_main) {
|
||||
static boost::asio::io_service service;
|
||||
static boost::asio::io_service::work work(service);
|
||||
::service = &service;
|
||||
::invoke_main = invoke_main;
|
||||
|
||||
for (unsigned i = 0; i < std::max<unsigned>(1, std::thread::hardware_concurrency()); ++i)
|
||||
std::thread([]{ ::service->run(); }).detach();
|
||||
}
|
||||
|
||||
void Queue::Async(Thunk thunk) {
|
||||
DoInvoke(thunk);
|
||||
}
|
||||
|
||||
void Queue::Sync(Thunk thunk) {
|
||||
std::mutex m;
|
||||
std::condition_variable cv;
|
||||
std::unique_lock<std::mutex> l(m);
|
||||
bool done = false;
|
||||
DoInvoke([&]{
|
||||
std::unique_lock<std::mutex> l(m);
|
||||
thunk();
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
cv.wait(l, [&]{ return done; });
|
||||
}
|
||||
|
||||
Queue& Main() {
|
||||
static MainQueue q;
|
||||
return q;
|
||||
}
|
||||
|
||||
Queue& Background() {
|
||||
static BackgroundQueue q;
|
||||
return q;
|
||||
}
|
||||
|
||||
std::unique_ptr<Queue> Create() {
|
||||
return std::unique_ptr<Queue>(new SerialQueue);
|
||||
}
|
||||
|
||||
} }
|
106
aegisub/libaegisub/common/fs.cpp
Normal file
106
aegisub/libaegisub/common/fs.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
// Aegisub Project http://www.aegisub.org/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libaegisub/fs.h"
|
||||
|
||||
#include "libaegisub/access.h"
|
||||
#include "libaegisub/exception.h"
|
||||
#include "libaegisub/log.h"
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace bfs = boost::filesystem;
|
||||
namespace ec = boost::system::errc;
|
||||
|
||||
// boost::filesystem functions throw a single exception type for all
|
||||
// errors, which isn't really what we want, so do some crazy wrapper
|
||||
// shit to map error codes to more useful exceptions.
|
||||
#define CHECKED_CALL(exp, src_path, dst_path) \
|
||||
boost::system::error_code ec; \
|
||||
exp; \
|
||||
switch (ec.value()) {\
|
||||
case ec::success: break; \
|
||||
case ec::no_such_file_or_directory: throw FileNotFound(src_path); \
|
||||
case ec::is_a_directory: throw NotAFile(src_path); \
|
||||
case ec::not_a_directory: throw NotADirectory(src_path); \
|
||||
case ec::no_space_on_device: throw DriveFull(dst_path); \
|
||||
case ec::permission_denied: \
|
||||
if (!src_path.empty()) \
|
||||
acs::CheckFileRead(src_path); \
|
||||
if (!dst_path.empty()) \
|
||||
acs::CheckFileWrite(dst_path); \
|
||||
throw AccessDenied(src_path); \
|
||||
default: \
|
||||
LOG_D("filesystem") << "Unknown error when calling '" << #exp << "': " << ec << ": " << ec.message(); \
|
||||
throw FileSystemUnknownError(ec.message()); \
|
||||
}
|
||||
|
||||
#define CHECKED_CALL_RETURN(exp, src_path) \
|
||||
CHECKED_CALL(auto ret = exp, src_path, agi::fs::path()); \
|
||||
return ret
|
||||
|
||||
#define WRAP_BFS(bfs_name, agi_name) \
|
||||
auto agi_name(path const& p) -> decltype(bfs::bfs_name(p)) { \
|
||||
CHECKED_CALL_RETURN(bfs::bfs_name(p, ec), p); \
|
||||
}
|
||||
|
||||
#define WRAP_BFS_IGNORE_ERROR(bfs_name, agi_name) \
|
||||
auto agi_name(path const& p) -> decltype(bfs::bfs_name(p)) { \
|
||||
boost::system::error_code ec; \
|
||||
return bfs::bfs_name(p, ec); \
|
||||
}
|
||||
|
||||
// sasuga windows.h
|
||||
#undef CreateDirectory
|
||||
|
||||
namespace agi { namespace fs {
|
||||
WRAP_BFS_IGNORE_ERROR(exists, Exists)
|
||||
WRAP_BFS_IGNORE_ERROR(is_regular_file, FileExists)
|
||||
WRAP_BFS_IGNORE_ERROR(is_directory, DirectoryExists)
|
||||
WRAP_BFS(file_size, SizeImpl)
|
||||
WRAP_BFS(last_write_time, ModifiedTime)
|
||||
WRAP_BFS(create_directories, CreateDirectory)
|
||||
WRAP_BFS(space, Space)
|
||||
WRAP_BFS(remove, Remove)
|
||||
WRAP_BFS(canonical, Canonicalize)
|
||||
|
||||
uintmax_t Size(path const& p) {
|
||||
if (DirectoryExists(p))
|
||||
throw NotAFile(p);
|
||||
return SizeImpl(p);
|
||||
}
|
||||
|
||||
uintmax_t FreeSpace(path const& p) {
|
||||
return Space(p).available;
|
||||
}
|
||||
|
||||
void Rename(const path& from, const path& to) {
|
||||
CHECKED_CALL(bfs::rename(from, to, ec), from, to);
|
||||
}
|
||||
|
||||
void Copy(path const& from, path const& to) {
|
||||
CreateDirectory(to.parent_path());
|
||||
CHECKED_CALL(bfs::copy_file(from, to, bfs::copy_option::overwrite_if_exists, ec), from, to);
|
||||
}
|
||||
|
||||
bool HasExtension(path const& p, std::string const& ext) {
|
||||
if (!p.has_extension()) return ext.empty();
|
||||
return boost::iequals(p.extension().string().substr(1), ext);
|
||||
}
|
||||
} }
|
|
@ -18,11 +18,6 @@
|
|||
|
||||
#include "../config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
||||
#include "libaegisub/hotkey.h"
|
||||
|
||||
#include "libaegisub/cajun/writer.h"
|
||||
|
@ -31,8 +26,12 @@
|
|||
#include "libaegisub/json.h"
|
||||
#include "libaegisub/log.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <tuple>
|
||||
|
||||
namespace agi {
|
||||
namespace hotkey {
|
||||
|
@ -50,12 +49,12 @@ void Hotkey::ComboInsert(Combo const& combo) {
|
|||
cmd_map.insert(make_pair(combo.CmdName(), combo));
|
||||
}
|
||||
|
||||
Hotkey::Hotkey(const std::string &file, const std::string &default_config)
|
||||
Hotkey::Hotkey(agi::fs::path const& file, const std::string &default_config)
|
||||
: config_file(file)
|
||||
{
|
||||
LOG_D("hotkey/init") << "Generating hotkeys.";
|
||||
|
||||
json::Object object(agi::json_util::file(config_file, default_config));
|
||||
const json::Object object(agi::json_util::file(config_file, default_config));
|
||||
for (auto const& hotkey_context : object)
|
||||
BuildHotkey(hotkey_context.first, hotkey_context.second);
|
||||
}
|
||||
|
@ -118,7 +117,7 @@ std::vector<std::string> Hotkey::GetHotkeys(const std::string &context, const st
|
|||
for (std::tie(it, end) = cmd_map.equal_range(command); it != end; ++it) {
|
||||
std::string ctext = it->second.Context();
|
||||
if (ctext == "Always" || ctext == "Default" || ctext == context)
|
||||
ret.push_back(it->second.StrMenu());
|
||||
ret.emplace_back(it->second.StrMenu());
|
||||
}
|
||||
|
||||
sort(ret.begin(), ret.end());
|
||||
|
|
|
@ -16,49 +16,25 @@
|
|||
/// @brief Windows IO methods.
|
||||
/// @ingroup libaegisub
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "libaegisub/io.h"
|
||||
|
||||
#include <libaegisub/access.h>
|
||||
#include <libaegisub/charset_conv_win.h>
|
||||
#include "libaegisub/io.h"
|
||||
#include "libaegisub/fs.h"
|
||||
#include "libaegisub/log.h"
|
||||
#include "libaegisub/path.h"
|
||||
#include "libaegisub/util.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
std::string make_temp_name(std::string const& filename) {
|
||||
char tmp[1024];
|
||||
snprintf(tmp, sizeof tmp, "_tmp_%lld", (long long)time(0));
|
||||
|
||||
std::string::size_type pos = filename.rfind('.');
|
||||
if (pos == std::string::npos)
|
||||
return filename + tmp;
|
||||
|
||||
return filename.substr(0, pos) + tmp + filename.substr(pos);
|
||||
}
|
||||
}
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
namespace agi {
|
||||
namespace io {
|
||||
|
||||
using agi::charset::ConvertW;
|
||||
|
||||
#ifndef _WIN32
|
||||
#define ConvertW
|
||||
#endif
|
||||
|
||||
std::ifstream* Open(const std::string &file, bool binary) {
|
||||
std::ifstream* Open(fs::path const& file, bool binary) {
|
||||
LOG_D("agi/io/open/file") << file;
|
||||
acs::CheckFileRead(file);
|
||||
|
||||
std::ifstream *stream = new std::ifstream(ConvertW(file).c_str(), (binary ? std::ios::binary : std::ios::in));
|
||||
auto stream = new boost::filesystem::ifstream(file, (binary ? std::ios::binary : std::ios::in));
|
||||
|
||||
if (stream->fail()) {
|
||||
delete stream;
|
||||
|
@ -68,34 +44,30 @@ std::ifstream* Open(const std::string &file, bool binary) {
|
|||
return stream;
|
||||
}
|
||||
|
||||
Save::Save(const std::string& file, bool binary)
|
||||
Save::Save(fs::path const& file, bool binary)
|
||||
: file_name(file)
|
||||
, tmp_name(make_temp_name(file))
|
||||
, tmp_name(unique_path(file.parent_path()/(file.stem().string() + "_tmp_%%%%." + file.extension().string())))
|
||||
{
|
||||
LOG_D("agi/io/save/file") << file;
|
||||
const std::string pwd = util::DirName(file);
|
||||
|
||||
acs::CheckDirWrite(pwd);
|
||||
acs::CheckDirWrite(file.parent_path());
|
||||
|
||||
try {
|
||||
acs::CheckFileWrite(file);
|
||||
} catch (FileNotFoundError const&) {
|
||||
// If the file doesn't exist we create a 0 byte file, this so so
|
||||
// util::Rename will find it, and to let users know something went
|
||||
// wrong by leaving a 0 byte file.
|
||||
std::ofstream(ConvertW(file).c_str());
|
||||
}
|
||||
catch (fs::FileNotFound const&) {
|
||||
// Not an error
|
||||
}
|
||||
|
||||
fp = new std::ofstream(ConvertW(tmp_name).c_str(), binary ? std::ios::binary : std::ios::out);
|
||||
fp = new boost::filesystem::ofstream(tmp_name, binary ? std::ios::binary : std::ios::out);
|
||||
if (!fp->good()) {
|
||||
delete fp;
|
||||
throw agi::FileNotAccessibleError("Could not create temporary file at: " + tmp_name);
|
||||
throw fs::WriteDenied(tmp_name);
|
||||
}
|
||||
}
|
||||
|
||||
Save::~Save() {
|
||||
delete fp;
|
||||
util::Rename(tmp_name, file_name);
|
||||
delete fp; // Explicitly delete to unlock file on Windows
|
||||
fs::Rename(tmp_name, file_name);
|
||||
}
|
||||
|
||||
std::ofstream& Save::Get() {
|
||||
|
|
|
@ -18,21 +18,22 @@
|
|||
|
||||
#include "../config.h"
|
||||
|
||||
#include "libaegisub/json.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include "libaegisub/fs.h"
|
||||
#include "libaegisub/io.h"
|
||||
#include "libaegisub/json.h"
|
||||
#include "libaegisub/log.h"
|
||||
#include "libaegisub/scoped_ptr.h"
|
||||
|
||||
|
||||
namespace agi {
|
||||
namespace json_util {
|
||||
|
||||
json::UnknownElement parse(std::istream *stream) {
|
||||
try {
|
||||
agi::scoped_ptr<std::istream> stream_deleter(stream);
|
||||
std::unique_ptr<std::istream> stream_deleter(stream);
|
||||
|
||||
json::UnknownElement root;
|
||||
json::Reader::Read(root, *stream);
|
||||
|
@ -46,15 +47,15 @@ json::UnknownElement parse(std::istream *stream) {
|
|||
}
|
||||
}
|
||||
|
||||
json::UnknownElement file(const std::string &file) {
|
||||
json::UnknownElement file(agi::fs::path const& file) {
|
||||
return parse(io::Open(file));
|
||||
}
|
||||
|
||||
json::UnknownElement file(const std::string &file, const std::string &default_config) {
|
||||
json::UnknownElement file(agi::fs::path const& file, const std::string &default_config) {
|
||||
try {
|
||||
return parse(io::Open(file));
|
||||
}
|
||||
catch (FileNotFoundError const&) {
|
||||
catch (fs::FileNotFound const&) {
|
||||
// Not an error
|
||||
return parse(new std::istringstream(default_config));
|
||||
}
|
||||
|
|
|
@ -17,16 +17,15 @@
|
|||
/// @ingroup libaegisub
|
||||
///
|
||||
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#include "libaegisub/keyframe.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
#include "libaegisub/io.h"
|
||||
#include "libaegisub/line_iterator.h"
|
||||
#include "libaegisub/keyframe.h"
|
||||
#include "libaegisub/vfr.h"
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
|
@ -77,7 +76,7 @@ char x264(std::string const& line) {
|
|||
}
|
||||
|
||||
namespace agi { namespace keyframe {
|
||||
void Save(std::string const& filename, std::vector<int> const& keyframes) {
|
||||
void Save(agi::fs::path const& filename, std::vector<int> const& keyframes) {
|
||||
io::Save file(filename);
|
||||
std::ofstream& of = file.Get();
|
||||
of << "# keyframe format v1" << std::endl;
|
||||
|
@ -85,7 +84,7 @@ void Save(std::string const& filename, std::vector<int> const& keyframes) {
|
|||
boost::copy(keyframes, std::ostream_iterator<int>(of, "\n"));
|
||||
}
|
||||
|
||||
std::vector<int> Load(std::string const& filename) {
|
||||
std::vector<int> Load(agi::fs::path const& filename) {
|
||||
std::unique_ptr<std::ifstream> file(io::Open(filename));
|
||||
std::istream &is(*file);
|
||||
|
||||
|
|
|
@ -18,21 +18,20 @@
|
|||
|
||||
#include "../config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include "libaegisub/log.h"
|
||||
|
||||
#include "libaegisub/cajun/elements.h"
|
||||
#include "libaegisub/cajun/writer.h"
|
||||
#include "libaegisub/io.h"
|
||||
#include "libaegisub/log.h"
|
||||
#include "libaegisub/types.h"
|
||||
#include "libaegisub/util.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace agi {
|
||||
namespace log {
|
||||
|
@ -109,7 +108,7 @@ Message::~Message() {
|
|||
agi::log::log->log(sm);
|
||||
}
|
||||
|
||||
JsonEmitter::JsonEmitter(std::string const& directory, const agi::log::LogSink *log_sink)
|
||||
JsonEmitter::JsonEmitter(agi::fs::path const& directory, const agi::log::LogSink *log_sink)
|
||||
: directory(directory)
|
||||
, log_sink(log_sink)
|
||||
{
|
||||
|
@ -146,9 +145,7 @@ JsonEmitter::~JsonEmitter() {
|
|||
timeval_close.push_back((int64_t)time_close.tv_sec);
|
||||
timeval_close.push_back((int64_t)time_close.tv_usec);
|
||||
|
||||
std::stringstream str;
|
||||
str << directory << time_start.tv_sec << ".json";
|
||||
json::Writer::Write(root, io::Save(str.str()).Get());
|
||||
json::Writer::Write(root, io::Save(directory/(std::to_string(time_start.tv_sec) + ".json")).Get());
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
namespace agi {
|
||||
|
||||
MRUManager::MRUManager(std::string const& config, std::string const& default_config, agi::Options *options)
|
||||
MRUManager::MRUManager(agi::fs::path const& config, std::string const& default_config, agi::Options *options)
|
||||
: config_name(config)
|
||||
, options(options)
|
||||
{
|
||||
|
@ -60,16 +60,22 @@ MRUManager::MRUListMap &MRUManager::Find(std::string const& key) {
|
|||
return index->second;
|
||||
}
|
||||
|
||||
void MRUManager::Add(std::string const& key, std::string const& entry) {
|
||||
void MRUManager::Add(std::string const& key, agi::fs::path const& entry) {
|
||||
MRUListMap &map = Find(key);
|
||||
map.remove(entry);
|
||||
map.push_front(entry);
|
||||
Prune(key, map);
|
||||
auto it = find(begin(map), end(map), entry);
|
||||
if (it == begin(map) && it != end(map))
|
||||
return;
|
||||
if (it != end(map))
|
||||
map.splice(begin(map), map, it);
|
||||
else {
|
||||
map.push_front(entry);
|
||||
Prune(key, map);
|
||||
}
|
||||
|
||||
Flush();
|
||||
}
|
||||
|
||||
void MRUManager::Remove(std::string const& key, std::string const& entry) {
|
||||
void MRUManager::Remove(std::string const& key, agi::fs::path const& entry) {
|
||||
Find(key).remove(entry);
|
||||
|
||||
Flush();
|
||||
|
@ -79,7 +85,7 @@ const MRUManager::MRUListMap* MRUManager::Get(std::string const& key) {
|
|||
return &Find(key);
|
||||
}
|
||||
|
||||
std::string const& MRUManager::GetEntry(std::string const& key, const size_t entry) {
|
||||
agi::fs::path const& MRUManager::GetEntry(std::string const& key, const size_t entry) {
|
||||
const MRUManager::MRUListMap *const map = Get(key);
|
||||
|
||||
if (entry >= map->size())
|
||||
|
@ -93,7 +99,8 @@ void MRUManager::Flush() {
|
|||
|
||||
for (auto const& mru_map : mru) {
|
||||
json::Array &array = out[mru_map.first];
|
||||
array.insert(array.end(), mru_map.second.begin(), mru_map.second.end());
|
||||
transform(begin(mru_map.second), end(mru_map.second),
|
||||
back_inserter(array), [](agi::fs::path const& p) { return p.string(); });
|
||||
}
|
||||
|
||||
json::Writer::Write(out, io::Save(config_name).Get());
|
||||
|
@ -116,7 +123,8 @@ void MRUManager::Prune(std::string const& key, MRUListMap& map) const {
|
|||
/// @param array json::Array of values.
|
||||
void MRUManager::Load(std::string const& key, const json::Array& array) {
|
||||
try {
|
||||
copy(array.begin(), array.end(), back_inserter(mru[key]));
|
||||
transform(begin(array), end(array),
|
||||
back_inserter(mru[key]), [](std::string const& s) { return s; });
|
||||
}
|
||||
catch (json::Exception const&) {
|
||||
// Out of date MRU file; just discard the data and skip it
|
||||
|
|
|
@ -20,14 +20,11 @@
|
|||
|
||||
#include "libaegisub/option.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include "libaegisub/cajun/reader.h"
|
||||
#include "libaegisub/cajun/writer.h"
|
||||
#include "libaegisub/cajun/elements.h"
|
||||
|
||||
#include "libaegisub/fs.h"
|
||||
#include "libaegisub/io.h"
|
||||
#include "libaegisub/log.h"
|
||||
#include "libaegisub/option_value.h"
|
||||
|
@ -35,6 +32,9 @@
|
|||
#include "option_visit.h"
|
||||
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
/// @brief Write an option to a json object
|
||||
|
@ -66,7 +66,7 @@ namespace {
|
|||
|
||||
namespace agi {
|
||||
|
||||
Options::Options(const std::string &file, const std::string& default_config, const OptionSetting setting)
|
||||
Options::Options(agi::fs::path const& file, const std::string& default_config, const OptionSetting setting)
|
||||
: config_file(file)
|
||||
, setting(setting)
|
||||
{
|
||||
|
@ -88,21 +88,17 @@ void Options::ConfigNext(std::istream& stream) {
|
|||
}
|
||||
|
||||
void Options::ConfigUser() {
|
||||
std::unique_ptr<std::istream> stream;
|
||||
|
||||
try {
|
||||
stream.reset(agi::io::Open(config_file));
|
||||
} catch (const FileNotFoundError&) {
|
||||
std::unique_ptr<std::istream> stream(io::Open(config_file));
|
||||
LoadConfig(*stream, true);
|
||||
}
|
||||
catch (fs::FileNotFound const&) {
|
||||
return;
|
||||
}
|
||||
|
||||
/// @todo Handle other errors such as parsing and notifying the user.
|
||||
LoadConfig(*stream, true);
|
||||
}
|
||||
|
||||
void Options::LoadConfig(std::istream& stream, bool ignore_errors) {
|
||||
/// @todo Store all previously loaded configs in an array for bug report purposes,
|
||||
/// this is just a temp stub.
|
||||
json::UnknownElement config_root;
|
||||
|
||||
try {
|
||||
|
|
150
aegisub/libaegisub/common/path.cpp
Normal file
150
aegisub/libaegisub/common/path.cpp
Normal file
|
@ -0,0 +1,150 @@
|
|||
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
// Aegisub Project http://www.aegisub.org/
|
||||
|
||||
/// @file path.cpp
|
||||
/// @brief Platform-independent path code
|
||||
/// @ingroup libaegisub
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#include "libaegisub/path.h"
|
||||
|
||||
#include "libaegisub/fs.h"
|
||||
#include "libaegisub/util.h"
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/range/distance.hpp>
|
||||
|
||||
namespace {
|
||||
template<class T, class U>
|
||||
typename T::const_iterator last_less_than(T const& cont, U const& value) {
|
||||
auto it = cont.upper_bound(value);
|
||||
if (it != cont.begin())
|
||||
--it;
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
namespace agi {
|
||||
|
||||
Path::Path() {
|
||||
tokens["?user"];
|
||||
tokens["?local"];
|
||||
tokens["?data"];
|
||||
tokens["?temp"];
|
||||
tokens["?dictionary"];
|
||||
tokens["?docs"];
|
||||
|
||||
FillPlatformSpecificPaths();
|
||||
|
||||
tokens["?audio"];
|
||||
tokens["?script"];
|
||||
tokens["?video"];
|
||||
}
|
||||
|
||||
fs::path Path::Decode(std::string const& path) const {
|
||||
const auto it = last_less_than(tokens, path);
|
||||
|
||||
if (!it->second.empty() && boost::starts_with(path, it->first))
|
||||
return (it->second/path.substr(it->first.size())).make_preferred();
|
||||
return fs::path(path).make_preferred();
|
||||
}
|
||||
|
||||
fs::path Path::MakeRelative(fs::path const& path, std::string const& token) const {
|
||||
const auto it = tokens.find(token);
|
||||
if (it == tokens.end()) throw agi::InternalError("Bad token: " + token, 0);
|
||||
|
||||
return MakeRelative(path, it->second);
|
||||
}
|
||||
|
||||
fs::path Path::MakeRelative(fs::path const& path, fs::path const& base) const {
|
||||
if (path.empty() || base.empty()) return path;
|
||||
|
||||
const auto str = path.string();
|
||||
if (boost::starts_with(str, "?dummy") || boost::starts_with(str, "dummy-audio:"))
|
||||
return path;
|
||||
|
||||
// Paths on different volumes can't be made relative to each other
|
||||
if (path.has_root_name() && path.root_name() != base.root_name())
|
||||
return path.string();
|
||||
|
||||
auto path_it = path.begin();
|
||||
auto ref_it = base.begin();
|
||||
for (; path_it != path.end() && ref_it != base.end() && *path_it == *ref_it; ++path_it, ++ref_it) ;
|
||||
|
||||
agi::fs::path result;
|
||||
for (; ref_it != base.end(); ++ref_it)
|
||||
result /= "..";
|
||||
for (; path_it != path.end(); ++path_it)
|
||||
result /= *path_it;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fs::path Path::MakeAbsolute(fs::path path, std::string const& token) const {
|
||||
const auto it = tokens.find(token);
|
||||
if (it == tokens.end()) throw agi::InternalError("Bad token: " + token, 0);
|
||||
if (path.empty()) return path;
|
||||
|
||||
path.make_preferred();
|
||||
const auto str = path.string();
|
||||
if (boost::starts_with(str, "?dummy") || boost::starts_with(str, "dummy-audio:"))
|
||||
return path;
|
||||
return (it->second.empty() || path.is_absolute()) ? path : it->second/path;
|
||||
}
|
||||
|
||||
std::string Path::Encode(fs::path const& path) const {
|
||||
// Find the shortest encoding of path made relative to each token
|
||||
std::string shortest = path.string();
|
||||
size_t length = boost::distance(path);
|
||||
for (auto const& tok : tokens) {
|
||||
if (tok.second.empty()) continue;
|
||||
|
||||
const auto p = MakeRelative(path, tok.first);
|
||||
const size_t d = boost::distance(p);
|
||||
if (d < length) {
|
||||
length = d;
|
||||
shortest = (tok.first/p).string();
|
||||
}
|
||||
}
|
||||
|
||||
return shortest;
|
||||
}
|
||||
|
||||
void Path::SetToken(std::string const& token_name, fs::path const& token_value) {
|
||||
const auto it = tokens.find(token_name);
|
||||
if (it == tokens.end()) throw agi::InternalError("Bad token: " + token_name, 0);
|
||||
|
||||
if (token_value.empty())
|
||||
it->second = token_value;
|
||||
else if (!token_value.is_absolute())
|
||||
it->second.clear();
|
||||
else {
|
||||
it->second = token_value;
|
||||
it->second.make_preferred();
|
||||
if (fs::FileExists(it->second))
|
||||
it->second = it->second.parent_path();
|
||||
}
|
||||
|
||||
paths.clear();
|
||||
for (auto const& tok : tokens) {
|
||||
if (!tok.second.empty())
|
||||
paths[tok.second] = tok.first;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -26,16 +26,16 @@
|
|||
#include <boost/phoenix/operator/comparison.hpp>
|
||||
#include <boost/phoenix/core/argument.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
|
||||
using boost::phoenix::placeholders::_1;
|
||||
|
||||
namespace agi {
|
||||
|
||||
Thesaurus::Thesaurus(std::string const& dat_path, std::string const& idx_path)
|
||||
Thesaurus::Thesaurus(agi::fs::path const& dat_path, agi::fs::path const& idx_path)
|
||||
: dat(io::Open(dat_path))
|
||||
{
|
||||
scoped_ptr<std::ifstream> idx(io::Open(idx_path));
|
||||
std::unique_ptr<std::ifstream> idx(io::Open(idx_path));
|
||||
|
||||
std::string encoding_name;
|
||||
getline(*idx, encoding_name);
|
||||
|
|