Replace boost::format with agi::format

boost::format is slow to compile, slow to run, and has an unpleasant
interface.
This commit is contained in:
Thomas Goyne 2014-05-28 15:19:05 -07:00
parent 8ba286c544
commit b43788fa7f
42 changed files with 616 additions and 171 deletions

View File

@ -54,6 +54,7 @@
<ClInclude Include="$(SrcDir)include\libaegisub\dispatch.h" />
<ClInclude Include="$(SrcDir)include\libaegisub\exception.h" />
<ClInclude Include="$(SrcDir)include\libaegisub\file_mapping.h" />
<ClInclude Include="$(SrcDir)include\libaegisub\format.h" />
<ClInclude Include="$(SrcDir)include\libaegisub\fs.h" />
<ClInclude Include="$(SrcDir)include\libaegisub\fs_fwd.h" />
<ClInclude Include="$(SrcDir)include\libaegisub\hotkey.h" />
@ -104,6 +105,7 @@
<ClCompile Include="$(SrcDir)common\color.cpp" />
<ClCompile Include="$(SrcDir)common\dispatch.cpp" />
<ClCompile Include="$(SrcDir)common\file_mapping.cpp" />
<ClCompile Include="$(SrcDir)common\format.cpp" />
<ClCompile Include="$(SrcDir)common\fs.cpp" />
<ClCompile Include="$(SrcDir)common\hotkey.cpp" />
<ClCompile Include="$(SrcDir)common\io.cpp" />

View File

@ -170,6 +170,9 @@
<ClInclude Include="$(SrcDir)include\libaegisub\file_mapping.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)include\libaegisub\format.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)include\libaegisub\character_count.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@ -16,7 +16,7 @@
#include "parser.h"
#include <boost/format.hpp>
#include "libaegisub/format.h"
namespace agi {
@ -29,11 +29,11 @@ Color::Color(std::string const& str) {
}
std::string Color::GetAssStyleFormatted() const {
return str(boost::format("&H%02X%02X%02X%02X") % (int)a % (int)b % (int)g % (int)r);
return agi::format("&H%02X%02X%02X%02X", a, b, g, r);
}
std::string Color::GetAssOverrideFormatted() const {
return str(boost::format("&H%02X%02X%02X&") % (int)b % (int)g % (int)r);
return agi::format("&H%02X%02X%02X&", b, g, r);
}
std::string Color::GetSsaFormatted() const {
@ -42,12 +42,12 @@ std::string Color::GetSsaFormatted() const {
std::string Color::GetHexFormatted(bool rgba) const {
if (rgba)
return str(boost::format("#%02X%02X%02X%02X") % (int)r % (int)g % (int)b % (int)a);
return str(boost::format("#%02X%02X%02X") % (int)r % (int)g % (int)b);
return agi::format("#%02X%02X%02X%02X", r, g, b, a);
return agi::format("#%02X%02X%02X", r, g, b);
}
std::string Color::GetRgbFormatted() const {
return str(boost::format("rgb(%d, %d, %d)") % (int)r % (int)g % (int)b);
return agi::format("rgb(%d, %d, %d)", r, g, b);
}
bool Color::operator==(Color const& col) const {

View File

@ -0,0 +1,324 @@
// Copyright (c) 2014, 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 <boost/interprocess/streams/vectorstream.hpp>
#include <boost/io/ios_state.hpp>
#include <cassert>
#include <type_traits>
namespace agi { namespace format_detail {
// A static cast which throws at runtime if the cast is invalid rather than
// failing to compile, as with format strings we don't know what type to cast
// to at compile time.
template<typename In, typename Out, bool = std::is_convertible<In, Out>::value>
struct runtime_cast_helper {
static Out cast(In const&) { throw std::bad_cast(); }
};
template<typename In, typename Out>
struct runtime_cast_helper<In, Out, true> {
static Out cast(In const& value) {
return static_cast<Out>(value);
}
};
template<typename Out, typename In>
Out runtime_cast(In const& value) {
return runtime_cast_helper<In, Out>::cast(value);
}
template<typename T>
void write_string(std::ostream& out, int, T const& value) {
out << value;
}
// Check length for string types
inline void write_string(std::ostream& out, int max_len, const char *value) {
if (max_len <= 0)
out << value;
else {
std::streamsize len = 0;
for (; len < max_len && value[len]; ++len) ;
out.write(value, len);
}
}
inline void write_string(std::ostream& out, int max_len, std::string const& value) {
if (max_len > 0 && static_cast<size_t>(max_len) < value.size())
out.write(value.data(), max_len);
else
out << value;
}
class formatter {
formatter(const formatter&) = delete;
formatter& operator=(const formatter&) = delete;
std::ostream& out;
const char *fmt;
const char *fmt_cur = nullptr;
bool read_width = false;
bool read_precision = false;
bool pending = false;
int width = 0;
int precision = 0;
boost::io::ios_all_saver saver;
void read_and_append_up_to_next_specifier() {
for (std::streamsize len = 0; ; ++len) {
// Ran out of format specifiers; not an error due to that
// translated strings may not need them all
if (!fmt[len]) {
out.write(fmt, len);
fmt += len;
return;
}
if (fmt[len] == '%') {
if (fmt[len + 1] == '%') {
out.write(fmt, len);
fmt += len + 1;
len = 0;
continue;
}
out.write(fmt, len);
fmt += len;
break;
}
}
}
int read_int() {
int i = 0;
for (; *fmt_cur >= '0' && *fmt_cur <= '9'; ++fmt_cur)
i = 10 * i + (*fmt_cur - '0');
return i;
}
void parse_flags() {
for (; ; ++fmt_cur) {
switch (*fmt_cur) {
// Not supported: ' ' (add a space before positive numers to align with negative)
case '#':
out.setf(std::ios::showpoint | std::ios::showbase);
continue;
case '0':
// overridden by left alignment ('-' flag)
if (!(out.flags() & std::ios::left)) {
// Use internal padding so that numeric values are
// formatted correctly, eg -00010 rather than 000-10
out.fill('0');
out.setf(std::ios::internal, std::ios::adjustfield);
}
continue;
case '-':
out.fill(' ');
out.setf(std::ios::left, std::ios::adjustfield);
continue;
case '+':
out.setf(std::ios::showpos);
continue;
}
break;
}
}
void parse_width() {
if (*fmt_cur >= '0' && *fmt_cur <= '9')
width = read_int();
else if (*fmt_cur == '*') {
read_width = true;
pending = true;
++fmt_cur;
}
}
void parse_precision() {
if (*fmt_cur != '.') return;
++fmt_cur;
// Ignoring negative precision because it's dumb and pointless
if (*fmt_cur >= '0' && *fmt_cur <= '9')
precision = read_int();
else if (*fmt_cur == '*') {
read_precision = true;
pending = true;
++fmt_cur;
}
else
precision = 0;
}
void parse_length_modifiers() {
// Where "parse" means "skip" since we don't need them
for (char c = *fmt_cur;
c == 'l' || c == 'h' || c == 'L' || c == 'j' || c == 'z' || c == 't';
c = *++fmt_cur);
}
void parse_format_specifier() {
width = 0;
precision = -1;
out.fill(' ');
out.unsetf(
std::ios::adjustfield |
std::ios::basefield |
std::ios::boolalpha |
std::ios::floatfield |
std::ios::showbase |
std::ios::showpoint |
std::ios::showpos |
std::ios::uppercase);
// Don't touch fmt until the specifier is fully applied so that if we
// have insufficient arguments it'll get passed through to the output
fmt_cur = fmt + 1;
parse_flags();
parse_width();
parse_precision();
parse_length_modifiers();
}
public:
formatter(std::ostream& out, const char *fmt) : out(out), fmt(fmt), saver(out) { }
~formatter() {
// Write remaining formatting string
for (std::streamsize len = 0; ; ++len) {
if (!fmt[len]) {
out.write(fmt, len);
return;
}
if (fmt[len] == '%' && fmt[len + 1] == '%') {
out.write(fmt, len);
fmt += len + 1;
len = 0;
continue;
}
}
}
template<typename T>
void operator()(T&& value) {
if (!pending) {
read_and_append_up_to_next_specifier();
if (!*fmt) return;
parse_format_specifier();
}
if (read_width) {
width = runtime_cast<int>(value);
read_width = false;
return;
}
if (read_precision) {
precision = runtime_cast<int>(value);
read_precision = false;
return;
}
pending = false;
if (width < 0) {
out.fill(' ');
out.setf(std::ios::left, std::ios::adjustfield);
width = -width;
}
out.width(width);
out.precision(precision < 0 ? 6 : precision);
char c = *fmt_cur ? fmt_cur[0] : 's';
if (c >= 'A' && c <= 'Z') {
out.setf(std::ios::uppercase);
c += 'a' - 'A';
}
switch (c) {
case 'c':
out.setf(std::ios::dec, std::ios::basefield);
out << runtime_cast<char>(value);
break;
case 'd': case 'i':
out.setf(std::ios::dec, std::ios::basefield);
out << runtime_cast<intmax_t>(value);
break;
case 'o':
out.setf(std::ios::oct, std::ios::basefield);
out << runtime_cast<intmax_t>(value);
break;
case 'x':
out.setf(std::ios::hex, std::ios::basefield);
out << runtime_cast<intmax_t>(value);
break;
case 'u':
out.setf(std::ios::dec, std::ios::basefield);
out << runtime_cast<uintmax_t>(value);
break;
case 'e':
out.setf(std::ios::scientific, std::ios::floatfield);
out.setf(std::ios::dec, std::ios::basefield);
out << runtime_cast<double>(value);
break;
case 'f':
out.setf(std::ios::fixed, std::ios::floatfield);
out << runtime_cast<double>(value);
break;
case 'g':
out.setf(std::ios::dec, std::ios::basefield);
out.flags(out.flags() & ~std::ios::floatfield);
out << runtime_cast<double>(value);
break;
case 'p':
out.setf(std::ios::hex, std::ios::basefield);
out << runtime_cast<const void *>(value);
break;
default: // s and other
out.setf(std::ios::boolalpha);
write_string(out, precision, value);
break;
}
fmt = *fmt_cur ? fmt_cur + 1 : fmt_cur;
}
};
// Base case for variadic template recursion
inline void format(formatter&&) { }
template<typename T, typename... Args>
void format(formatter&& fmt, T&& first, Args&&... rest) {
fmt(first);
format(std::move(fmt), std::forward<Args>(rest)...);
}
} // namespace format_detail
template<typename... Args>
void format(std::ostream& out, const char *fmt, Args&&... args) {
format(format_detail::formatter(out, fmt), std::forward<Args>(args)...);
}
template<typename... Args>
std::string format(const char *fmt, Args&&... args) {
boost::interprocess::basic_vectorstream<std::string> out;
format(out, fmt, std::forward<Args>(args)...);
return out.vector();
}
}

View File

@ -16,11 +16,11 @@
#include "libaegisub/lua/utils.h"
#include "libaegisub/format.h"
#include "libaegisub/log.h"
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/format.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/regex.hpp>
@ -170,9 +170,9 @@ int add_stack_trace(lua_State *L) {
else if (*ar.what == 'C')
function = '?';
else if (!*ar.namewhat)
function = str(boost::format("<anonymous function at lines %d-%d>") % real_line(ar.linedefined) % real_line(ar.lastlinedefined - 1));
function = agi::format("<anonymous function at lines %d-%d>", real_line(ar.linedefined), real_line(ar.lastlinedefined - 1));
frames.emplace_back(str(boost::format(" File \"%s\", line %d\n%s") % file % real_line(ar.currentline) % function));
frames.emplace_back(agi::format(" File \"%s\", line %d\n%s", file, real_line(ar.currentline), function));
}
}

View File

@ -18,12 +18,13 @@
#include <libaegisub/access.h>
#include <libaegisub/format.h>
#include <libaegisub/format_path.h>
#include <libaegisub/fs.h>
#include <libaegisub/log.h>
#include <libaegisub/util.h>
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <windows.h>
@ -63,7 +64,7 @@ void Check(fs::path const& file, acs::Type type) {
case ERROR_ACCESS_DENIED:
throw fs::ReadDenied(file);
default:
throw fs::FileSystemUnknownError(str(boost::format("Unexpected error when getting attributes for \"%s\": %s") % file % util::ErrorString(GetLastError())));
throw fs::FileSystemUnknownError(agi::format("Unexpected error when getting attributes for \"%s\": %s", file, util::ErrorString(GetLastError())));
}
}

View File

@ -34,7 +34,7 @@
#include "ass_export_filter.h"
#include <boost/format.hpp>
#include <libaegisub/format.h>
static FilterList& filters() {
static FilterList instance;
@ -53,7 +53,7 @@ void AssExportFilterChain::Register(std::unique_ptr<AssExportFilter> filter) {
std::string name = filter->name;
// Find a unique name
while (GetFilter(name))
name = str(boost::format("%s (%d)") % filter->name % filter_copy++);
name = agi::format("%s (%d)", filter->name, filter_copy++);
filter->name = name;

View File

@ -18,7 +18,8 @@
#include "ass_dialogue.h"
#include <boost/format.hpp>
#include <libaegisub/format.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/trim.hpp>
@ -26,7 +27,7 @@ std::string AssKaraoke::Syllable::GetText(bool k_tag) const {
std::string ret;
if (k_tag)
ret = str(boost::format("{%s%d}") % tag_type % ((duration + 5) / 10));
ret = agi::format("{%s%d}", tag_type, ((duration + 5) / 10));
size_t idx = 0;
for (auto const& ovr : ovr_tags) {

View File

@ -38,12 +38,12 @@
#include "utils.h"
#include <libaegisub/color.h>
#include <libaegisub/format.h>
#include <libaegisub/make_unique.h>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/format.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <functional>
@ -128,7 +128,7 @@ template<> void AssOverrideParameter::Set<std::string>(std::string new_value) {
template<> void AssOverrideParameter::Set<int>(int new_value) {
if (classification == AssParameterClass::ALPHA)
Set(str(boost::format("&H%02X&") % mid(0, new_value, 255)));
Set(agi::format("&H%02X&", mid(0, new_value, 255)));
else
Set(std::to_string(new_value));
}

View File

@ -37,10 +37,10 @@
#include "subtitle_format.h"
#include "utils.h"
#include <libaegisub/format.h>
#include <libaegisub/split.h>
#include <boost/algorithm/string/trim.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <wx/intl.h>
@ -175,17 +175,17 @@ void AssStyle::UpdateData() {
replace(name.begin(), name.end(), ',', ';');
replace(font.begin(), font.end(), ',', ';');
data = str(boost::format("Style: %s,%s,%g,%s,%s,%s,%s,%d,%d,%d,%d,%g,%g,%g,%g,%d,%g,%g,%i,%i,%i,%i,%i")
% name % font % fontsize
% primary.GetAssStyleFormatted()
% secondary.GetAssStyleFormatted()
% outline.GetAssStyleFormatted()
% shadow.GetAssStyleFormatted()
% (bold? -1 : 0) % (italic ? -1 : 0)
% (underline ? -1 : 0) % (strikeout ? -1 : 0)
% scalex % scaley % spacing % angle
% borderstyle % outline_w % shadow_w % alignment
% Margin[0] % Margin[1] % Margin[2] % encoding);
data = agi::format("Style: %s,%s,%g,%s,%s,%s,%s,%d,%d,%d,%d,%g,%g,%g,%g,%d,%g,%g,%i,%i,%i,%i,%i",
name, font, fontsize,
primary.GetAssStyleFormatted(),
secondary.GetAssStyleFormatted(),
outline.GetAssStyleFormatted(),
shadow.GetAssStyleFormatted(),
(bold? -1 : 0), (italic ? -1 : 0),
(underline ? -1 : 0), (strikeout ? -1 : 0),
scalex, scaley, spacing, angle,
borderstyle, outline_w, shadow_w, alignment,
Margin[0], Margin[1], Margin[2], encoding);
}
void AssStyle::GetEncodings(wxArrayString &encodingStrings) {

View File

@ -23,12 +23,12 @@
#include "utils.h"
#include <libaegisub/format.h>
#include <libaegisub/util.h>
#include <algorithm>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/format.hpp>
#include <boost/range/adaptor/filtered.hpp>
AssTime::AssTime(int time) : time(mid(0, time, 10 * 60 * 60 * 1000 - 1)) { }
@ -94,7 +94,7 @@ SmpteFormatter::SmpteFormatter(agi::vfr::Framerate fps, std::string sep)
std::string SmpteFormatter::ToSMPTE(AssTime time) const {
int h=0, m=0, s=0, f=0;
fps.SmpteAtTime(time, &h, &m, &s, &f);
return str(boost::format("%02d%s%02d%s%02d%c%02d") % h % sep % m % sep % s % sep % f);
return agi::format("%02d%s%02d%s%02d%c%02d", h, sep, m, sep, s, sep, f);
}
AssTime SmpteFormatter::FromSMPTE(std::string const& str) const {

View File

@ -20,12 +20,12 @@
#include "options.h"
#include <libaegisub/file_mapping.h>
#include <libaegisub/format.h>
#include <libaegisub/fs.h>
#include <libaegisub/path.h>
#include <libaegisub/make_unique.h>
#include <boost/filesystem/path.hpp>
#include <boost/format.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
#include <thread>
@ -64,9 +64,8 @@ public:
if ((uint64_t)num_samples * bytes_per_sample > agi::fs::FreeSpace(cache_dir))
throw agi::AudioCacheOpenError("Not enough free disk space in " + cache_dir.string() + " to cache the audio", nullptr);
auto filename = str(boost::format("audio-%lld-%lld")
% (long long)time(nullptr)
% (long long)boost::interprocess::ipcdetail::get_current_process_id());
auto filename = agi::format("audio-%lld-%lld", time(nullptr),
boost::interprocess::ipcdetail::get_current_process_id());
file = agi::make_unique<agi::temp_file_mapping>(cache_dir / filename, num_samples * bytes_per_sample);
decoder = std::thread([&] {

View File

@ -39,13 +39,13 @@
#include "subs_controller.h"
#include <libaegisub/dispatch.h>
#include <libaegisub/format.h>
#include <libaegisub/fs.h>
#include <libaegisub/path.h>
#include <libaegisub/make_unique.h>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/format.hpp>
#include <boost/tokenizer.hpp>
#include <future>
@ -490,7 +490,7 @@ namespace Automation4 {
std::string filter(fact->GetFilenamePattern());
boost::replace_all(filter, ",", ";");
fnfilter += str(boost::format("%s scripts (%s)|%s|") % fact->GetEngineName() % fact->GetFilenamePattern() % filter);
fnfilter += agi::format("%s scripts (%s)|%s|", fact->GetEngineName(), fact->GetFilenamePattern(), filter);
catchall += filter + ";";
}
fnfilter += from_wx(_("All Files")) + " (*.*)|*.*";

View File

@ -50,17 +50,17 @@
#include "video_controller.h"
#include "utils.h"
#include <libaegisub/format.h>
#include <libaegisub/lua/modules.h>
#include <libaegisub/lua/script_reader.h>
#include <libaegisub/lua/utils.h>
#include <libaegisub/path.h>
#include <libaegisub/make_unique.h>
#include <libaegisub/path.h>
#include <algorithm>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/format.hpp>
#include <boost/scope_exit.hpp>
#include <cassert>
#include <mutex>
@ -475,7 +475,7 @@ namespace {
// don't thread this, as there's no point in it and it seems to break on wx 2.8.3, for some reason
if (lua_pcall(L, 0, 0, 0)) {
// error occurred, assumed to be on top of Lua stack
description = str(boost::format("Error initialising Lua script \"%s\":\n\n%s") % GetPrettyFilename().string() % get_string_or_default(L, -1));
description = agi::format("Error initialising Lua script \"%s\":\n\n%s", GetPrettyFilename().string(), get_string_or_default(L, -1));
lua_pop(L, 1);
return;
}
@ -655,7 +655,7 @@ namespace {
, cmd_type(cmd::COMMAND_NORMAL)
{
lua_getfield(L, LUA_REGISTRYINDEX, "filename");
cmd_name = str(boost::format("automation/lua/%s/%s") % check_string(L, -1) % check_string(L, 1));
cmd_name = agi::format("automation/lua/%s/%s", check_string(L, -1), check_string(L, 1));
if (!lua_isfunction(L, 3))
error(L, "The macro processing function must be a function");

View File

@ -50,12 +50,12 @@
#include "../video_controller.h"
#include <libaegisub/address_of_adaptor.h>
#include <libaegisub/format.h>
#include <libaegisub/of_type_adaptor.h>
#include <libaegisub/make_unique.h>
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/indirected.hpp>
@ -358,7 +358,7 @@ void show_color_picker(const agi::Context *c, agi::Color (AssStyle::*field), con
for (auto& line : lines) {
int shift = line.second.set_tag(tag, new_color.GetAssOverrideFormatted(), norm_sel_start, sel_start);
if (new_color.a != line.first.a) {
shift += line.second.set_tag(alpha, str(boost::format("&H%02X&") % (int)new_color.a), norm_sel_start, sel_start + shift);
shift += line.second.set_tag(alpha, agi::format("&H%02X&", (int)new_color.a), norm_sel_start, sel_start + shift);
line.first.a = new_color.a;
}

View File

@ -50,6 +50,7 @@
#include "../video_display.h"
#include "../video_frame.h"
#include <libaegisub/format.h>
#include <libaegisub/fs.h>
#include <libaegisub/path.h>
#include <libaegisub/make_unique.h>
@ -58,7 +59,6 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/format.hpp>
#include <wx/msgdlg.h>
#include <wx/textdlg.h>
@ -487,7 +487,7 @@ static void save_snapshot(agi::Context *c, bool raw) {
int session_shot_count = 1;
std::string path;
do {
path = str(boost::format("%s_%03d_%d.png") % basepath.string() % session_shot_count++ % c->videoController->GetFrameN());
path = agi::format("%s_%03d_%d.png", basepath.string(), session_shot_count++, c->videoController->GetFrameN());
} while (agi::fs::FileExists(path));
get_image(c, raw).SaveFile(to_wx(path), wxBITMAP_TYPE_PNG);

View File

@ -18,10 +18,10 @@
#include "version.h"
#include <libaegisub/format.h>
#include <libaegisub/util.h>
#include <boost/filesystem/fstream.hpp>
#include <boost/format.hpp>
#include <wx/string.h>
#include <wx/stackwalk.h>
@ -41,8 +41,8 @@ public:
if (!fp.good()) return;
fp << util::strftime("--- %y-%m-%d %H:%M:%S ------------------\n");
fp << boost::format("VER - %s\n") % GetAegisubLongVersionString();
fp << boost::format("FTL - Beginning stack dump for \"%s\": \n") % cause;
fp << agi::format("VER - %s\n", GetAegisubLongVersionString());
fp << agi::format("FTL - Beginning stack dump for \"%s\": \n", cause);
}
~StackWalker() {
@ -55,9 +55,9 @@ public:
void OnStackFrame(wxStackFrame const& frame) override final {
if (!fp.good()) return;
fp << boost::format("%03u - %p: %s") % frame.GetLevel() % frame.GetAddress() % frame.GetName().utf8_str().data();
fp << agi::format("%03u - %p: %s", frame.GetLevel(), frame.GetAddress(), frame.GetName().utf8_str().data());
if (frame.HasSourceLocation())
fp << boost::format(" on %s:%u") % frame.GetFileName().utf8_str().data() % frame.GetLine();
fp << agi::format(" on %s:%u", frame.GetFileName().utf8_str().data(), frame.GetLine());
fp << "\n";
}
@ -83,8 +83,8 @@ void Write(std::string const& error) {
boost::filesystem::ofstream file(crashlog_path, std::ios::app);
if (file.is_open()) {
file << util::strftime("--- %y-%m-%d %H:%M:%S ------------------\n");
file << boost::format("VER - %s\n") % GetAegisubLongVersionString();
file << boost::format("EXC - Aegisub has crashed with unhandled exception \"%s\".\n") % error;
file << agi::format("VER - %s\n", GetAegisubLongVersionString());
file << agi::format("EXC - Aegisub has crashed with unhandled exception \"%s\".\n", error);
file << "----------------------------------------\n\n";
file.close();
}

View File

@ -18,13 +18,13 @@
#include "version.h"
#include <libaegisub/format.h>
#include <libaegisub/fs.h>
#include <libaegisub/make_unique.h>
#include <libaegisub/util.h>
#include <atomic>
#include <boost/filesystem/fstream.hpp>
#include <boost/format.hpp>
#include <condition_variable>
#include <mutex>
#include <thread>
@ -143,10 +143,9 @@ void Write(std::string const& error) {
boost::filesystem::ofstream file(crashlog_path, std::ios::app);
if (file.is_open()) {
file << agi::util::strftime("--- %y-%m-%d %H:%M:%S ------------------\n");
file << boost::format("VER - %s\n") % GetAegisubLongVersionString();
file << boost::format("EXC - Aegisub has crashed with unhandled exception \"%s\".\n") % error;
agi::format(file, "VER - %s\n", GetAegisubLongVersionString());
agi::format(file, "EXC - Aegisub has crashed with unhandled exception \"%s\".\n", error);
file << "----------------------------------------\n\n";
file.close();
}
}
}

View File

@ -40,6 +40,7 @@
#include <libaegisub/dispatch.h>
#include <libaegisub/exception.h>
#include <libaegisub/format.h>
#include <libaegisub/line_iterator.h>
#include <libaegisub/scoped_ptr.h>
@ -47,7 +48,6 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/format.hpp>
#include <functional>
#include <mutex>
#include <vector>
@ -287,21 +287,20 @@ void DoCheck(bool interactive) {
if (!stream)
throw VersionCheckError(from_wx(_("Could not connect to updates server.")));
stream << boost::format(
stream << agi::format(
"GET %s?rev=%d&rel=%d&os=%s&lang=%s&aegilang=%s HTTP/1.0\r\n"
"User-Agent: Aegisub %s\r\n"
"Host: %s\r\n"
"Accept: */*\r\n"
"Connection: close\r\n\r\n")
% UPDATE_CHECKER_BASE_URL
% GetSVNRevision()
% (GetIsOfficialRelease() ? 1 : 0)
% GetOSShortName()
% GetSystemLanguage()
% GetAegisubLanguage()
% GetAegisubLongVersionString()
% UPDATE_CHECKER_SERVER
;
"Connection: close\r\n\r\n"
, UPDATE_CHECKER_BASE_URL
, GetSVNRevision()
, (GetIsOfficialRelease() ? 1 : 0)
, GetOSShortName()
, GetSystemLanguage()
, GetAegisubLanguage()
, GetAegisubLongVersionString()
, UPDATE_CHECKER_SERVER);
std::string http_version;
stream >> http_version;

View File

@ -55,6 +55,7 @@
#include "version.h"
#include <libaegisub/dispatch.h>
#include <libaegisub/format.h>
#include <libaegisub/fs.h>
#include <libaegisub/io.h>
#include <libaegisub/log.h>
@ -62,7 +63,6 @@
#include <libaegisub/path.h>
#include <libaegisub/util.h>
#include <boost/format.hpp>
#include <boost/interprocess/streams/bufferstream.hpp>
#include <boost/locale.hpp>
#include <locale>
@ -378,7 +378,7 @@ static void UnhandledExeception(bool stackWalk, agi::Context *c) {
agi::fs::CreateDirectory(path);
auto filename = c->subsController->Filename().stem();
filename.replace_extension(str(boost::format("%s.ass") % agi::util::strftime("%Y-%m-%d-%H-%M-%S")));
filename.replace_extension(agi::format("%s.ass", agi::util::strftime("%Y-%m-%d-%H-%M-%S")));
path /= filename;
c->subsController->Save(path);

View File

@ -42,11 +42,11 @@
#include "MatroskaParser.h"
#include <libaegisub/file_mapping.h>
#include <libaegisub/format.h>
#include <libaegisub/scoped_ptr.h>
#include <algorithm>
#include <boost/algorithm/string/replace.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/range/irange.hpp>
#include <boost/tokenizer.hpp>
@ -143,18 +143,18 @@ static void read_subtitles(agi::ProgressSink *ps, MatroskaFile *file, MkvStdIO *
subList.emplace_back(
boost::lexical_cast<int>(str_range(readBuf, first)),
str(boost::format("Dialogue: %d,%s,%s,%s")
% boost::lexical_cast<int>(str_range(first + 1, second))
% subStart.GetAssFormated()
% subEnd.GetAssFormated()
% str_range(second + 1, readBufEnd)));
agi::format("Dialogue: %d,%s,%s,%s"
, boost::lexical_cast<int>(str_range(first + 1, second))
, subStart.GetAssFormated()
, subEnd.GetAssFormated()
, str_range(second + 1, readBufEnd)));
}
// Process SRT
else {
auto line = str(boost::format("Dialogue: 0,%s,%s,Default,,0,0,0,,%s")
% subStart.GetAssFormated()
% subEnd.GetAssFormated()
% str_range(readBuf, readBufEnd));
auto line = agi::format("Dialogue: 0,%s,%s,Default,,0,0,0,,%s"
, subStart.GetAssFormated()
, subEnd.GetAssFormated()
, str_range(readBuf, readBufEnd));
boost::replace_all(line, "\r\n", "\\N");
boost::replace_all(line, "\r", "\\N");
boost::replace_all(line, "\n", "\\N");
@ -191,7 +191,7 @@ void MatroskaWrapper::GetSubtitles(agi::fs::path const& filename, AssFile *targe
std::string CodecID(trackInfo->CodecID);
if (CodecID == "S_TEXT/SSA" || CodecID == "S_TEXT/ASS" || CodecID == "S_TEXT/UTF8") {
tracksFound.push_back(track);
tracksNames.emplace_back(str(boost::format("%d (%s %s)") % track % CodecID % trackInfo->Language));
tracksNames.emplace_back(agi::format("%d (%s %s)", track, CodecID, trackInfo->Language));
if (trackInfo->Name) {
tracksNames.back() += ": ";
tracksNames.back() += trackInfo->Name;

View File

@ -24,6 +24,7 @@
#include "options.h"
#include <libaegisub/charset_conv.h>
#include <libaegisub/format.h>
#include <libaegisub/fs.h>
#include <libaegisub/io.h>
#include <libaegisub/line_iterator.h>
@ -31,7 +32,6 @@
#include <libaegisub/path.h>
#include <libaegisub/make_unique.h>
#include <boost/format.hpp>
#include <boost/range/algorithm.hpp>
#include <hunspell/hunspell.hxx>
@ -177,8 +177,8 @@ std::vector<std::string> HunspellSpellChecker::GetLanguageList() {
}
static bool check_path(agi::fs::path const& path, std::string const& language, agi::fs::path& aff, agi::fs::path& dic) {
aff = path/str(boost::format("%s.aff") % language);
dic = path/str(boost::format("%s.dic") % language);
aff = path/agi::format("%s.aff", language);
dic = path/agi::format("%s.dic", language);
return agi::fs::FileExists(aff) && agi::fs::FileExists(dic);
}
@ -204,7 +204,7 @@ void HunspellSpellChecker::OnLanguageChanged() {
conv = agi::make_unique<agi::charset::IconvWrapper>("utf-8", hunspell->get_dic_encoding());
rconv = agi::make_unique<agi::charset::IconvWrapper>(hunspell->get_dic_encoding(), "utf-8");
userDicPath = config::path->Decode("?user/dictionaries")/str(boost::format("user_%s.dic") % language);
userDicPath = config::path->Decode("?user/dictionaries")/agi::format("user_%s.dic", language);
ReadUserDictionary();
for (auto const& word : customWords) {

View File

@ -37,15 +37,14 @@
#include "string_codec.h"
#include <boost/format.hpp>
#include <libaegisub/format.h>
std::string inline_string_encode(const std::string &input) {
std::string output;
output.reserve(input.size());
auto format = boost::format("#%02X");
for (char c : input) {
if (c <= 0x1F || c == 0x23 || c == 0x2C || c == 0x3A || c == 0x7C)
output += str(format % (int)(unsigned char)c);
output += agi::format("#%02X", (unsigned char)c);
else
output += c;
}

View File

@ -31,11 +31,11 @@
#include "subtitle_format.h"
#include "text_selection_controller.h"
#include <libaegisub/format.h>
#include <libaegisub/fs.h>
#include <libaegisub/path.h>
#include <libaegisub/util.h>
#include <boost/format.hpp>
#include <wx/msgdlg.h>
namespace {
@ -277,7 +277,7 @@ agi::fs::path SubsController::AutoSave() {
if (name.empty())
name = "Untitled";
path /= str(boost::format("%s.%s.AUTOSAVE.ass") % name.string() % agi::util::strftime("%Y-%m-%d-%H-%M-%S"));
path /= agi::format("%s.%s.AUTOSAVE.ass", name.string(), agi::util::strftime("%Y-%m-%d-%H-%M-%S"));
SubtitleFormat::GetWriter(path)->WriteFile(context->ass.get(), path, 0);
autosaved_commit_id = commit_id;

View File

@ -38,7 +38,7 @@
#include "ass_file.h"
#include "text_file_writer.h"
#include <boost/format.hpp>
#include <libaegisub/format.h>
EncoreSubtitleFormat::EncoreSubtitleFormat()
: SubtitleFormat("Adobe Encore")
@ -70,5 +70,5 @@ void EncoreSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& fi
int i = 0;
TextFileWriter file(filename, "UTF-8");
for (auto const& current : copy.Events)
file.WriteLineToFile(str(boost::format("%i %s %s %s") % ++i % ft.ToSMPTE(current.Start) % ft.ToSMPTE(current.End) % current.Text));
file.WriteLineToFile(agi::format("%i %s %s %s", ++i, ft.ToSMPTE(current.Start), ft.ToSMPTE(current.End), current.Text));
}

View File

@ -41,11 +41,11 @@
#include "text_file_reader.h"
#include "text_file_writer.h"
#include <libaegisub/format.h>
#include <libaegisub/fs.h>
#include <libaegisub/util.h>
#include <boost/algorithm/string/replace.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/regex.hpp>
@ -135,13 +135,13 @@ void MicroDVDSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const&
// Write FPS line
if (!fps.IsVFR())
file.WriteLineToFile(str(boost::format("{1}{1}%.6f") % fps.FPS()));
file.WriteLineToFile(agi::format("{1}{1}%.6f", fps.FPS()));
// Write lines
for (auto const& current : copy.Events) {
int start = fps.FrameAtTime(current.Start, agi::vfr::START);
int end = fps.FrameAtTime(current.End, agi::vfr::END);
file.WriteLineToFile(str(boost::format("{%i}{%i}%s") % start % end % boost::replace_all_copy(current.Text.get(), "\\N", "|")));
file.WriteLineToFile(agi::format("{%i}{%i}%s", start, end, boost::replace_all_copy(current.Text.get(), "\\N", "|")));
}
}

View File

@ -41,13 +41,13 @@
#include "text_file_reader.h"
#include "text_file_writer.h"
#include <libaegisub/format.h>
#include <libaegisub/of_type_adaptor.h>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/format.hpp>
#include <boost/regex.hpp>
#include <map>
@ -200,11 +200,11 @@ public:
// handle the attributes
if (attr_name == "face")
new_attribs.face = str(boost::format("{\\fn%s}") % attr_value);
new_attribs.face = agi::format("{\\fn%s}", attr_value);
else if (attr_name == "size")
new_attribs.size = str(boost::format("{\\fs%s}") % attr_value);
new_attribs.size = agi::format("{\\fs%s}", attr_value);
else if (attr_name == "color")
new_attribs.color = str(boost::format("{\\c%s}") % agi::Color(attr_value).GetAssOverrideFormatted());
new_attribs.color = agi::format("{\\c%s}", agi::Color(attr_value).GetAssOverrideFormatted());
// remove this attribute to prepare for the next
tag_attrs = result.suffix().str();
@ -320,7 +320,7 @@ milliseconds:
std::string WriteSRTTime(AssTime const& ts)
{
return str(boost::format("%02d:%02d:%02d,%03d") % ts.GetTimeHours() % ts.GetTimeMinutes() % ts.GetTimeSeconds() % ts.GetTimeMiliseconds());
return agi::format("%02d:%02d:%02d,%03d", ts.GetTimeHours(), ts.GetTimeMinutes(), ts.GetTimeSeconds(), ts.GetTimeMiliseconds());
}
}
@ -382,11 +382,11 @@ void SRTSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename,
if (regex_search(text_line, timestamp_match, timestamp_regex))
goto found_timestamps;
throw SRTParseError(str(boost::format("Parsing SRT: Expected subtitle index at line %d") % line_num), nullptr);
throw SRTParseError(agi::format("Parsing SRT: Expected subtitle index at line %d", line_num), nullptr);
case STATE_TIMESTAMP:
if (!regex_search(text_line, timestamp_match, timestamp_regex))
throw SRTParseError(str(boost::format("Parsing SRT: Expected timestamp pair at line %d") % line_num), nullptr);
throw SRTParseError(agi::format("Parsing SRT: Expected timestamp pair at line %d", line_num), nullptr);
found_timestamps:
if (line) {
// finalize active line
@ -524,9 +524,9 @@ std::string SRTSubtitleFormat::ConvertTags(const AssDialogue *diag) const {
if (it != tag_states.end()) {
bool temp = tag.Params[0].Get(false);
if (temp && !it->second)
final += str(boost::format("<%c>") % it->first);
final += agi::format("<%c>", it->first);
if (!temp && it->second)
final += str(boost::format("</%c>") % it->first);
final += agi::format("</%c>", it->first);
it->second = temp;
}
}
@ -541,7 +541,7 @@ std::string SRTSubtitleFormat::ConvertTags(const AssDialogue *diag) const {
// Otherwise unclosed overrides might affect lines they shouldn't, see bug #809 for example
for (auto it : tag_states) {
if (it.second)
final += str(boost::format("</%c>") % it.first);
final += agi::format("</%c>", it.first);
}
return final;

View File

@ -24,9 +24,10 @@
#include "text_file_writer.h"
#include "version.h"
#include <libaegisub/format.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/format.hpp>
namespace {
std::string replace_commas(std::string str) {
@ -54,14 +55,14 @@ void SsaSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filen
file.WriteLineToFile("[V4 Styles]");
file.WriteLineToFile("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding");
for (auto const& line : src->Styles)
file.WriteLineToFile(str(boost::format("Style: %s,%s,%g,%s,%s,0,%s,%d,%d,%d,%g,%g,%d,%d,%d,%d,0,%i")
% line.name % line.font % line.fontsize
% line.primary.GetSsaFormatted()
% line.secondary.GetSsaFormatted()
% line.shadow.GetSsaFormatted()
% (line.bold? -1 : 0) % (line.italic ? -1 : 0)
% line.borderstyle % line.outline_w % line.shadow_w % AssStyle::AssToSsa(line.alignment)
% line.Margin[0] % line.Margin[1] % line.Margin[2] % line.encoding));
file.WriteLineToFile(agi::format("Style: %s,%s,%g,%s,%s,0,%s,%d,%d,%d,%g,%g,%d,%d,%d,%d,0,%i"
, line.name, line.font, line.fontsize
, line.primary.GetSsaFormatted()
, line.secondary.GetSsaFormatted()
, line.shadow.GetSsaFormatted()
, (line.bold? -1 : 0), (line.italic ? -1 : 0)
, line.borderstyle, line.outline_w, line.shadow_w, AssStyle::AssToSsa(line.alignment)
, line.Margin[0], line.Margin[1], line.Margin[2], line.encoding));
file.WriteLineToFile("");
file.WriteLineToFile("[Fonts]");
@ -81,11 +82,11 @@ void SsaSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filen
file.WriteLineToFile("[Events]");
file.WriteLineToFile("Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text");
for (auto const& line : src->Events)
file.WriteLineToFile(str(boost::format("%s: Marked=0,%s,%s,%s,%s,%d,%d,%d,%s,%s")
% (line.Comment ? "Comment" : "Dialogue")
% line.Start.GetAssFormated() % line.End.GetAssFormated()
% replace_commas(line.Style) % replace_commas(line.Actor)
% line.Margin[0] % line.Margin[1] % line.Margin[2]
% replace_commas(line.Effect)
% strip_newlines(line.Text)));
file.WriteLineToFile(agi::format("%s: Marked=0,%s,%s,%s,%s,%d,%d,%d,%s,%s"
, (line.Comment ? "Comment" : "Dialogue")
, line.Start.GetAssFormated(), line.End.GetAssFormated()
, replace_commas(line.Style), replace_commas(line.Actor)
, line.Margin[0], line.Margin[1], line.Margin[2]
, replace_commas(line.Effect)
, strip_newlines(line.Text)));
}

View File

@ -40,7 +40,7 @@
#include "ass_time.h"
#include "text_file_writer.h"
#include <boost/format.hpp>
#include <libaegisub/format.h>
TranStationSubtitleFormat::TranStationSubtitleFormat()
: SubtitleFormat("TranStation")
@ -109,6 +109,6 @@ std::string TranStationSubtitleFormat::ConvertLine(AssFile *file, const AssDialo
if (nextl_start > 0 && end == nextl_start)
end = fps.TimeAtFrame(fps.FrameAtTime(end, agi::vfr::END) - 1, agi::vfr::END);
std::string header = str(boost::format("SUB[%i%s%s %s>%s]\r\n") % valign % halign % type % ft.ToSMPTE(current->Start) % ft.ToSMPTE(end));
std::string header = agi::format("SUB[%i%s%s %s>%s]\r\n", valign, halign, type, ft.ToSMPTE(current->Start), ft.ToSMPTE(end));
return header + current->Text.get();
}

View File

@ -23,16 +23,16 @@
#include "options.h"
#include <boost/format.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/range/algorithm.hpp>
#include <libaegisub/dispatch.h>
#include <libaegisub/format.h>
#include <libaegisub/fs.h>
#include <libaegisub/log.h>
#include <libaegisub/make_unique.h>
#include <libaegisub/path.h>
#include <libaegisub/thesaurus.h>
#include <libaegisub/make_unique.h>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/range/algorithm.hpp>
Thesaurus::Thesaurus()
: lang_listener(OPT_SUB("Tool/Thesaurus/Language", &Thesaurus::OnLanguageChanged, this))
@ -76,8 +76,8 @@ std::vector<std::string> Thesaurus::GetLanguageList() const {
}
static bool check_path(agi::fs::path const& path, std::string const& language, agi::fs::path& idx, agi::fs::path& dat) {
idx = path/str(boost::format("th_%s.idx") % language);
dat = path/str(boost::format("th_%s.dat") % language);
idx = path/agi::format("th_%s.idx", language);
dat = path/agi::format("th_%s.dat", language);
return agi::fs::FileExists(idx) && agi::fs::FileExists(dat);
}

View File

@ -27,11 +27,6 @@
//
// Aegisub Project http://www.aegisub.org/
/// @file utils.cpp
/// @brief Misc. utility functions
/// @ingroup utility
///
#include "utils.h"
#include "compat.h"
@ -39,6 +34,7 @@
#include "retina_helper.h"
#include <libaegisub/dispatch.h>
#include <libaegisub/format.h>
#include <libaegisub/fs.h>
#include <libaegisub/log.h>
@ -46,7 +42,6 @@
#include <unistd.h>
#endif
#include <boost/filesystem/path.hpp>
#include <boost/format.hpp>
#include <map>
#include <unicode/locid.h>
#include <wx/clipbrd.h>
@ -81,7 +76,7 @@ wxString PrettySize(int bytes) {
}
std::string float_to_string(double val) {
std::string s = str(boost::format("%.3f") % val);
std::string s = agi::format("%.3f", val);
size_t pos = s.find_last_not_of("0");
if (pos != s.find(".")) ++pos;
s.erase(begin(s) + pos, end(s));
@ -184,8 +179,8 @@ void CleanCache(agi::fs::path const& directory, std::string const& file_type, ui
}
if (cachefiles.size() <= max_files && total_size <= max_size) {
LOG_D("utils/clean_cache") << boost::format("cache does not need cleaning (maxsize=%d, cursize=%d, maxfiles=%d, numfiles=%d), exiting")
% max_size % total_size % max_files % cachefiles.size();
LOG_D("utils/clean_cache") << agi::format("cache does not need cleaning (maxsize=%d, cursize=%d, maxfiles=%d, numfiles=%d), exiting"
, max_size, total_size, max_files, cachefiles.size());
return;
}

View File

@ -23,7 +23,8 @@
#include "utils.h"
#include <boost/format.hpp>
#include <libaegisub/format.h>
#include <limits>
Vector2D::Vector2D()
@ -83,7 +84,7 @@ std::string Vector2D::PStr(char sep) const {
}
std::string Vector2D::DStr(char sep) const {
return str(boost::format("%d%c%d") % (int)x % sep % (int)y);
return agi::format("%d%c%d", (int)x, sep, (int)y);
}
std::string Vector2D::Str(char sep) const {

View File

@ -45,7 +45,7 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/format.hpp>
#include <libaegisub/format.h>
#include <boost/gil/gil_all.hpp>
DummyVideoProvider::DummyVideoProvider(double fps, int frames, int width, int height, agi::Color colour, bool pattern)
@ -89,7 +89,7 @@ DummyVideoProvider::DummyVideoProvider(double fps, int frames, int width, int he
}
std::string DummyVideoProvider::MakeFilename(double fps, int frames, int width, int height, agi::Color colour, bool pattern) {
return str(boost::format("?dummy:%f:%d:%d:%d:%d:%d:%d:%s") % fps % frames % width % height % (int)colour.r % (int)colour.g % (int)colour.b % (pattern ? "c" : ""));
return agi::format("?dummy:%f:%d:%d:%d:%d:%d:%d:%s", fps, frames, width, height, (int)colour.r, (int)colour.g, (int)colour.b, (pattern ? "c" : ""));
}
std::shared_ptr<VideoFrame> DummyVideoProvider::GetFrame(int) {

View File

@ -32,10 +32,10 @@
#include "visual_tool_drag.h"
#include "visual_tool_vector_clip.h"
#include <libaegisub/format.h>
#include <libaegisub/of_type_adaptor.h>
#include <algorithm>
#include <boost/format.hpp>
const wxColour VisualToolBase::colour[] = {
wxColour(106,32,19),
@ -500,11 +500,11 @@ std::string VisualToolBase::GetLineVectorClip(AssDialogue *diag, int &scale, boo
tag = find_tag(blocks, "\\clip");
if (tag && tag->size() == 4) {
return str(boost::format("m %d %d l %d %d %d %d %d %d")
% (*tag)[0].Get<int>() % (*tag)[1].Get<int>()
% (*tag)[2].Get<int>() % (*tag)[1].Get<int>()
% (*tag)[2].Get<int>() % (*tag)[3].Get<int>()
% (*tag)[0].Get<int>() % (*tag)[3].Get<int>());
return agi::format("m %d %d l %d %d %d %d %d %d"
, (*tag)[0].Get<int>(), (*tag)[1].Get<int>()
, (*tag)[2].Get<int>(), (*tag)[1].Get<int>()
, (*tag)[2].Get<int>(), (*tag)[3].Get<int>()
, (*tag)[0].Get<int>(), (*tag)[3].Get<int>());
}
if (tag) {
scale = std::max((*tag)[0].Get(scale), 1);

View File

@ -24,7 +24,8 @@
#include "include/aegisub/context.h"
#include "selection_controller.h"
#include <boost/format.hpp>
#include <libaegisub/format.h>
#include <wx/colour.h>
VisualToolClip::VisualToolClip(VideoDisplay *parent, agi::Context *context)
@ -102,7 +103,7 @@ void VisualToolClip::UpdateHold() {
}
void VisualToolClip::CommitHold() {
std::string value = str(boost::format("(%s,%s)") % ToScriptCoords(cur_1.Min(cur_2)).Str() % ToScriptCoords(cur_1.Max(cur_2)).Str());
std::string value = agi::format("(%s,%s)", ToScriptCoords(cur_1.Min(cur_2)).Str(), ToScriptCoords(cur_1.Max(cur_2)).Str());
for (auto line : c->selectionController->GetSelectedSet()) {
// This check is technically not correct as it could be outside of an

View File

@ -26,10 +26,9 @@
#include "video_display.h"
#include <libaegisub/color.h>
#include <libaegisub/format.h>
#include <libaegisub/make_unique.h>
#include <boost/format.hpp>
VisualToolCross::VisualToolCross(VideoDisplay *parent, agi::Context *context)
: VisualTool<VisualDraggableFeature>(parent, context)
, gl_text(agi::make_unique<OpenGLText>())
@ -49,9 +48,9 @@ void VisualToolCross::OnDoubleClick() {
int t1, t2;
if (GetLineMove(line, p1, p2, t1, t2)) {
if (t1 > 0 || t2 > 0)
SetOverride(line, "\\move", str(boost::format("(%s,%s,%d,%d)") % Text(p1 + d) % Text(p2 + d) % t1 % t2));
SetOverride(line, "\\move", agi::format("(%s,%s,%d,%d)", Text(p1 + d), Text(p2 + d), t1, t2));
else
SetOverride(line, "\\move", str(boost::format("(%s,%s)") % Text(p1 + d) % Text(p2 + d)));
SetOverride(line, "\\move", agi::format("(%s,%s)", Text(p1 + d), Text(p2 + d)));
}
else
SetOverride(line, "\\pos", "(" + Text(GetLinePosition(line) + d) + ")");

View File

@ -29,10 +29,10 @@
#include "video_controller.h"
#include "video_display.h"
#include <libaegisub/format.h>
#include <libaegisub/make_unique.h>
#include <algorithm>
#include <boost/format.hpp>
#include <boost/range/algorithm/binary_search.hpp>
#include <wx/toolbar.h>
@ -91,7 +91,7 @@ void VisualToolDrag::OnSubTool(wxCommandEvent &) {
// Round the start and end times to exact frames
int start = vc->TimeAtFrame(vc->FrameAtTime(line->Start, agi::vfr::START)) - line->Start;
int end = vc->TimeAtFrame(vc->FrameAtTime(line->Start, agi::vfr::END)) - line->Start;
SetOverride(line, "\\move", str(boost::format("(%s,%s,%d,%d)") % p1.Str() % p1.Str() % start % end));
SetOverride(line, "\\move", agi::format("(%s,%s,%d,%d)", p1.Str(), p1.Str(), start, end));
}
}
@ -298,11 +298,10 @@ void VisualToolDrag::UpdateDrag(Feature *feature) {
if (!feature->parent)
SetOverride(feature->line, "\\pos", ToScriptCoords(feature->pos).PStr());
else
SetOverride(feature->line, "\\move",
str(boost::format("(%s,%s,%d,%d)")
% ToScriptCoords(feature->pos).Str()
% ToScriptCoords(end_feature->pos).Str()
% feature->time % end_feature->time));
SetOverride(feature->line, "\\move", agi::format("(%s,%s,%d,%d)"
, ToScriptCoords(feature->pos).Str()
, ToScriptCoords(end_feature->pos).Str()
, feature->time , end_feature->time));
}
void VisualToolDrag::OnDoubleClick() {
@ -313,9 +312,9 @@ void VisualToolDrag::OnDoubleClick() {
int t1, t2;
if (GetLineMove(line, p1, p2, t1, t2)) {
if (t1 > 0 || t2 > 0)
SetOverride(line, "\\move", str(boost::format("(%s,%s,%d,%d)") % (p1 + d).Str() % (p2 + d).Str() % t1 % t2));
SetOverride(line, "\\move", agi::format("(%s,%s,%d,%d)", (p1 + d).Str(), (p2 + d).Str(), t1, t2));
else
SetOverride(line, "\\move", str(boost::format("(%s,%s)") % (p1 + d).Str() % (p2 + d).Str()));
SetOverride(line, "\\move", agi::format("(%s,%s)", (p1 + d).Str(), (p2 + d).Str()));
}
else
SetOverride(line, "\\pos", (GetLinePosition(line) + d).PStr());

View File

@ -20,7 +20,8 @@
#include "visual_tool_rotatexy.h"
#include <boost/format.hpp>
#include <libaegisub/format.h>
#include <cmath>
#include <wx/colour.h>
@ -162,8 +163,8 @@ void VisualToolRotateXY::UpdateHold() {
angle_x = fmodf(angle_x + 360.f, 360.f);
angle_y = fmodf(angle_y + 360.f, 360.f);
SetSelectedOverride("\\frx", str(boost::format("%.4g") % angle_x));
SetSelectedOverride("\\fry", str(boost::format("%.4g") % angle_y));
SetSelectedOverride("\\frx", agi::format("%.4g", angle_x));
SetSelectedOverride("\\fry", agi::format("%.4g", angle_y));
}
void VisualToolRotateXY::UpdateDrag(Feature *feature) {

View File

@ -20,7 +20,8 @@
#include "visual_tool_rotatez.h"
#include <boost/format.hpp>
#include <libaegisub/format.h>
#include <cmath>
#include <wx/colour.h>
@ -108,7 +109,7 @@ void VisualToolRotateZ::UpdateHold() {
angle = fmodf(angle + 360.f, 360.f);
SetSelectedOverride("\\frz", str(boost::format("%.4g") % angle));
SetSelectedOverride("\\frz", agi::format("%.4g", angle));
}
void VisualToolRotateZ::UpdateDrag(Feature *feature) {

View File

@ -24,6 +24,7 @@ SRC = \
tests/cajun.cpp \
tests/color.cpp \
tests/dialogue_lexer.cpp \
tests/format.cpp \
tests/fs.cpp \
tests/hotkey.cpp \
tests/iconv.cpp \

119
tests/tests/format.cpp Normal file
View File

@ -0,0 +1,119 @@
// Copyright (c) 2014, 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 "main.h"
#include "util.h"
#include <libaegisub/format.h>
TEST(lagi_format, s) {
EXPECT_EQ("hello", agi::format("%s", "hello"));
EXPECT_EQ("he", agi::format("%.2s", "hello"));
EXPECT_EQ("hello", agi::format("%.8s", "hello"));
EXPECT_EQ("he", agi::format("%.*s", 2, "hello"));
EXPECT_EQ("hello", agi::format("%", "hello"));
EXPECT_EQ("hello", agi::format("%s", std::string("hello")));
EXPECT_EQ("he", agi::format("%.2s", std::string("hello")));
EXPECT_EQ("true", agi::format("%s", true));
EXPECT_EQ("false", agi::format("%s", false));
}
TEST(lagi_format, c) {
EXPECT_EQ("a", agi::format("%c", 'a'));
EXPECT_EQ("a", agi::format("%c", (int)'a'));
}
TEST(lagi_format, d) {
EXPECT_EQ("10", agi::format("%i", 10));
EXPECT_EQ("10", agi::format("%d", 10));
EXPECT_EQ("-10", agi::format("%d", -10));
EXPECT_EQ("1", agi::format("%d", 1.1));
EXPECT_EQ("97", agi::format("%d", 'a'));
EXPECT_EQ("97", agi::format("%d", (int)'a'));
EXPECT_EQ("1", agi::format("%d", true));
}
TEST(lagi_format, o) {
EXPECT_EQ("15", agi::format("%o", 015));
}
TEST(lagi_format, u) {
EXPECT_EQ("10", agi::format("%u", 10));
EXPECT_EQ(std::to_string(static_cast<uintmax_t>(-10)), agi::format("%u", -10));
}
TEST(lagi_format, x) {
EXPECT_EQ("deadbeef", agi::format("%x", 0xdeadbeef));
EXPECT_EQ("DEADBEEF", agi::format("%X", 0xDEADBEEF));
}
TEST(lagi_format, e) {
EXPECT_EQ("1.234560e+10", agi::format("%e", 1.23456e10));
EXPECT_EQ("-1.234560E+10", agi::format("%E", -1.23456E10));
}
TEST(lagi_format, f) {
EXPECT_EQ("-9.876500", agi::format("%f", -9.8765));
EXPECT_EQ("9.876500", agi::format("%F", 9.8765));
}
TEST(lagi_format, g) {
EXPECT_EQ("10", agi::format("%g", 10));
EXPECT_EQ("100", agi::format("%G", 100));
}
TEST(lagi_format, escape) {
EXPECT_EQ("%d", agi::format("%%d"));
EXPECT_EQ("%d", agi::format("%%d", 5));
}
TEST(lagi_format, length_modifiers) {
EXPECT_EQ("10", agi::format("%hd", 10));
EXPECT_EQ("10", agi::format("%ld", 10));
EXPECT_EQ("10", agi::format("%lld", 10));
EXPECT_EQ("10", agi::format("%zd", 10));
EXPECT_EQ("10", agi::format("%td", 10));
EXPECT_EQ("10", agi::format("%jd", 10));
}
TEST(lagi_format, precision_width) {
EXPECT_EQ("05", agi::format("%02X", 5));
EXPECT_EQ(" -10", agi::format("%10d", -10));
EXPECT_EQ("0010", agi::format("%04d", 10));
EXPECT_EQ(" 1234.1235", agi::format("%10.4f", 1234.1234567890));
EXPECT_EQ("10", agi::format("%.f", 10.1));
EXPECT_EQ("0000000100", agi::format("%010d", 100));
EXPECT_EQ("-000000010", agi::format("%010d", -10));
EXPECT_EQ("0X0000BEEF", agi::format("%#010X", 0xBEEF));
}
TEST(lagi_format, flags) {
EXPECT_EQ("0x271828", agi::format("%#x", 0x271828));
EXPECT_EQ("011614050", agi::format("%#o", 0x271828));
EXPECT_EQ("3.000000", agi::format("%#f", 3.0));
EXPECT_EQ("+3", agi::format("%+d", 3));
EXPECT_EQ("+0", agi::format("%+d", 0));
EXPECT_EQ("-3", agi::format("%+d", -3));
EXPECT_EQ("10 ", agi::format("%-010d", 10));
EXPECT_EQ("10 ", agi::format("%0-10d", 10));
}
TEST(lagi_format, bad_cast) {
EXPECT_THROW(agi::format("%d", "hello"), std::bad_cast);
EXPECT_THROW(agi::format("%.*s", "hello", "str"), std::bad_cast);
}

View File

@ -28,7 +28,7 @@ TEST(lagi_word_split, empty) {
SplitWords(text, tokens);
EXPECT_TRUE(tokens.empty());
tokens.emplace_back(0, 0);
tokens.push_back(DialogueToken{0, 0});
SplitWords(text, tokens);
EXPECT_EQ(1u, tokens.size());
}
@ -134,7 +134,7 @@ TEST(lagi_word_split, unclosed_ovr) {
text = "{";
tokens.clear();
tokens.emplace_back(dt::OVR_BEGIN, 1);
tokens.push_back(DialogueToken{dt::OVR_BEGIN, 1});
SplitWords(text, tokens);
ASSERT_EQ(1u, tokens.size());