Use C++11 stuff in libaegisub
This commit is contained in:
parent
653aa32eb2
commit
2dd1da8333
15 changed files with 147 additions and 223 deletions
|
@ -22,13 +22,11 @@ namespace agi {
|
|||
namespace charset {
|
||||
|
||||
std::string Detect(const std::string &file) {
|
||||
UCDetect ucd(file);
|
||||
return ucd.Single();
|
||||
return UCDetect(file).Single();
|
||||
}
|
||||
|
||||
void DetectAll(const std::string& file, CharsetListDetected &list) {
|
||||
UCDetect ucd(file);
|
||||
ucd.List(list);
|
||||
UCDetect(file).List(list);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include <iconv.h>
|
||||
|
||||
#include <boost/range/algorithm.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
// ISO-6937-2 values for the first 383 codepoints
|
||||
|
@ -160,9 +162,8 @@ int get_iso6937(int codepoint) {
|
|||
if (static_cast<size_t>(codepoint) < countof(iso6937_codepoints))
|
||||
return iso6937_codepoints[codepoint];
|
||||
|
||||
const extended_range *end = iso6937_extended_codepoints + countof(iso6937_extended_codepoints);
|
||||
const extended_range *ext = std::lower_bound(iso6937_extended_codepoints, end, codepoint);
|
||||
if (ext == end || ext->codepoint != codepoint)
|
||||
auto ext = boost::lower_bound(iso6937_extended_codepoints, codepoint);
|
||||
if (ext == std::end(iso6937_extended_codepoints) || ext->codepoint != codepoint)
|
||||
return 0;
|
||||
return ext->value;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace {
|
|||
# undef ADD
|
||||
}
|
||||
|
||||
std::map<const char*, const char*, ltstr>::iterator real = pretty_names.find(name);
|
||||
auto real = pretty_names.find(name);
|
||||
if (real != pretty_names.end())
|
||||
return real->second;
|
||||
return name;
|
||||
|
@ -146,16 +146,14 @@ namespace {
|
|||
{
|
||||
const char *dstEnc = get_real_encoding_name(destEncoding);
|
||||
cd = iconv_open(dstEnc, "UTF-8");
|
||||
if (cd == iconv_invalid) {
|
||||
if (cd == iconv_invalid)
|
||||
throw agi::charset::UnsupportedConversion(std::string(dstEnc) + " is not a supported character set");
|
||||
}
|
||||
|
||||
bomSize = get_bom_size(cd);
|
||||
iconv_close(cd);
|
||||
cd = iconv_open(dstEnc, get_real_encoding_name(sourceEncoding));
|
||||
if (cd == iconv_invalid) {
|
||||
if (cd == iconv_invalid)
|
||||
throw agi::charset::UnsupportedConversion(std::string("Cannot convert from ") + sourceEncoding + " to " + destEncoding);
|
||||
}
|
||||
}
|
||||
~ConverterImpl() {
|
||||
if (cd != iconv_invalid) iconv_close(cd);
|
||||
|
@ -232,10 +230,10 @@ namespace {
|
|||
|
||||
if (subst) {
|
||||
data = this;
|
||||
mb_to_uc_fallback = NULL;
|
||||
mb_to_wc_fallback = NULL;
|
||||
mb_to_uc_fallback = nullptr;
|
||||
mb_to_wc_fallback = nullptr;
|
||||
uc_to_mb_fallback = fallback;
|
||||
wc_to_mb_fallback = NULL;
|
||||
wc_to_mb_fallback = nullptr;
|
||||
|
||||
int transliterate = 1;
|
||||
iconvctl(cd, ICONV_SET_TRANSLITERATE, &transliterate);
|
||||
|
@ -316,7 +314,7 @@ void IconvWrapper::Convert(std::string const& source, std::string &dest) {
|
|||
char *dst = buff;
|
||||
size_t dstLen = sizeof(buff);
|
||||
res = conv->Convert(&src, &srcLen, &dst, &dstLen);
|
||||
if (res == 0) conv->Convert(NULL, NULL, &dst, &dstLen);
|
||||
if (res == 0) conv->Convert(nullptr, nullptr, &dst, &dstLen);
|
||||
|
||||
dest.append(buff, sizeof(buff) - dstLen);
|
||||
} while (res == iconv_failed && errno == E2BIG);
|
||||
|
@ -341,13 +339,11 @@ void IconvWrapper::Convert(std::string const& source, std::string &dest) {
|
|||
}
|
||||
|
||||
size_t IconvWrapper::Convert(const char* source, size_t sourceSize, char *dest, size_t destSize) {
|
||||
if (sourceSize == (size_t)-1) {
|
||||
if (sourceSize == (size_t)-1)
|
||||
sourceSize = SrcStrLen(source);
|
||||
}
|
||||
|
||||
|
||||
size_t res = conv->Convert(&source, &sourceSize, &dest, &destSize);
|
||||
if (res == 0) res = conv->Convert(NULL, NULL, &dest, &destSize);
|
||||
if (res == 0) res = conv->Convert(nullptr, nullptr, &dest, &destSize);
|
||||
|
||||
if (res == iconv_failed) {
|
||||
switch (errno) {
|
||||
|
@ -390,7 +386,7 @@ size_t IconvWrapper::RequiredBufferSize(const char* src, size_t srcLen) {
|
|||
char* dst = buff;
|
||||
size_t dstSize = sizeof(buff);
|
||||
res = conv->Convert(&src, &srcLen, &dst, &dstSize);
|
||||
conv->Convert(NULL, NULL, &dst, &dstSize);
|
||||
conv->Convert(nullptr, nullptr, &dst, &dstSize);
|
||||
|
||||
charsWritten += dst - buff;
|
||||
} while (res == iconv_failed && errno == E2BIG);
|
||||
|
|
|
@ -33,18 +33,14 @@
|
|||
#include "libaegisub/json.h"
|
||||
#include "libaegisub/log.h"
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
|
||||
namespace agi {
|
||||
namespace hotkey {
|
||||
|
||||
std::string Combo::Str() const {
|
||||
if (key_map.empty()) return "";
|
||||
|
||||
std::string str(key_map[0]);
|
||||
str.reserve(str.size() + (key_map.size() - 1) * 2);
|
||||
for (unsigned int i=1; i < key_map.size(); i++) {
|
||||
str.append("-" + key_map[i]);
|
||||
}
|
||||
return str;
|
||||
return boost::algorithm::join(key_map, "-");
|
||||
}
|
||||
|
||||
std::string Combo::StrMenu() const {
|
||||
|
@ -52,8 +48,8 @@ std::string Combo::StrMenu() const {
|
|||
}
|
||||
|
||||
void Hotkey::ComboInsert(Combo const& combo) {
|
||||
str_map.insert(std::make_pair(combo.Str(), combo));
|
||||
cmd_map.insert(std::make_pair(combo.CmdName(), combo));
|
||||
str_map.insert(make_pair(combo.Str(), combo));
|
||||
cmd_map.insert(make_pair(combo.CmdName(), combo));
|
||||
}
|
||||
|
||||
Hotkey::Hotkey(const std::string &file, const std::string &default_config)
|
||||
|
@ -62,29 +58,28 @@ Hotkey::Hotkey(const std::string &file, const std::string &default_config)
|
|||
LOG_D("hotkey/init") << "Generating hotkeys.";
|
||||
|
||||
json::Object object(agi::json_util::file(config_file, default_config));
|
||||
for (json::Object::const_iterator index(object.begin()); index != object.end(); ++index)
|
||||
BuildHotkey(index->first, index->second);
|
||||
for (auto const& hotkey_context : object)
|
||||
BuildHotkey(hotkey_context.first, hotkey_context.second);
|
||||
}
|
||||
|
||||
void Hotkey::BuildHotkey(std::string const& context, json::Object const& hotkeys) {
|
||||
for (auto const& command : hotkeys) {
|
||||
const json::Array& command_hotkeys = command.second;
|
||||
|
||||
void Hotkey::BuildHotkey(std::string const& context, const json::Object& object) {
|
||||
for (json::Object::const_iterator index(object.begin()); index != object.end(); ++index) {
|
||||
const json::Array& array = index->second;
|
||||
|
||||
for (json::Array::const_iterator arr_index(array.begin()); arr_index != array.end(); ++arr_index) {
|
||||
for (auto const& hotkey : command_hotkeys) {
|
||||
std::vector<std::string> keys;
|
||||
|
||||
try {
|
||||
const json::Array& arr_mod = (*arr_index)["modifiers"];
|
||||
const json::Array& arr_mod = hotkey["modifiers"];
|
||||
keys.reserve(arr_mod.size() + 1);
|
||||
copy(arr_mod.begin(), arr_mod.end(), back_inserter(keys));
|
||||
keys.push_back((*arr_index)["key"]);
|
||||
keys.push_back(hotkey["key"]);
|
||||
}
|
||||
catch (json::Exception const& e) {
|
||||
LOG_E("agi/hotkey/load") << "Failed loading hotkey for command '" << index->first << "': " << e.what();
|
||||
LOG_E("agi/hotkey/load") << "Failed loading hotkey for command '" << command.first << "': " << e.what();
|
||||
}
|
||||
|
||||
ComboInsert(Combo(context, index->first, keys));
|
||||
ComboInsert(Combo(context, command.first, keys));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,18 +146,16 @@ std::string Hotkey::GetHotkey(const std::string &context, const std::string &com
|
|||
void Hotkey::Flush() {
|
||||
json::Object root;
|
||||
|
||||
for (HotkeyMap::iterator index = str_map.begin(); index != str_map.end(); ++index) {
|
||||
std::vector<std::string> const& combo_map(index->second.Get());
|
||||
|
||||
for (auto const& combo : str_map | boost::adaptors::map_values) {
|
||||
json::Object hotkey;
|
||||
if (combo_map.size()) {
|
||||
hotkey["key"] = combo_map.back();
|
||||
if (combo.Get().size()) {
|
||||
hotkey["key"] = combo.Get().back();
|
||||
json::Array& modifiers = hotkey["modifiers"];
|
||||
copy(combo_map.begin(), combo_map.end() - 1, std::back_inserter(modifiers));
|
||||
modifiers.insert(modifiers.end(), combo.Get().begin(), combo.Get().end() - 1);
|
||||
}
|
||||
|
||||
json::Array& combo_array = root[index->second.Context()][index->second.CmdName()];
|
||||
combo_array.push_back(hotkey);
|
||||
json::Array& combo_array = root[combo.Context()][combo.CmdName()];
|
||||
combo_array.push_back(std::move(hotkey));
|
||||
}
|
||||
|
||||
io::Save file(config_file);
|
||||
|
@ -173,8 +166,8 @@ void Hotkey::SetHotkeyMap(HotkeyMap const& new_map) {
|
|||
cmd_map = new_map;
|
||||
|
||||
str_map.clear();
|
||||
for (HotkeyMap::iterator it = cmd_map.begin(); it != cmd_map.end(); ++it)
|
||||
str_map.insert(make_pair(it->second.Str(), it->second));
|
||||
for (auto const& combo : cmd_map | boost::adaptors::map_values)
|
||||
str_map.insert(make_pair(combo.Str(), combo));
|
||||
|
||||
Flush();
|
||||
HotkeysChanged();
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#include "libaegisub/keyframe.h"
|
||||
#include "libaegisub/vfr.h"
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
|
||||
namespace {
|
||||
std::vector<int> agi_keyframes(std::istream &file) {
|
||||
double fps;
|
||||
|
@ -37,9 +40,7 @@ std::vector<int> agi_keyframes(std::istream &file) {
|
|||
file >> fps_str;
|
||||
file >> fps;
|
||||
|
||||
std::vector<int> ret;
|
||||
copy(std::istream_iterator<int>(file), std::istream_iterator<int>(), back_inserter(ret));
|
||||
return ret;
|
||||
return std::vector<int>(std::istream_iterator<int>(file), std::istream_iterator<int>());
|
||||
}
|
||||
|
||||
std::vector<int> other_keyframes(std::istream &file, char (*func)(std::string const&)) {
|
||||
|
@ -48,12 +49,10 @@ std::vector<int> other_keyframes(std::istream &file, char (*func)(std::string co
|
|||
agi::line_iterator<std::string> end;
|
||||
for (agi::line_iterator<std::string> iter(file); iter != end; ++iter) {
|
||||
char c = tolower(func(*iter));
|
||||
if (c == 'i') {
|
||||
if (c == 'i')
|
||||
ret.push_back(count++);
|
||||
}
|
||||
else if (c == 'p' || c == 'b') {
|
||||
else if (c == 'p' || c == 'b')
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -77,34 +76,28 @@ char x264(std::string const& line) {
|
|||
if (pos == line.npos || pos + 5 >= line.size()) return 0;
|
||||
return line[pos + 5];
|
||||
}
|
||||
|
||||
template<int N>
|
||||
bool starts_with(std::string const& str, const char (&test)[N]) {
|
||||
if (str.size() < N) return false;
|
||||
return std::mismatch(str.begin(), str.begin() + N - 1, test).first == str.begin() + N - 1;
|
||||
}
|
||||
}
|
||||
|
||||
namespace agi { namespace keyframe {
|
||||
void Save(std::string const& filename, std::vector<int> const& keyframes) {
|
||||
void Save(std::string const& filename, std::vector<int> const& keyframes) {
|
||||
io::Save file(filename);
|
||||
std::ofstream& of = file.Get();
|
||||
of << "# keyframe format v1" << std::endl;
|
||||
of << "fps " << 0 << std::endl;
|
||||
copy(keyframes.begin(), keyframes.end(), std::ostream_iterator<int>(of, "\n"));
|
||||
boost::copy(keyframes, std::ostream_iterator<int>(of, "\n"));
|
||||
}
|
||||
|
||||
std::vector<int> Load(std::string const& filename) {
|
||||
std::auto_ptr<std::ifstream> file(io::Open(filename));
|
||||
std::istream &is(*file.get());
|
||||
std::unique_ptr<std::ifstream> file(io::Open(filename));
|
||||
std::istream &is(*file);
|
||||
|
||||
std::string header;
|
||||
std::getline(is, header);
|
||||
getline(is, header);
|
||||
|
||||
if (header == "# keyframe format v1") return agi_keyframes(is);
|
||||
if (starts_with(header, "# XviD 2pass stat file")) return other_keyframes(is, xvid);
|
||||
if (starts_with(header, "##map version")) return other_keyframes(is, divx);
|
||||
if (starts_with(header, "#options:")) return other_keyframes(is, x264);
|
||||
if (boost::starts_with(header, "# XviD 2pass stat file")) return other_keyframes(is, xvid);
|
||||
if (boost::starts_with(header, "##map version")) return other_keyframes(is, divx);
|
||||
if (boost::starts_with(header, "#options:")) return other_keyframes(is, x264);
|
||||
|
||||
throw Error("Unknown keyframe format");
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "libaegisub/types.h"
|
||||
#include "libaegisub/util.h"
|
||||
|
||||
#include <boost/range/algorithm.hpp>
|
||||
|
||||
namespace agi {
|
||||
namespace log {
|
||||
|
||||
|
@ -53,7 +55,7 @@ SinkMessage::SinkMessage(const char *section, Severity severity,
|
|||
, func(func)
|
||||
, line(line)
|
||||
, tv(tv)
|
||||
, message(NULL)
|
||||
, message(nullptr)
|
||||
, len(0)
|
||||
{
|
||||
}
|
||||
|
@ -75,11 +77,7 @@ LogSink::~LogSink() {
|
|||
|
||||
void LogSink::log(SinkMessage *sm) {
|
||||
sink.push_back(sm);
|
||||
|
||||
for_each(
|
||||
emitters.begin(),
|
||||
emitters.end(),
|
||||
bind2nd(std::mem_fun(&Emitter::log), sm));
|
||||
boost::for_each(emitters, [=](Emitter *em) { em->log(sm); });
|
||||
}
|
||||
|
||||
void LogSink::Subscribe(Emitter *em) {
|
||||
|
@ -139,7 +137,7 @@ JsonEmitter::~JsonEmitter() {
|
|||
entry["line"] = sink[i]->line;
|
||||
entry["message"] = std::string(sink[i]->message, sink[i]->len);
|
||||
|
||||
array.push_back(entry);
|
||||
array.push_back(std::move(entry));
|
||||
}
|
||||
|
||||
json::Array &timeval_open = root["timeval"]["open"];
|
||||
|
|
|
@ -46,8 +46,8 @@ MRUManager::MRUManager(std::string const& config, std::string const& default_con
|
|||
LOG_D("agi/mru") << "Loading MRU List";
|
||||
|
||||
json::Object root(json_util::file(config, default_config));
|
||||
for (json::Object::const_iterator it(root.begin()); it != root.end(); ++it)
|
||||
Load(it->first, it->second);
|
||||
for (auto const& it : root)
|
||||
Load(it.first, it.second);
|
||||
}
|
||||
|
||||
MRUManager::~MRUManager() {
|
||||
|
@ -93,9 +93,9 @@ std::string const& MRUManager::GetEntry(std::string const& key, const size_t ent
|
|||
void MRUManager::Flush() {
|
||||
json::Object out;
|
||||
|
||||
for (MRUMap::const_iterator i = mru.begin(); i != mru.end(); ++i) {
|
||||
json::Array &array = out[i->first];
|
||||
copy(i->second.begin(), i->second.end(), std::back_inserter(array));
|
||||
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());
|
||||
}
|
||||
|
||||
json::Writer::Write(out, io::Save(config_name).Get());
|
||||
|
@ -106,7 +106,7 @@ void MRUManager::Flush() {
|
|||
void MRUManager::Prune(std::string const& key, MRUListMap& map) const {
|
||||
size_t limit = 16u;
|
||||
if (options) {
|
||||
std::map<const std::string, std::string>::const_iterator it = option_names.find(key);
|
||||
auto it = option_names.find(key);
|
||||
if (it != option_names.end())
|
||||
limit = (size_t)options->Get(it->second)->GetInt();
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include "option_visit.h"
|
||||
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
|
||||
namespace {
|
||||
/// @brief Write an option to a json object
|
||||
/// @param[out] obj Parent object
|
||||
|
@ -50,12 +52,8 @@ namespace {
|
|||
assert(obj.find(path) == obj.end());
|
||||
obj[path] = value;
|
||||
}
|
||||
else {
|
||||
put_option(
|
||||
obj[path.substr(0, pos)],
|
||||
path.substr(pos + 1),
|
||||
value);
|
||||
}
|
||||
else
|
||||
put_option(obj[path.substr(0, pos)], path.substr(pos + 1), value);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
@ -80,13 +78,11 @@ Options::Options(const std::string &file, const std::string& default_config, con
|
|||
}
|
||||
|
||||
Options::~Options() {
|
||||
if ((setting & FLUSH_SKIP) != FLUSH_SKIP) {
|
||||
if ((setting & FLUSH_SKIP) != FLUSH_SKIP)
|
||||
Flush();
|
||||
}
|
||||
|
||||
for (OptionValueMap::iterator i = values.begin(); i != values.end(); i++) {
|
||||
delete i->second;
|
||||
}
|
||||
for (auto option_value : values | boost::adaptors::map_values)
|
||||
delete option_value;
|
||||
}
|
||||
|
||||
void Options::ConfigNext(std::istream& stream) {
|
||||
|
@ -94,7 +90,7 @@ void Options::ConfigNext(std::istream& stream) {
|
|||
}
|
||||
|
||||
void Options::ConfigUser() {
|
||||
std::auto_ptr<std::istream> stream;
|
||||
std::unique_ptr<std::istream> stream;
|
||||
|
||||
try {
|
||||
stream.reset(agi::io::Open(config_file));
|
||||
|
@ -125,9 +121,8 @@ void Options::LoadConfig(std::istream& stream, bool ignore_errors) {
|
|||
}
|
||||
|
||||
OptionValue* Options::Get(const std::string &name) {
|
||||
OptionValueMap::iterator index;
|
||||
|
||||
if ((index = values.find(name)) != values.end())
|
||||
auto index = values.find(name);
|
||||
if (index != values.end())
|
||||
return index->second;
|
||||
|
||||
LOG_E("option/get") << "agi::Options::Get Option not found: (" << name << ")";
|
||||
|
@ -137,46 +132,46 @@ OptionValue* Options::Get(const std::string &name) {
|
|||
void Options::Flush() {
|
||||
json::Object obj_out;
|
||||
|
||||
for (OptionValueMap::const_iterator i = values.begin(); i != values.end(); ++i) {
|
||||
switch (i->second->GetType()) {
|
||||
for (auto const& ov : values) {
|
||||
switch (ov.second->GetType()) {
|
||||
case OptionValue::Type_String:
|
||||
put_option(obj_out, i->first, i->second->GetString());
|
||||
put_option(obj_out, ov.first, ov.second->GetString());
|
||||
break;
|
||||
|
||||
case OptionValue::Type_Int:
|
||||
put_option(obj_out, i->first, i->second->GetInt());
|
||||
put_option(obj_out, ov.first, ov.second->GetInt());
|
||||
break;
|
||||
|
||||
case OptionValue::Type_Double:
|
||||
put_option(obj_out, i->first, i->second->GetDouble());
|
||||
put_option(obj_out, ov.first, ov.second->GetDouble());
|
||||
break;
|
||||
|
||||
case OptionValue::Type_Color:
|
||||
put_option(obj_out, i->first, i->second->GetColor().GetRgbFormatted());
|
||||
put_option(obj_out, ov.first, ov.second->GetColor().GetRgbFormatted());
|
||||
break;
|
||||
|
||||
case OptionValue::Type_Bool:
|
||||
put_option(obj_out, i->first, i->second->GetBool());
|
||||
put_option(obj_out, ov.first, ov.second->GetBool());
|
||||
break;
|
||||
|
||||
case OptionValue::Type_List_String:
|
||||
put_array(obj_out, i->first, "string", i->second->GetListString());
|
||||
put_array(obj_out, ov.first, "string", ov.second->GetListString());
|
||||
break;
|
||||
|
||||
case OptionValue::Type_List_Int:
|
||||
put_array(obj_out, i->first, "int", i->second->GetListInt());
|
||||
put_array(obj_out, ov.first, "int", ov.second->GetListInt());
|
||||
break;
|
||||
|
||||
case OptionValue::Type_List_Double:
|
||||
put_array(obj_out, i->first, "double", i->second->GetListDouble());
|
||||
put_array(obj_out, ov.first, "double", ov.second->GetListDouble());
|
||||
break;
|
||||
|
||||
case OptionValue::Type_List_Color:
|
||||
put_array(obj_out, i->first, "color", i->second->GetListColor());
|
||||
put_array(obj_out, ov.first, "color", ov.second->GetListColor());
|
||||
break;
|
||||
|
||||
case OptionValue::Type_List_Bool:
|
||||
put_array(obj_out, i->first, "bool", i->second->GetListBool());
|
||||
put_array(obj_out, ov.first, "bool", ov.second->GetListBool());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,14 +50,12 @@ void ConfigVisitor::Error(const char *message) {
|
|||
}
|
||||
|
||||
void ConfigVisitor::Visit(const json::Object& object) {
|
||||
json::Object::const_iterator index(object.begin()), index_end(object.end());
|
||||
|
||||
if (!name.empty())
|
||||
name += "/";
|
||||
|
||||
for (; index != index_end; ++index) {
|
||||
ConfigVisitor config_visitor(values, name + index->first, ignore_errors, replace);
|
||||
index->second.Accept(config_visitor);
|
||||
for (auto const& obj : object) {
|
||||
ConfigVisitor config_visitor(values, name + obj.first, ignore_errors, replace);
|
||||
obj.second.Accept(config_visitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,9 +64,7 @@ OptionValue *ConfigVisitor::ReadArray(json::Array const& src, std::string const&
|
|||
std::vector<ValueType> arr;
|
||||
arr.reserve(src.size());
|
||||
|
||||
for (json::Array::const_iterator it = src.begin(); it != src.end(); ++it) {
|
||||
json::Object const& obj = *it;
|
||||
|
||||
for (json::Object const& obj : src) {
|
||||
if (obj.size() != 1) {
|
||||
Error<OptionJsonValueArray>("Invalid array member");
|
||||
return 0;
|
||||
|
|
|
@ -22,22 +22,15 @@
|
|||
#include "libaegisub/io.h"
|
||||
#include "libaegisub/line_iterator.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/phoenix/operator/comparison.hpp>
|
||||
#include <boost/phoenix/core/argument.hpp>
|
||||
|
||||
#ifndef LAGI_PRE
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
template<class String, class Char, class Container>
|
||||
static void split(String const& str, Char sep, Container *out) {
|
||||
typename String::size_type pos, prev = 0;
|
||||
out->reserve(2);
|
||||
while ((pos = str.find(sep, prev)) != String::npos) {
|
||||
if (pos > prev)
|
||||
out->push_back(str.substr(prev, pos - prev));
|
||||
prev = pos + 1;
|
||||
}
|
||||
if (prev < str.size())
|
||||
out->push_back(str.substr(prev));
|
||||
}
|
||||
using boost::phoenix::placeholders::_1;
|
||||
|
||||
namespace agi {
|
||||
|
||||
|
@ -54,10 +47,9 @@ Thesaurus::Thesaurus(std::string const& dat_path, std::string const& idx_path)
|
|||
// Read the list of words and file offsets for those words
|
||||
for (line_iterator<std::string> iter(*idx, encoding_name), end; iter != end; ++iter) {
|
||||
std::vector<std::string> chunks;
|
||||
split(*iter, '|', &chunks);
|
||||
if (chunks.size() == 2) {
|
||||
boost::split(chunks, *iter, _1 == '|');
|
||||
if (chunks.size() == 2)
|
||||
offsets[chunks[0]] = atoi(chunks[1].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
conv.reset(new charset::IconvWrapper(encoding_name.c_str(), "utf-8"));
|
||||
|
@ -67,9 +59,10 @@ Thesaurus::~Thesaurus() { }
|
|||
|
||||
void Thesaurus::Lookup(std::string const& word, std::vector<Entry> *out) {
|
||||
out->clear();
|
||||
if (!dat.get()) return;
|
||||
|
||||
std::map<std::string, int>::const_iterator it = offsets.find(word);
|
||||
if (!dat.get() || it == offsets.end()) return;
|
||||
if (it == offsets.end()) return;
|
||||
|
||||
dat->seekg(it->second, std::ios::beg);
|
||||
if (!dat->good()) return;
|
||||
|
@ -78,7 +71,7 @@ void Thesaurus::Lookup(std::string const& word, std::vector<Entry> *out) {
|
|||
std::string temp;
|
||||
getline(*dat, temp);
|
||||
std::vector<std::string> header;
|
||||
split(conv->Convert(temp), '|', &header);
|
||||
boost::split(header, conv->Convert(temp), _1 == '|');
|
||||
if (header.size() != 2) return;
|
||||
int meanings = atoi(header[1].c_str());
|
||||
|
||||
|
@ -86,7 +79,7 @@ void Thesaurus::Lookup(std::string const& word, std::vector<Entry> *out) {
|
|||
for (int i = 0; i < meanings; ++i) {
|
||||
std::vector<std::string> line;
|
||||
getline(*dat, temp);
|
||||
split(conv->Convert(temp), '|', &line);
|
||||
boost::split(line, conv->Convert(temp), _1 == '|');
|
||||
|
||||
// The "definition" is just the part of speech plus the word it's
|
||||
// giving synonyms for (which may not be the passed word)
|
||||
|
|
|
@ -24,24 +24,20 @@
|
|||
#include <locale>
|
||||
#endif
|
||||
|
||||
|
||||
#include "libaegisub/util.h"
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
namespace agi {
|
||||
namespace util {
|
||||
|
||||
|
||||
void str_lower(std::string &str) {
|
||||
std::locale loc;
|
||||
for (size_t i=0; i < str.length(); ++i) {
|
||||
str[i] = std::tolower(str[i], loc);
|
||||
}
|
||||
boost::to_lower(str);
|
||||
}
|
||||
|
||||
|
||||
int strtoi(std::string &str) {
|
||||
errno = 0;
|
||||
long l = strtol(str.c_str(), NULL, 10);
|
||||
long l = strtol(str.c_str(), nullptr, 10);
|
||||
|
||||
if ((errno == ERANGE) || (l < INT_MIN) || (l > INT_MAX))
|
||||
return 0;
|
||||
|
@ -49,6 +45,5 @@ int strtoi(std::string &str) {
|
|||
return (int)l;
|
||||
}
|
||||
|
||||
|
||||
} // namespace util
|
||||
} // namespace agi
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "libaegisub/line_iterator.h"
|
||||
#include "libaegisub/scoped_ptr.h"
|
||||
|
||||
#include <boost/range/algorithm.hpp>
|
||||
|
||||
namespace std {
|
||||
template<> void swap(agi::vfr::Framerate &lft, agi::vfr::Framerate &rgt) {
|
||||
lft.swap(rgt);
|
||||
|
@ -43,27 +45,20 @@ static const int64_t default_denominator = 1000000000;
|
|||
namespace agi {
|
||||
namespace vfr {
|
||||
|
||||
static int is_increasing(int prev, int cur) {
|
||||
if (prev > cur)
|
||||
throw UnorderedTimecodes("Timecodes are out of order");
|
||||
return cur;
|
||||
}
|
||||
|
||||
/// @brief Verify that timecodes monotonically increase
|
||||
/// @param timecodes List of timecodes to check
|
||||
static void validate_timecodes(std::vector<int> const& timecodes) {
|
||||
if (timecodes.size() <= 1) {
|
||||
if (timecodes.size() <= 1)
|
||||
throw TooFewTimecodes("Must have at least two timecodes to do anything useful");
|
||||
}
|
||||
std::accumulate(timecodes.begin()+1, timecodes.end(), timecodes.front(), is_increasing);
|
||||
if (!is_sorted(timecodes.begin(), timecodes.end()))
|
||||
throw UnorderedTimecodes("Timecodes are out of order");
|
||||
}
|
||||
|
||||
/// @brief Shift timecodes so that frame 0 starts at time 0
|
||||
/// @param timecodes List of timecodes to normalize
|
||||
static void normalize_timecodes(std::vector<int> &timecodes) {
|
||||
if (int front = timecodes.front()) {
|
||||
std::transform(timecodes.begin(), timecodes.end(), timecodes.begin(), std::bind2nd(std::minus<int>(), front));
|
||||
}
|
||||
if (int front = timecodes.front())
|
||||
boost::for_each(timecodes, [=](int &tc) { tc -= front; });
|
||||
}
|
||||
|
||||
// A "start,end,fps" line in a v1 timecode file
|
||||
|
@ -74,7 +69,8 @@ struct TimecodeRange {
|
|||
bool operator<(TimecodeRange const& cmp) const {
|
||||
return start < cmp.start;
|
||||
}
|
||||
TimecodeRange() : fps(0.) { }
|
||||
TimecodeRange(int start=0, int end=0, double fps=0.)
|
||||
: start(start), end(end), fps(fps) { }
|
||||
};
|
||||
|
||||
/// @brief Parse a single line of a v1 timecode file
|
||||
|
@ -87,57 +83,38 @@ static TimecodeRange v1_parse_line(std::string const& str) {
|
|||
TimecodeRange range;
|
||||
char comma1, comma2;
|
||||
ss >> range.start >> comma1 >> range.end >> comma2 >> range.fps;
|
||||
if (ss.fail() || comma1 != ',' || comma2 != ',' || !ss.eof()) {
|
||||
if (ss.fail() || comma1 != ',' || comma2 != ',' || !ss.eof())
|
||||
throw MalformedLine(str);
|
||||
}
|
||||
if (range.start < 0 || range.end < 0) {
|
||||
if (range.start < 0 || range.end < 0)
|
||||
throw UnorderedTimecodes("Cannot specify frame rate for negative frames.");
|
||||
}
|
||||
if (range.end < range.start) {
|
||||
if (range.end < range.start)
|
||||
throw UnorderedTimecodes("End frame must be greater than or equal to start frame");
|
||||
}
|
||||
if (range.fps <= 0.) {
|
||||
if (range.fps <= 0.)
|
||||
throw BadFPS("FPS must be greater than zero");
|
||||
}
|
||||
if (range.fps > 1000.) {
|
||||
if (range.fps > 1000.)
|
||||
// This is our limitation, not mkvmerge's
|
||||
// mkvmerge uses nanoseconds internally
|
||||
throw BadFPS("FPS must be at most 1000");
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
/// @brief Is the timecode range a comment line?
|
||||
static bool v1_invalid_timecode(TimecodeRange const& range) {
|
||||
return range.fps == 0.;
|
||||
}
|
||||
|
||||
/// @brief Generate override ranges for all frames with assumed fpses
|
||||
/// @param ranges List with ranges which is mutated
|
||||
/// @param fps Assumed fps to use for gaps
|
||||
static void v1_fill_range_gaps(std::list<TimecodeRange> &ranges, double fps) {
|
||||
// Range for frames between start and first override
|
||||
if (ranges.empty() || ranges.front().start > 0) {
|
||||
TimecodeRange range;
|
||||
range.fps = fps;
|
||||
range.start = 0;
|
||||
range.end = ranges.empty() ? 0 : ranges.front().start - 1;
|
||||
ranges.push_front(range);
|
||||
}
|
||||
if (ranges.empty() || ranges.front().start > 0)
|
||||
ranges.emplace_front(0, ranges.empty() ? 0 : ranges.front().start - 1, fps);
|
||||
|
||||
std::list<TimecodeRange>::iterator cur = ++ranges.begin();
|
||||
std::list<TimecodeRange>::iterator prev = ranges.begin();
|
||||
for (; cur != ranges.end(); ++cur, ++prev) {
|
||||
if (prev->end >= cur->start) {
|
||||
if (prev->end >= cur->start)
|
||||
// mkvmerge allows overlapping timecode ranges, but does completely
|
||||
// broken things with them
|
||||
throw UnorderedTimecodes("Override ranges must not overlap");
|
||||
}
|
||||
if (prev->end + 1 < cur->start) {
|
||||
TimecodeRange range;
|
||||
range.fps = fps;
|
||||
range.start = prev->end + 1;
|
||||
range.end = cur->start - 1;
|
||||
ranges.insert(cur, range);
|
||||
ranges.emplace(cur, prev->end + 1, cur->start -1, fps);
|
||||
++prev;
|
||||
}
|
||||
}
|
||||
|
@ -150,24 +127,23 @@ static void v1_fill_range_gaps(std::list<TimecodeRange> &ranges, double fps) {
|
|||
/// @param[out] last Unrounded time of the last frame
|
||||
/// @return Assumed fps times one million
|
||||
static int64_t v1_parse(line_iterator<std::string> file, std::string line, std::vector<int> &timecodes, int64_t &last) {
|
||||
using namespace std;
|
||||
double fps = atof(line.substr(7).c_str());
|
||||
if (fps <= 0.) throw BadFPS("Assumed FPS must be greater than zero");
|
||||
if (fps > 1000.) throw BadFPS("Assumed FPS must not be greater than 1000");
|
||||
|
||||
list<TimecodeRange> ranges;
|
||||
transform(file, line_iterator<string>(), back_inserter(ranges), v1_parse_line);
|
||||
ranges.erase(remove_if(ranges.begin(), ranges.end(), v1_invalid_timecode), ranges.end());
|
||||
std::list<TimecodeRange> ranges;
|
||||
transform(file, line_iterator<std::string>(), back_inserter(ranges), v1_parse_line);
|
||||
ranges.erase(boost::remove_if(ranges, [](TimecodeRange const& r) { return r.fps == 0; }), ranges.end());
|
||||
|
||||
ranges.sort();
|
||||
v1_fill_range_gaps(ranges, fps);
|
||||
timecodes.reserve(ranges.back().end);
|
||||
|
||||
double time = 0.;
|
||||
for (list<TimecodeRange>::iterator cur = ranges.begin(); cur != ranges.end(); ++cur) {
|
||||
for (int frame = cur->start; frame <= cur->end; frame++) {
|
||||
for (auto const& range : ranges) {
|
||||
for (int frame = range.start; frame <= range.end; ++frame) {
|
||||
timecodes.push_back(int(time + .5));
|
||||
time += 1000. / cur->fps;
|
||||
time += 1000. / range.fps;
|
||||
}
|
||||
}
|
||||
timecodes.push_back(int(time + .5));
|
||||
|
@ -229,20 +205,18 @@ Framerate::Framerate(std::string const& filename)
|
|||
: denominator(default_denominator)
|
||||
, numerator(0)
|
||||
{
|
||||
using namespace std;
|
||||
scoped_ptr<ifstream> file(agi::io::Open(filename));
|
||||
string encoding = agi::charset::Detect(filename);
|
||||
string line = *line_iterator<string>(*file, encoding);
|
||||
scoped_ptr<std::ifstream> file(agi::io::Open(filename));
|
||||
std::string encoding = agi::charset::Detect(filename);
|
||||
std::string line = *line_iterator<std::string>(*file, encoding);
|
||||
if (line == "# timecode format v2") {
|
||||
copy(line_iterator<int>(*file, encoding), line_iterator<int>(), back_inserter(timecodes));
|
||||
SetFromTimecodes();
|
||||
return;
|
||||
}
|
||||
if (line == "# timecode format v1" || line.substr(0, 7) == "Assume ") {
|
||||
if (line[0] == '#') {
|
||||
line = *line_iterator<string>(*file, encoding);
|
||||
}
|
||||
numerator = v1_parse(line_iterator<string>(*file, encoding), line, timecodes, last);
|
||||
if (line[0] == '#')
|
||||
line = *line_iterator<std::string>(*file, encoding);
|
||||
numerator = v1_parse(line_iterator<std::string>(*file, encoding), line, timecodes, last);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -254,10 +228,9 @@ void Framerate::Save(std::string const& filename, int length) const {
|
|||
std::ofstream &out = file.Get();
|
||||
|
||||
out << "# timecode format v2\n";
|
||||
std::copy(timecodes.begin(), timecodes.end(), std::ostream_iterator<int>(out, "\n"));
|
||||
for (int written = (int)timecodes.size(); written < length; ++written) {
|
||||
boost::copy(timecodes, std::ostream_iterator<int>(out, "\n"));
|
||||
for (int written = (int)timecodes.size(); written < length; ++written)
|
||||
out << TimeAtFrame(written) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int Framerate::FrameAtTime(int ms, Time type) const {
|
||||
|
@ -274,12 +247,10 @@ int Framerate::FrameAtTime(int ms, Time type) const {
|
|||
// Combining these allows us to easily calculate START and END in terms of
|
||||
// EXACT
|
||||
|
||||
if (type == START) {
|
||||
if (type == START)
|
||||
return FrameAtTime(ms - 1) + 1;
|
||||
}
|
||||
if (type == END) {
|
||||
if (type == END)
|
||||
return FrameAtTime(ms - 1);
|
||||
}
|
||||
|
||||
if (ms < 0)
|
||||
return int((ms * numerator / denominator - 999) / 1000);
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace detail {
|
|||
/// Used by the signal when the signal wishes to end a connection (such
|
||||
/// as if the signal is being destroyed while slots are still connected
|
||||
/// to it)
|
||||
void DisconnectToken(ConnectionToken *tok) { tok->signal = NULL; }
|
||||
void DisconnectToken(ConnectionToken *tok) { tok->signal = nullptr; }
|
||||
|
||||
/// @brief Has a token been claimed by a scoped connection object?
|
||||
bool TokenClaimed(ConnectionToken *tok) { return tok->claimed; }
|
||||
|
@ -129,7 +129,7 @@ namespace detail {
|
|||
|
||||
inline void ConnectionToken::Disconnect() {
|
||||
if (signal) signal->Disconnect(this);
|
||||
signal = NULL;
|
||||
signal = nullptr;
|
||||
}
|
||||
|
||||
/// @brief Templated common code for signals
|
||||
|
@ -176,7 +176,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
#define SIGNALS_H_FOR_EACH_SIGNAL(...) \
|
||||
for (typename super::SlotMap::iterator cur = slots.begin(); cur != slots.end();) { \
|
||||
for (auto cur = slots.begin(); cur != slots.end();) { \
|
||||
if (Blocked(cur->first)) \
|
||||
++cur; \
|
||||
else \
|
||||
|
@ -261,16 +261,11 @@ class Signal<void> : public detail::SignalBaseImpl<std::function<void ()> > {
|
|||
using super::slots;
|
||||
public:
|
||||
Signal() { }
|
||||
// Work around compilters that can't tell this is a template context due to it
|
||||
// being fully specified, making typename invalid here.
|
||||
#define typename
|
||||
|
||||
/// @brief Trigger this signal
|
||||
///
|
||||
/// The order in which connected slots are called is undefined and should
|
||||
/// not be relied on
|
||||
void operator()() { SIGNALS_H_FOR_EACH_SIGNAL() }
|
||||
#undef typename
|
||||
};
|
||||
|
||||
#undef SIGNALS_H_FOR_EACH_SIGNAL
|
||||
|
|
|
@ -105,7 +105,7 @@ void Check(const std::string &file, acs::Type type) {
|
|||
|
||||
SECURITY_INFORMATION info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
|
||||
DWORD len = 0;
|
||||
GetFileSecurity(wfile.c_str(), info, NULL, 0, &len);
|
||||
GetFileSecurity(wfile.c_str(), info, nullptr, 0, &len);
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
LOG_W("acs/check") << "GetFileSecurity: fatal: " << util::ErrorString(GetLastError());
|
||||
|
||||
|
|
|
@ -60,9 +60,9 @@ void Rename(const std::string& from, const std::string& to) {
|
|||
}
|
||||
|
||||
std::string ErrorString(DWORD error) {
|
||||
LPWSTR lpstr = NULL;
|
||||
LPWSTR lpstr = nullptr;
|
||||
|
||||
if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, reinterpret_cast<LPWSTR>(&lpstr), 0, NULL) == 0) {
|
||||
if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error, 0, reinterpret_cast<LPWSTR>(&lpstr), 0, nullptr) == 0) {
|
||||
/// @todo Return the actual 'unknown error' string from windows.
|
||||
return "Unknown Error";
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue