Redesign AssOverrideParameter

Always store the original string form and convert it to the desired type
on demand. In most cases this is significantly faster as typically only
a few of the parameters in a line are actually read. In addition, this
makes it so that parameters which did not actually change are always
reserialized in their original form.

Delete VariableData as it's no longer used by anything.

Closes #1513.
This commit is contained in:
Thomas Goyne 2012-12-10 14:19:28 -08:00
parent f28f6ad5b3
commit a0d3b8595f
9 changed files with 123 additions and 345 deletions

View File

@ -232,7 +232,6 @@
<ClInclude Include="$(SrcDir)tooltip_manager.h" />
<ClInclude Include="$(SrcDir)utils.h" />
<ClInclude Include="$(SrcDir)validators.h" />
<ClInclude Include="$(SrcDir)variable_data.h" />
<ClInclude Include="$(SrcDir)vector2d.h" />
<ClInclude Include="$(SrcDir)version.h" />
<ClInclude Include="$(SrcDir)video_box.h" />
@ -426,7 +425,6 @@
<ClCompile Include="$(SrcDir)tooltip_manager.cpp" />
<ClCompile Include="$(SrcDir)utils.cpp" />
<ClCompile Include="$(SrcDir)validators.cpp" />
<ClCompile Include="$(SrcDir)variable_data.cpp" />
<ClCompile Include="$(SrcDir)vector2d.cpp" />
<ClCompile Include="$(SrcDir)version.cpp" />
<ClCompile Include="$(SrcDir)video_box.cpp" />

View File

@ -630,9 +630,6 @@
<ClInclude Include="$(SrcDir)validators.h">
<Filter>Utilities</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)variable_data.h">
<Filter>Utilities</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)tooltip_manager.h">
<Filter>Features\Help</Filter>
</ClInclude>
@ -1179,9 +1176,6 @@
<ClCompile Include="$(SrcDir)validators.cpp">
<Filter>Utilities</Filter>
</ClCompile>
<ClCompile Include="$(SrcDir)variable_data.cpp">
<Filter>Utilities</Filter>
</ClCompile>
<ClCompile Include="$(SrcDir)tooltip_manager.cpp">
<Filter>Features\Help</Filter>
</ClCompile>
@ -1245,4 +1239,4 @@
<Filter>Resources</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
</Project>

View File

@ -245,7 +245,6 @@ SRC += \
tooltip_manager.cpp \
utils.cpp \
validators.cpp \
variable_data.cpp \
vector2d.cpp \
version.cpp \
video_box.cpp \

View File

@ -39,6 +39,7 @@
#include "ass_dialogue.h"
#include "ass_override.h"
#include "compat.h"
#include "utils.h"
#include <boost/algorithm/string/join.hpp>
@ -50,6 +51,84 @@
using namespace boost::adaptors;
AssOverrideParameter::AssOverrideParameter(VariableDataType type, AssParameterClass classification)
: type(type)
, classification(classification)
{
}
AssOverrideParameter::AssOverrideParameter(AssOverrideParameter&& o)
: value(std::move(o.value))
, block(std::move(o.block))
, type(o.type)
, classification(o.classification)
{
}
AssOverrideParameter::~AssOverrideParameter() {
}
template<> wxString AssOverrideParameter::Get<wxString>() const {
if (omitted) throw agi::InternalError("AssOverrideParameter::Get() called on omitted parameter", 0);
if (block.get()) {
wxString str(block->GetText());
str.Replace("{", "");
str.Replace("}", "");
return str;
}
return value;
}
template<> int AssOverrideParameter::Get<int>() const {
long v = 0;
Get<wxString>().ToLong(&v);
return v;
}
template<> double AssOverrideParameter::Get<double>() const {
double v = 0;
Get<wxString>().ToDouble(&v);
return v;
}
template<> float AssOverrideParameter::Get<float>() const {
return Get<double>();
}
template<> bool AssOverrideParameter::Get<bool>() const {
return Get<int>() != 0;
}
template<> agi::Color AssOverrideParameter::Get<agi::Color>() const {
return from_wx(Get<wxString>());
}
template<> AssDialogueBlockOverride *AssOverrideParameter::Get<AssDialogueBlockOverride*>() const {
if (!block.get()) {
block.reset(new AssDialogueBlockOverride(Get<wxString>()));
block->ParseTags();
}
return block.get();
}
template<> void AssOverrideParameter::Set<wxString>(wxString new_value) {
omitted = false;
value = new_value;
block.reset();
}
template<> void AssOverrideParameter::Set<int>(int new_value) {
Set(wxString::Format("%d", new_value));
}
template<> void AssOverrideParameter::Set<double>(double new_value) {
Set(wxString::Format("%g", new_value));
}
template<> void AssOverrideParameter::Set<bool>(bool new_value) {
Set<int>(new_value);
}
namespace {
/// The parameter is absent unless the total number of parameters is the
/// indicated number. Note that only arguments not at the end need to be marked
@ -324,75 +403,19 @@ void parse_parameters(AssOverrideTag *tag, const wxString &text, AssOverrideTagP
unsigned curPar = 0;
for (auto& curproto : proto_it->params) {
// Create parameter
tag->Params.emplace_back();
tag->Params.emplace_back(curproto.type, curproto.classification);
AssOverrideParameter *newparam = &tag->Params.back();
newparam->classification = curproto.classification;
// Check if it's optional and not present
if (!(curproto.optional & parsFlag) || curPar >= totalPars)
continue;
wxString curtok = paramList[curPar++];
if (curtok.empty()) {
curPar++;
continue;
}
wxChar firstChar = curtok[0];
bool auto4 = (firstChar == '!' || firstChar == '$' || firstChar == '%') && curproto.type != VARDATA_BLOCK;
if (auto4) {
newparam->Set(curtok);
continue;
}
switch (curproto.type) {
case VARDATA_INT: {
long temp;
curtok.ToLong(&temp);
newparam->Set<int>(temp);
break;
}
case VARDATA_FLOAT: {
double temp;
curtok.ToDouble(&temp);
newparam->Set(temp);
break;
}
case VARDATA_TEXT:
newparam->Set(curtok);
break;
case VARDATA_BOOL: {
long temp;
curtok.ToLong(&temp);
newparam->Set<bool>(temp != 0);
break;
}
case VARDATA_BLOCK: {
AssDialogueBlockOverride *temp = new AssDialogueBlockOverride(curtok);
temp->ParseTags();
newparam->Set(temp);
break;
}
default:
break;
}
tag->Params.back().Set(paramList[curPar++]);
}
}
}
AssOverrideParameter::AssOverrideParameter()
: classification(PARCLASS_NORMAL)
{
}
AssOverrideParameter::AssOverrideParameter(AssOverrideParameter&& o)
: VariableData(std::move(o))
, classification(o.classification)
{
}
// From ass_dialogue.h
AssDialogueBlockOverride::~AssDialogueBlockOverride() {
delete_clear(Tags);
@ -409,9 +432,8 @@ void AssDialogueBlockOverride::ParseTags() {
curTag += tkn.GetNextToken();
// Check for parenthesis matching for \t
while (curTag.Freq('(') > curTag.Freq(')') && tkn.HasMoreTokens()) {
while (curTag.Freq('(') > curTag.Freq(')') && tkn.HasMoreTokens())
curTag << "\\" << tkn.GetNextToken();
}
Tags.push_back(new AssOverrideTag(curTag));
@ -431,7 +453,7 @@ wxString AssDialogueBlockOverride::GetText() {
void AssDialogueBlockOverride::ProcessParameters(ProcessParametersCallback callback, void *userData) {
for (auto tag : Tags) {
for (auto& par : tag->Params) {
if (par.GetType() == VARDATA_NONE) continue;
if (par.omitted) continue;
callback(tag->Name, &par, userData);
@ -478,7 +500,7 @@ AssOverrideTag::operator wxString() const {
// Add parameters
result += join(Params
| filtered([](AssOverrideParameter const& p) { return p.GetType() != VARDATA_NONE; })
| filtered([](AssOverrideParameter const& p) { return !p.omitted; } )
| transformed(param_str),
wxS(","));

View File

@ -32,9 +32,12 @@
/// @ingroup subs_storage
///
#include <boost/noncopyable.hpp>
#include <memory>
#include <vector>
#include "variable_data.h"
class AssDialogueBlockOverride;
class wxString;
/// Type of parameter; probably only used by the resample tool
enum AssParameterClass {
@ -50,15 +53,37 @@ enum AssParameterClass {
PARCLASS_DRAWING
};
enum VariableDataType {
VARDATA_INT,
VARDATA_FLOAT,
VARDATA_TEXT,
VARDATA_BOOL,
VARDATA_BLOCK
};
/// A single parameter to an override tag
class AssOverrideParameter : public VariableData {
class AssOverrideParameter : boost::noncopyable {
wxString value;
mutable std::unique_ptr<AssDialogueBlockOverride> block;
VariableDataType type;
public:
AssOverrideParameter(VariableDataType type, AssParameterClass classification);
AssOverrideParameter(AssOverrideParameter&&);
~AssOverrideParameter();
/// Type of parameter
AssParameterClass classification;
AssOverrideParameter();
/// Is this parameter actually present?
bool omitted;
VariableDataType GetType() const { return type; }
template<class T> void Set(T param);
template<class T> T Get() const;
template<class T> T Get(T def) const {
return !omitted ? Get<T>() : def;
}
};
class AssOverrideTag : boost::noncopyable {

View File

@ -130,7 +130,7 @@ namespace
italic = t->Params[0].Get<bool>(style_italic);
else if (t->Name == "\\an")
align = t->Params[0].Get<int>(align);
else if (t->Name == "\\a" && t->Params[0].GetType() != VARDATA_NONE)
else if (t->Name == "\\a" && !t->Params[0].omitted)
align = AssStyle::SsaToAss(t->Params[0].Get<int>());
}
}

View File

@ -1,178 +0,0 @@
// Copyright (c) 2005, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Aegisub Project http://www.aegisub.org/
/// @file variable_data.cpp
/// @brief A variant-type implementation
/// @ingroup utility subs_storage
#include "config.h"
#include "variable_data.h"
#include "ass_dialogue.h"
#include "ass_style.h"
#include "compat.h"
#include "utils.h"
#include <libaegisub/color.h>
VariableData::VariableData() {
type = VARDATA_NONE;
value = nullptr;
}
VariableData::VariableData(VariableData&& o)
: value(o.value)
, type(o.type)
{
}
VariableData::~VariableData() {
DeleteValue();
}
void VariableData::DeleteValue() {
if (!value) return;
if (type == VARDATA_NONE) return;
switch (type) {
case VARDATA_INT: delete value_int; break;
case VARDATA_FLOAT: delete value_float; break;
case VARDATA_TEXT: delete value_text; break;
case VARDATA_BOOL: delete value_bool; break;
case VARDATA_COLOUR: delete value_colour; break;
case VARDATA_BLOCK: delete *value_block; delete value_block; break;
default: break;
}
type = VARDATA_NONE;
value = nullptr;
}
template<class T> static inline VariableDataType get_type();
template<> inline VariableDataType get_type<int>() {
return VARDATA_INT;
}
template<> inline VariableDataType get_type<float>() {
return VARDATA_FLOAT;
}
template<> inline VariableDataType get_type<double>() {
return VARDATA_FLOAT;
}
template<> inline VariableDataType get_type<bool>() {
return VARDATA_BOOL;
}
template<> inline VariableDataType get_type<wxString>() {
return VARDATA_TEXT;
}
template<> inline VariableDataType get_type<agi::Color>() {
return VARDATA_COLOUR;
}
template<> inline VariableDataType get_type<AssDialogueBlockOverride *>() {
return VARDATA_BLOCK;
}
template<class T>
void VariableData::Set(T param) {
DeleteValue();
type = get_type<T>();
value = new T(param);
}
template void VariableData::Set<int>(int param);
template void VariableData::Set<float>(float param);
template void VariableData::Set<double>(double param);
template void VariableData::Set<bool>(bool param);
template void VariableData::Set(wxString param);
template void VariableData::Set<agi::Color>(agi::Color param);
template void VariableData::Set<AssDialogueBlockOverride *>(AssDialogueBlockOverride * param);
template<> int VariableData::Get<int>() const {
if (!value) throw "Null parameter";
if (type == VARDATA_BOOL) return !!(*value_bool);
if (type == VARDATA_INT) return *value_int;
if (type == VARDATA_FLOAT) return (int)(*value_float);
if (type == VARDATA_TEXT) return 0;
throw "Wrong parameter type, should be int";
}
template<> float VariableData::Get<float>() const {
if (!value) throw "Null parameter";
if (type == VARDATA_FLOAT) return (float)*value_float;
if (type == VARDATA_INT) return (float)(*value_int);
if (type == VARDATA_TEXT) return 0.0f;
throw "Wrong parameter type, should be float";
}
template<> double VariableData::Get<double>() const {
if (!value) throw "Null parameter";
if (type == VARDATA_FLOAT) return *value_float;
if (type == VARDATA_INT) return (float)(*value_int);
if (type == VARDATA_TEXT) return 0.0;
throw "Wrong parameter type, should be float";
}
template<> bool VariableData::Get<bool>() const {
if (!value) throw "Null parameter";
if (type == VARDATA_BOOL) return *value_bool;
if (type == VARDATA_INT) return ((*value_int)!=0);
if (type == VARDATA_FLOAT) return ((*value_float)!=0);
if (type == VARDATA_TEXT) return false;
throw "Wrong parameter type, should be bool";
}
template<> agi::Color VariableData::Get<agi::Color>() const {
if (!value) throw "Null parameter";
if (type == VARDATA_COLOUR) return *value_colour;
else if (type == VARDATA_TEXT) {
return agi::Color(from_wx(*value_text));
}
else throw "Wrong parameter type, should be colour";
}
template<> AssDialogueBlockOverride *VariableData::Get<AssDialogueBlockOverride *>() const {
if (!value) throw "Null parameter";
if (type != VARDATA_BLOCK) throw "Wrong parameter type, should be block";
return *value_block;
}
template<> wxString VariableData::Get<wxString>() const {
if (!value) throw "Null parameter";
if (type != VARDATA_TEXT) {
if (type == VARDATA_INT) return wxString::Format("%i",*value_int);
if (type == VARDATA_FLOAT) return wxString::Format("%g",*value_float);
if (type == VARDATA_COLOUR) return to_wx(value_colour->GetHexFormatted());
if (type == VARDATA_BOOL) return *value_bool ? "1" : "0";
if (type == VARDATA_BLOCK) {
wxString str((*value_block)->GetText());
str.Replace("{", "");
str.Replace("}", "");
return str;
}
throw "Wrong parameter type, should be text";
}
return *value_text;
}

View File

@ -1,82 +0,0 @@
// Copyright (c) 2005, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Aegisub Project http://www.aegisub.org/
/// @file variable_data.h
/// @see variable_data.cpp
/// @ingroup utility subs_storage
///
#pragma once
#include <boost/noncopyable.hpp>
namespace agi { struct Color; }
class wxString;
enum VariableDataType {
VARDATA_NONE,
VARDATA_INT,
VARDATA_FLOAT,
VARDATA_TEXT,
VARDATA_BOOL,
VARDATA_COLOUR,
VARDATA_BLOCK
};
class AssDialogueBlockOverride;
class VariableData : private boost::noncopyable {
private:
union {
void *value;
int *value_int;
double *value_float;
bool *value_bool;
wxString *value_text;
agi::Color *value_colour;
AssDialogueBlockOverride **value_block;
};
VariableDataType type;
protected:
void DeleteValue();
public:
VariableData();
VariableData(VariableData&& o);
virtual ~VariableData();
VariableDataType GetType() const { return type; }
template<class T> void Set(T param);
template<class T> T Get() const;
template<class T> T Get(T def) const {
return value ? Get<T>() : def;
}
};

View File

@ -373,7 +373,7 @@ static param_vec find_tag(boost::ptr_vector<AssDialogueBlock>& blocks, wxString
static Vector2D vec_or_bad(param_vec tag, size_t x_idx, size_t y_idx) {
if (!tag ||
tag->size() <= x_idx || tag->size() <= y_idx ||
(*tag)[x_idx].GetType() == VARDATA_NONE || (*tag)[y_idx].GetType() == VARDATA_NONE)
(*tag)[x_idx].omitted || (*tag)[y_idx].omitted)
{
return Vector2D();
}
@ -401,8 +401,8 @@ Vector2D VisualToolBase::GetLinePosition(AssDialogue *diag) {
param_vec align_tag;
int ovr_align = 0;
if ((align_tag = find_tag(blocks, "\\an")) && (*align_tag)[0].GetType() != VARDATA_NONE)
ovr_align = (*align_tag)[0].Get<int>();
if ((align_tag = find_tag(blocks, "\\an")))
ovr_align = (*align_tag)[0].Get<int>(ovr_align);
else if ((align_tag = find_tag(blocks, "\\a")))
ovr_align = AssStyle::SsaToAss((*align_tag)[0].Get<int>(2));
@ -462,13 +462,13 @@ void VisualToolBase::GetLineRotation(AssDialogue *diag, float &rx, float &ry, fl
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
if (param_vec tag = find_tag(blocks, "\\frx"))
rx = tag->front().Get<float>(rx);
rx = tag->front().Get(rx);
if (param_vec tag = find_tag(blocks, "\\fry"))
ry = tag->front().Get<float>(ry);
ry = tag->front().Get(ry);
if (param_vec tag = find_tag(blocks, "\\frz"))
rz = tag->front().Get<float>(rz);
rz = tag->front().Get(rz);
else if ((tag = find_tag(blocks, "\\fr")))
rz = tag->front().Get<float>(rz);
rz = tag->front().Get(rz);
}
void VisualToolBase::GetLineScale(AssDialogue *diag, Vector2D &scale) {
@ -482,9 +482,9 @@ void VisualToolBase::GetLineScale(AssDialogue *diag, Vector2D &scale) {
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
if (param_vec tag = find_tag(blocks, "\\fscx"))
x = tag->front().Get<float>(x);
x = tag->front().Get(x);
if (param_vec tag = find_tag(blocks, "\\fscy"))
y = tag->front().Get<float>(y);
y = tag->front().Get(y);
scale = Vector2D(x, y);
}