Use C++11 stuff in libaegisub

This commit is contained in:
Thomas Goyne 2012-11-13 06:07:39 -08:00
parent 653aa32eb2
commit 2dd1da8333
15 changed files with 147 additions and 223 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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();

View file

@ -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");
}

View file

@ -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"];

View file

@ -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();
}

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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());

View file

@ -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";
}