mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
Addded script functions for exporting, ExportTemplate package type
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@220 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -209,7 +209,7 @@ void Context::closeScope(size_t scope) {
|
||||
void instrUnary (UnaryInstructionType i, ScriptValueP& a) {
|
||||
switch (i) {
|
||||
case I_ITERATOR_C:
|
||||
a = a->makeIterator();
|
||||
a = a->makeIterator(a);
|
||||
break;
|
||||
case I_NEGATE:
|
||||
a = to_script(-(int)*a);
|
||||
|
||||
@@ -48,8 +48,8 @@ class DependencyUnion : public ScriptValue {
|
||||
virtual ScriptValueP dependencies(Context& ctx, const Dependency& dep) const {
|
||||
return unified( a->dependencies(ctx,dep), b->dependencies(ctx,dep));
|
||||
}
|
||||
virtual ScriptValueP makeIterator() const {
|
||||
return unified(a->makeIterator(), b->makeIterator());
|
||||
virtual ScriptValueP makeIterator(ScriptValueP thisP) const {
|
||||
return unified(a->makeIterator(thisP), b->makeIterator(thisP));
|
||||
}
|
||||
virtual ScriptValueP dependencyMember(const String& name, const Dependency& dep) const {
|
||||
return unified(a->dependencyMember(name,dep), b->dependencyMember(name,dep));
|
||||
@@ -279,7 +279,7 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script)
|
||||
ScriptValueP& a = stack.back();
|
||||
switch (i.instr1) {
|
||||
case I_ITERATOR_C:
|
||||
a = a->makeIterator(); // as normal
|
||||
a = a->makeIterator(a); // as normal
|
||||
break;
|
||||
default:
|
||||
a = dependency_dummy;
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <data/set.hpp>
|
||||
#include <data/game.hpp>
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(pair<String COMMA ScriptValueP>);
|
||||
|
||||
// ----------------------------------------------------------------------------- : String stuff
|
||||
|
||||
// convert a string to upper case
|
||||
@@ -147,7 +149,7 @@ int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const Scr
|
||||
}
|
||||
} else {
|
||||
// unordered position
|
||||
ScriptValueP it = in->makeIterator();
|
||||
ScriptValueP it = in->makeIterator(in);
|
||||
int i = 0;
|
||||
while (ScriptValueP v = it->next()) {
|
||||
if (equal(*of, *v)) return i;
|
||||
@@ -157,6 +159,34 @@ int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const Scr
|
||||
return -1; // TODO?
|
||||
}
|
||||
|
||||
// sort a script list
|
||||
ScriptValueP sort_script(Context& ctx, const ScriptValueP& list, ScriptValue& order_by) {
|
||||
ScriptType list_t = list->type();
|
||||
if (list_t == SCRIPT_STRING) {
|
||||
// sort a string
|
||||
String s = list->toString();
|
||||
sort(s.begin(), s.end());
|
||||
SCRIPT_RETURN(s);
|
||||
} else {
|
||||
// are we sorting a set
|
||||
ScriptObject<Set*>* set = dynamic_cast<ScriptObject<Set*>*>(list.get());
|
||||
// sort a collection
|
||||
vector<pair<String,ScriptValueP> > values;
|
||||
ScriptValueP it = list->makeIterator(list);
|
||||
while (ScriptValueP v = it->next()) {
|
||||
ctx.setVariable(set ? _("card") : _("input"), v);
|
||||
values.push_back(make_pair(order_by.eval(ctx)->toString(), v));
|
||||
}
|
||||
sort(values.begin(), values.end());
|
||||
// return collection
|
||||
intrusive_ptr<ScriptCustomCollection> ret(new ScriptCustomCollection());
|
||||
FOR_EACH(v, values) {
|
||||
ret->value.push_back(v.second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// finding positions, also of substrings
|
||||
SCRIPT_FUNCTION_WITH_DEP(position_of) {
|
||||
ScriptValueP of = ctx.getVariable(_("of"));
|
||||
@@ -436,12 +466,66 @@ String spec_sort(const String& spec, const String& input) {
|
||||
}
|
||||
|
||||
|
||||
// Create a rule for spec_sorting strings
|
||||
SCRIPT_RULE_1(sort, String, order) {
|
||||
SCRIPT_PARAM(String, input);
|
||||
SCRIPT_RETURN(spec_sort(order, input));
|
||||
}
|
||||
// Sort using spec_sort
|
||||
class ScriptRule_sort_order: public ScriptValue {
|
||||
public:
|
||||
inline ScriptRule_sort_order(const String& order) : order(order) {}
|
||||
virtual ScriptType type() const { return SCRIPT_FUNCTION; }
|
||||
virtual String typeName() const { return _("sort_rule"); }
|
||||
virtual ScriptValueP eval(Context& ctx) const {
|
||||
SCRIPT_PARAM(String, input);
|
||||
SCRIPT_RETURN(spec_sort(order, input));
|
||||
}
|
||||
private:
|
||||
String order;
|
||||
};
|
||||
// Sort using sort_script
|
||||
class ScriptRule_sort_order_by: public ScriptValue {
|
||||
public:
|
||||
inline ScriptRule_sort_order_by(const ScriptValueP& order_by) : order_by(order_by) {}
|
||||
virtual ScriptType type() const { return SCRIPT_FUNCTION; }
|
||||
virtual String typeName() const { return _("sort_rule"); }
|
||||
virtual ScriptValueP eval(Context& ctx) const {
|
||||
SCRIPT_PARAM(ScriptValueP, input);
|
||||
return sort_script(ctx, input, *order_by);
|
||||
}
|
||||
private:
|
||||
ScriptValueP order_by;
|
||||
};
|
||||
// Sort a string alphabetically
|
||||
class ScriptRule_sort: public ScriptValue {
|
||||
public:
|
||||
virtual ScriptType type() const { return SCRIPT_FUNCTION; }
|
||||
virtual String typeName() const { return _("sort_rule"); }
|
||||
virtual ScriptValueP eval(Context& ctx) const {
|
||||
SCRIPT_PARAM(String, input);
|
||||
sort(input.begin(), input.end());
|
||||
SCRIPT_RETURN(input);
|
||||
}
|
||||
private:
|
||||
ScriptValueP order_by;
|
||||
};
|
||||
|
||||
SCRIPT_FUNCTION(sort_rule) {
|
||||
SCRIPT_OPTIONAL_PARAM(String, order) {
|
||||
return new_intrusive1<ScriptRule_sort_order >(order);
|
||||
}
|
||||
SCRIPT_OPTIONAL_PARAM(ScriptValueP, order_by) {
|
||||
return new_intrusive1<ScriptRule_sort_order_by>(order_by);
|
||||
} else {
|
||||
return new_intrusive <ScriptRule_sort >();
|
||||
}
|
||||
}
|
||||
SCRIPT_FUNCTION(sort) {
|
||||
SCRIPT_OPTIONAL_PARAM(String, order) {
|
||||
return ScriptRule_sort_order (order ).eval(ctx);
|
||||
}
|
||||
SCRIPT_OPTIONAL_PARAM(ScriptValueP, order_by) {
|
||||
return ScriptRule_sort_order_by(order_by).eval(ctx);
|
||||
} else {
|
||||
return ScriptRule_sort ( ).eval(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Init
|
||||
|
||||
|
||||
@@ -7,10 +7,116 @@
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <script/functions/functions.hpp>
|
||||
#include <script/functions/util.hpp>
|
||||
#include <util/tagged_string.hpp>
|
||||
|
||||
// ----------------------------------------------------------------------------- : Numbers
|
||||
|
||||
/// Write a number using words, for example 23 -> "twenty-three"
|
||||
String english_number(int i) {
|
||||
switch (i) {
|
||||
case 0: return _("zero");
|
||||
case 1: return _("one");
|
||||
case 2: return _("two");
|
||||
case 3: return _("three");
|
||||
case 4: return _("four");
|
||||
case 5: return _("five");
|
||||
case 6: return _("six");
|
||||
case 7: return _("seven");
|
||||
case 8: return _("eight");
|
||||
case 9: return _("nine");
|
||||
case 10: return _("ten");
|
||||
case 11: return _("eleven");
|
||||
case 12: return _("twelve");
|
||||
case 13: return _("thirteen");
|
||||
case 15: return _("fifteen");
|
||||
case 18: return _("eighteen");
|
||||
case 20: return _("twenty");
|
||||
case 30: return _("thirty");
|
||||
case 50: return _("fifty");
|
||||
case 80: return _("eighty");
|
||||
default: {
|
||||
if (i < 0 || i >= 100) {
|
||||
// number too large, keep as digits
|
||||
return (String() << i);
|
||||
} else if (i < 20) {
|
||||
return english_number(i%10) + english_number(10);
|
||||
} else if (i % 10 == 0) {
|
||||
return english_number(i/10) + _("ty");
|
||||
} else {
|
||||
// <a>ty-<b>
|
||||
return english_number(i/10*10) + _("-") + english_number(i%10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(english_number) {
|
||||
SCRIPT_PARAM(int, input);
|
||||
SCRIPT_RETURN(english_number(input));
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(english_number_a) {
|
||||
SCRIPT_PARAM(int, input);
|
||||
if (input == 1) {
|
||||
SCRIPT_RETURN(_("a"));
|
||||
} else {
|
||||
SCRIPT_RETURN(english_number(input));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : A/an
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- : Singular/plural
|
||||
|
||||
// ----------------------------------------------------------------------------- : Hints
|
||||
|
||||
// insert a hint, <hint-1> for singular, <hint-2> otherwise
|
||||
SCRIPT_FUNCTION(plural_hint) {
|
||||
SCRIPT_PARAM(int, input);
|
||||
SCRIPT_RETURN(input == 1 ? _("<hint-1>") : _("<hint-2>"));
|
||||
}
|
||||
|
||||
/// Process english hints in the input string
|
||||
/** Hints have the following meaning:
|
||||
* - "<hint-1>xxx(yyy)zzz" ---> "xxxzzz" (singular)
|
||||
* - "<hint-2>xxx(yyy)zzz" ---> "xxxyyyzzz" (plural)
|
||||
* - "[^., ]a <hint-v>[aeiou]" ---> "\1 an \2" (articla 'an', case insensitive)
|
||||
* - "<hint-?>" ---> "" (remove <hint>s afterwards)
|
||||
*
|
||||
* Note: there is no close tags for hints
|
||||
*/
|
||||
String process_english_hints(const String& str) {
|
||||
String ret; ret.reserve(str.size());
|
||||
int singplur = 0; // 1 for singular, 2 for plural
|
||||
for (size_t i = 0 ; i < str.size() ; ) {
|
||||
Char c = str.GetChar(i);
|
||||
if (i + 6 < str.size() && is_substr(str, i, _("<hint-"))) {
|
||||
Char h = str.GetChar(i + 6); // hint code
|
||||
if (h == _('1')) {
|
||||
singplur = 1;
|
||||
} else if (h == _('2')) {
|
||||
singplur = 2;
|
||||
} else if (h == _('v')) {
|
||||
// TODO
|
||||
}
|
||||
i = skip_tag(str, i);
|
||||
} else if (c == _('(') && singplur) {
|
||||
// singular -> drop (...), plural -> keep it
|
||||
// TODO
|
||||
} else {
|
||||
ret += c;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return ret; // TODO
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- : Init
|
||||
|
||||
void init_script_english_functions(Context& ctx) {
|
||||
ctx.setVariable(_("english number"), script_english_number);
|
||||
ctx.setVariable(_("english number a"), script_english_number_a);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,226 @@
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <script/functions/functions.hpp>
|
||||
#include <script/functions/util.hpp>
|
||||
#include <data/symbol_font.hpp>
|
||||
#include <util/tagged_string.hpp>
|
||||
#include <util/error.hpp>
|
||||
|
||||
// ----------------------------------------------------------------------------- :
|
||||
// ----------------------------------------------------------------------------- : HTML
|
||||
|
||||
// An HTML tag
|
||||
struct Tag {
|
||||
Tag(const Char* open_tag, const Char* close_tag)
|
||||
: open_tag(open_tag), close_tag(close_tag), opened(0)
|
||||
{}
|
||||
const Char* open_tag; ///< The tags to insert in HTML "<tag>"
|
||||
const Char* close_tag; ///< The tags to insert in HTML "</tag>"
|
||||
int opened; ///< How often is the tag opened in the input?
|
||||
/// Write an open or close tag to a string if needed
|
||||
void write(String& ret, bool close) {
|
||||
if (close) {
|
||||
if (--opened == 0) {
|
||||
ret += close_tag;
|
||||
}
|
||||
} else {
|
||||
if (++opened == 1) {
|
||||
ret += open_tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// A tag, or a close tag
|
||||
struct NegTag {
|
||||
Tag* tag;
|
||||
bool neg; // a close tag instead of an open tag
|
||||
NegTag(Tag* tag, bool neg) : tag(tag), neg(neg) {}
|
||||
};
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(NegTag);
|
||||
|
||||
/// A stack of opened HTML tags
|
||||
class TagStack {
|
||||
public:
|
||||
void open(String& ret, Tag& tag) {
|
||||
add(ret, NegTag(&tag, false));
|
||||
}
|
||||
void close(String& ret, Tag& tag) {
|
||||
add(ret, NegTag(&tag, true));
|
||||
}
|
||||
// Close all tags, should be called at end of input
|
||||
void close_all(String& ret) {
|
||||
pending_tags.clear();
|
||||
while (!tags.empty()) {
|
||||
tags.back()->write(ret, true);
|
||||
tags.pop_back();
|
||||
}
|
||||
}
|
||||
// Write all pending tags, should be called before non-tag output
|
||||
void write_pending_tags(String& ret) {
|
||||
FOR_EACH(t, pending_tags) {
|
||||
t.tag->write(ret, t.neg);
|
||||
if (!t.neg) tags.push_back(t.tag);
|
||||
}
|
||||
pending_tags.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
vector<Tag*> tags; ///< Tags opened in the html output
|
||||
vector<NegTag> pending_tags; ///< Tags opened in the tagged string, but not (yet) in the output
|
||||
|
||||
void add(String& ret, const NegTag& tag) {
|
||||
// Cancel out with pending tag?
|
||||
for (size_t i = pending_tags.size() - 1 ; i >= 0 ; --i) {
|
||||
if (pending_tags[i].tag == tag.tag) {
|
||||
if (pending_tags[i].neg != tag.neg) {
|
||||
pending_tags.erase(pending_tags.begin() + i);
|
||||
return;
|
||||
} else {
|
||||
break; // look no further
|
||||
}
|
||||
}
|
||||
}
|
||||
// Cancel out with existing tag?
|
||||
if (tag.neg) {
|
||||
for (size_t i = tags.size() - 1 ; i >= 0 ; --i) {
|
||||
if (tags[i] == tag.tag) {
|
||||
// cancel out with existing tag i, e.g. <b>:
|
||||
// situation was <a><b><c>text
|
||||
// situation will become <a><b><c>text</c></b><c>
|
||||
vector<NegTag> reopen;
|
||||
for (size_t j = tags.size() - 1 ; j > i ; --j) {
|
||||
pending_tags.push_back(NegTag(tags[j], true)); // close tag, top down
|
||||
tags.pop_back();
|
||||
}
|
||||
pending_tags.push_back(tag); // now close tag i
|
||||
for (size_t j = i + 1 ; j < tags.size() ; ++j) {
|
||||
pending_tags.push_back(NegTag(tags[j], false)); // reopen later, bottom up
|
||||
tags.pop_back();
|
||||
}
|
||||
tags.resize(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Just insert normally
|
||||
pending_tags.push_back(tag);
|
||||
}
|
||||
};
|
||||
|
||||
String symbols_to_html(const String& str, const SymbolFontP& symbol_font) {
|
||||
return str; // TODO
|
||||
}
|
||||
|
||||
String to_html(const String& str_in, const SymbolFontP& symbol_font) {
|
||||
String str = remove_tag_contents(str,_("<sep-soft"));
|
||||
String ret;
|
||||
Tag bold (_("<b>"), _("</b>")),
|
||||
italic(_("<i>"), _("</i>")),
|
||||
symbol(_("<span class=\"symbol\">"), _("</span>"));
|
||||
TagStack tags;
|
||||
String symbols;
|
||||
for (size_t i = 0 ; i < str.size() ; ) {
|
||||
Char c = str.GetChar(i);
|
||||
if (c == _('<')) {
|
||||
++i;
|
||||
if (is_substr(str, i, _("b"))) {
|
||||
tags.open (ret, bold);
|
||||
} else if (is_substr(str, i, _("/b"))) {
|
||||
tags.close(ret, bold);
|
||||
} else if (is_substr(str, i, _("i"))) {
|
||||
tags.open (ret, italic);
|
||||
} else if (is_substr(str, i, _("/i"))) {
|
||||
tags.close(ret, italic);
|
||||
} else if (is_substr(str, i, _("sym"))) {
|
||||
tags.close(ret, symbol);
|
||||
} else if (is_substr(str, i, _("/sym"))) {
|
||||
if (!symbols.empty()) {
|
||||
// write symbols in a special way
|
||||
tags.write_pending_tags(ret);
|
||||
ret += symbols_to_html(symbols, symbol_font);
|
||||
symbols.clear();
|
||||
}
|
||||
tags.close(ret, symbol);
|
||||
}
|
||||
i = skip_tag(str, i-1);
|
||||
} else {
|
||||
// normal character
|
||||
tags.write_pending_tags(ret);
|
||||
++i;
|
||||
if (symbol.opened > 0 && symbol_font) {
|
||||
symbols += c; // write as symbols instead
|
||||
} else {
|
||||
if (c == _('\1')) { // escape <
|
||||
ret += _("<");
|
||||
} else if (c == _('&')) { // escape &
|
||||
ret += _("&");
|
||||
} else if (c >= 0x80) { // escape non ascii
|
||||
ret += String(_("&#")) << (int)c << _(';');
|
||||
} else {
|
||||
ret += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// end of input
|
||||
if (!symbols.empty()) {
|
||||
tags.write_pending_tags(ret);
|
||||
ret += symbols_to_html(symbols, symbol_font);
|
||||
symbols.clear();
|
||||
}
|
||||
tags.close_all(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// convert a tagged string to html
|
||||
SCRIPT_FUNCTION(to_html) {
|
||||
SCRIPT_PARAM(String, input);
|
||||
SymbolFontP symbol_font; // TODO
|
||||
SCRIPT_RETURN(to_html(input, symbol_font));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Text
|
||||
|
||||
// convert a tagged string to plain text
|
||||
SCRIPT_FUNCTION(to_text) {
|
||||
SCRIPT_PARAM(String, input);
|
||||
SCRIPT_RETURN(untag_hide_sep(input));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Files
|
||||
|
||||
// copy from source package -> destination package, return new filename (relative)
|
||||
SCRIPT_FUNCTION(copy_file) {
|
||||
throw InternalError(_("TODO: copy_file")); // TODO
|
||||
}
|
||||
|
||||
// write a file to the destination package.
|
||||
// if 'filename' is not set, writes to the 'main' output file.
|
||||
SCRIPT_FUNCTION(write_file) {
|
||||
throw InternalError(_("TODO: write_file")); // TODO
|
||||
}
|
||||
|
||||
// write an ImageValue to a new file, return the filename
|
||||
// if the image was not written, return nil
|
||||
// TODO: write a ScriptImage?
|
||||
SCRIPT_FUNCTION(image_to_file) {
|
||||
throw InternalError(_("TODO: image_to_file")); // TODO
|
||||
}
|
||||
|
||||
// render a card, and write the image to a file
|
||||
SCRIPT_FUNCTION(render_to_file) {
|
||||
throw InternalError(_("TODO: render_to_file")); // TODO
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Init
|
||||
|
||||
void init_script_export_functions(Context& ctx) {
|
||||
ctx.setVariable(_("to html"), script_to_html);
|
||||
ctx.setVariable(_("to text"), script_to_text);
|
||||
ctx.setVariable(_("copy file"), script_copy_file);
|
||||
ctx.setVariable(_("write file"), script_write_file);
|
||||
ctx.setVariable(_("image to file"), script_image_to_file);
|
||||
ctx.setVariable(_("write image"), script_image_to_file);
|
||||
ctx.setVariable(_("render to file"), script_render_to_file);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <util/prec.hpp>
|
||||
#include <util/error.hpp>
|
||||
#include <script/to_value.hpp>
|
||||
#include <script/context.hpp>
|
||||
|
||||
// ----------------------------------------------------------------------------- : Functions
|
||||
|
||||
|
||||
+20
-3
@@ -62,7 +62,7 @@ class ScriptCollection : public ScriptValue {
|
||||
return ScriptValue::getMember(name);
|
||||
}
|
||||
}
|
||||
virtual ScriptValueP makeIterator() const {
|
||||
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const {
|
||||
return new_intrusive1<ScriptCollectionIterator<Collection> >(value);
|
||||
}
|
||||
virtual int itemCount() const { return (int)value->size(); }
|
||||
@@ -113,6 +113,23 @@ class ScriptMap : public ScriptValue {
|
||||
const Collection* value;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Collections : from script
|
||||
|
||||
/// Script value containing a custom collection, returned from script functions
|
||||
class ScriptCustomCollection : public ScriptValue {
|
||||
public:
|
||||
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
||||
virtual String typeName() const { return _TYPE_("collection"); }
|
||||
virtual ScriptValueP getMember(const String& name) const;
|
||||
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const;
|
||||
virtual int itemCount() const { return (int)value.size(); }
|
||||
/// Collections can be compared by comparing pointers
|
||||
virtual const void* comparePointer() const { return &value; }
|
||||
|
||||
/// The collection
|
||||
vector<ScriptValueP> value;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Objects
|
||||
|
||||
/// Number of items in some collection like object, can be overloaded
|
||||
@@ -159,9 +176,9 @@ class ScriptObject : public ScriptValue {
|
||||
mark_dependency_member(value, name, dep);
|
||||
return getMember(name);
|
||||
}
|
||||
virtual ScriptValueP makeIterator() const {
|
||||
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const {
|
||||
ScriptValueP it = make_iterator(*value);
|
||||
return it ? it : ScriptValue::makeIterator();
|
||||
return it ? it : ScriptValue::makeIterator(thisP);
|
||||
}
|
||||
virtual int itemCount() const {
|
||||
int i = item_count(*value);
|
||||
|
||||
+41
-11
@@ -14,16 +14,16 @@
|
||||
// ----------------------------------------------------------------------------- : ScriptValue
|
||||
// Base cases
|
||||
|
||||
ScriptValue::operator String() const { return _("[[") + typeName() + _("]]"); }
|
||||
ScriptValue::operator int() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("integer" ))); }
|
||||
ScriptValue::operator double() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("real" ))); }
|
||||
ScriptValue::operator Color() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("color" ))); }
|
||||
ScriptValueP ScriptValue::eval(Context&) const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("function"))); }
|
||||
ScriptValueP ScriptValue::getMember(const String& name) const { throw ScriptError(_ERROR_2_("has no member", typeName(), name)); }
|
||||
ScriptValueP ScriptValue::next() { throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); }
|
||||
ScriptValueP ScriptValue::makeIterator() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
|
||||
int ScriptValue::itemCount() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
|
||||
const void* ScriptValue::comparePointer() const { return nullptr; }
|
||||
ScriptValue::operator String() const { return _("[[") + typeName() + _("]]"); }
|
||||
ScriptValue::operator int() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("integer" ))); }
|
||||
ScriptValue::operator double() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("real" ))); }
|
||||
ScriptValue::operator Color() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("color" ))); }
|
||||
ScriptValueP ScriptValue::eval(Context&) const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("function"))); }
|
||||
ScriptValueP ScriptValue::getMember(const String& name) const { throw ScriptError(_ERROR_2_("has no member", typeName(), name)); }
|
||||
ScriptValueP ScriptValue::next() { throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); }
|
||||
ScriptValueP ScriptValue::makeIterator(const ScriptValueP&) const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
|
||||
int ScriptValue::itemCount() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
|
||||
const void* ScriptValue::comparePointer() const { return nullptr; }
|
||||
|
||||
ScriptValueP ScriptValue::dependencyMember(const String& name, const Dependency&) const { return dependency_dummy; }
|
||||
ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; }
|
||||
@@ -236,5 +236,35 @@ class ScriptNil : public ScriptValue {
|
||||
/// The preallocated nil value
|
||||
ScriptValueP script_nil(new ScriptNil);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Custom collection
|
||||
|
||||
// Iterator over a custom collection
|
||||
class ScriptCustomCollectionIterator : public ScriptIterator {
|
||||
public:
|
||||
ScriptCustomCollectionIterator(const vector<ScriptValueP>* col, ScriptValueP colP)
|
||||
: pos(0), col(col), colP(colP) {}
|
||||
virtual ScriptValueP next() {
|
||||
if (pos < col->size()) {
|
||||
return to_script(col->at(pos++));
|
||||
} else {
|
||||
return ScriptValueP();
|
||||
}
|
||||
}
|
||||
private:
|
||||
size_t pos;
|
||||
ScriptValueP colP; // for ownership of the collection
|
||||
const vector<ScriptValueP>* col;
|
||||
};
|
||||
|
||||
ScriptValueP ScriptCustomCollection::getMember(const String& name) const {
|
||||
long index;
|
||||
if (name.ToLong(&index) && index >= 0 && (size_t)index < value.size()) {
|
||||
return to_script(value.at(index));
|
||||
} else {
|
||||
return ScriptValue::getMember(name);
|
||||
}
|
||||
}
|
||||
ScriptValueP ScriptCustomCollection::makeIterator(const ScriptValueP& thisP) const {
|
||||
return new_intrusive2<ScriptCustomCollectionIterator>(&value, thisP);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
@@ -74,7 +74,8 @@ class ScriptValue : public IntrusivePtrBase {
|
||||
virtual ScriptValueP dependencies(Context&, const Dependency&) const;
|
||||
|
||||
/// Return an iterator for the current collection, an iterator is a value that has next()
|
||||
virtual ScriptValueP makeIterator() const;
|
||||
/** thisP can be used to prevent destruction of the collection */
|
||||
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const;
|
||||
/// Return the next item for this iterator, or ScriptValueP() if there is no such item
|
||||
virtual ScriptValueP next();
|
||||
/// Return the number of items in this value (assuming it is a collection)
|
||||
|
||||
Reference in New Issue
Block a user