/* [<][>][^][v][top][bottom][index][help] */
//
// Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef GNASH_ABC_CLASS_H
#define GNASH_ABC_CLASS_H
#ifdef HAVE_CONFIG_H
#include "gnashconfig.h"
#endif
#include <list>
#include <map>
#include <vector>
#include "string_table.h"
#include "Property.h"
#include "AbcBlock.h"
namespace gnash {
namespace abc {
class Machine;
class MultiName;
class abc_function;
class BoundValue;
class BoundAccessor;
class Method;
class Class;
class Namespace;
}
class ClassHierarchy;
class Property;
class as_value;
}
namespace gnash {
namespace abc {
/// A class to represent AS3 Classes.
//
/// Used to store ABC classes. These are not themselves AS-referenceable
/// objects, but can be associated with AS3 Class objects in a way that
/// is yet to be determined.
//
/// TODO: update this documentation when we've worked it out.
//
/// An abc::Class is a static description of an ActionScript Class. Classes
/// have the following important properties:
//
/// 1. A static initialization method ("cinit"). This is executed during
/// the opcode NewClass, which is generally called only once per class.
/// 2. A constructor method ("iinit"). This is run every time the Class
/// is constructed. As not all Classes are constructed, the iinit method
/// may never be executed.
/// 3. A set of class Traits.
/// 4. A set of instance Traits.
//
/// Classes are parsed from the "instances" and "classes" section of an
/// ABCBlock. Each of these contains the same number of entries. The iinit
/// methods are found in the instances section, the cinit methods in the
/// classes section.
class Class
{
public:
Class()
:
_prototype(0),
_final(false),
_sealed(false),
_dynamic(false),
_interface(false),
_name(0),
_interfaces(),
_protectedNs(0),
_super(0),
_constructor(0),
_staticConstructor(0),
_bindings(),
_staticBindings(),
_declared(false),
_inherited(false),
_system(false)
{}
void setDeclared() { _declared = true; }
bool isDeclared() { return _declared; }
void setInherited() { _inherited = true; }
bool isInherited() { return _inherited; }
void setSystem() { _system = true; }
void unsetSystem() { _system = false; }
bool isSystem() { return _system; }
/// Set our Name
void setName(string_table::key name) { _name = name; }
void dump();
bool addValue(string_table::key name, Namespace *ns,
boost::uint32_t slotID, Class *type, as_value& val,
bool isconst, bool isstatic);
bool addSlot(string_table::key name, Namespace *ns,
boost::uint32_t slotID, Class *type, bool isstatic);
bool addMethod(string_table::key name, Namespace *ns, Method *method,
bool isstatic);
bool addGetter(string_table::key name, Namespace *ns, Method *method,
bool isstatic);
bool addSetter(string_table::key name, Namespace *ns, Method *method,
bool isstatic);
bool addMemberScript(string_table::key name, Namespace *ns,
boost::uint32_t slotID, Class *type, bool isstatic);
// TODO: Figure out how this differs from addMethod
bool addSlotFunction(string_table::key name, Namespace *ns,
boost::uint32_t slotID, Method *method, bool isstatic);
/// Is the class final?
bool isFinal() const { return _final; }
/// Set the class as final.
void setFinal() { _final = true; }
/// Set the class as not final.
void unsetFinal() { _final = false; }
/// Is the class sealed?
bool isSealed() const { return _sealed; }
/// Set the class as sealed.
void setSealed() { _sealed = true; }
// Set the class as not sealed.
void unsetSealed() { _sealed = false; }
/// Is the class an interface type?
bool isInterface() const { return _interface; }
/// Set the class as an interface.
void setInterface() { _interface = true; }
/// Set the class as not an interface.
void unsetInterface() { _interface = false; }
/// Is the class dynamic?
bool isDynamic() const { return _dynamic; }
/// Set the class as dynamic.
void setDynamic() { _dynamic = true; }
/// Set the class as not dynamic.
void unsetDynamic() { _dynamic = false; }
/// Does the class have a protected namespace to be inherited?
bool hasProtectedNs() const { return _protectedNs; }
/// Get the protected namespace.
Namespace* getProtectedNs() { return _protectedNs; }
/// Set the protected namespace.
void setProtectedNs(Namespace *n) { _protectedNs = n; }
/// The global name of the class.
string_table::key getName() const { return _name; }
/// Retrieve the Class from which this Class derives.
Class* getSuper() const { return _super; }
/// Set the Super Class.
//
/// This is the base class for this Class.
void setSuper(Class *p) { _super = p; }
/// We implement this interface.
void pushInterface(Class* p) { _interfaces.push_back(p); }
/// Set the iinit method.
//
/// This is used to construct instances of the Class.
void setConstructor(Method *m) { _constructor = m; }
/// Get the iinit method or 'constructor'.
//
/// A Class is also valid if it does not have an iinit method, so this
/// function can return 0.
Method* getConstructor() const {
return _constructor;
}
/// Set the cinit method
//
/// This is used to initialize the Class.
void setStaticConstructor(Method *m) { _staticConstructor = m; }
/// Get the cinit method or 'static constructor'.
//
/// A Class may have no cinit method, so this function can return 0.
Method* getStaticConstructor() const {
return _staticConstructor;
}
void addStaticTrait(const Trait& t) {
_staticTraits.push_back(t);
}
void addInstanceTrait(const Trait& t) {
_instanceTraits.push_back(t);
}
Property* getBinding(string_table::key name)
{
BindingContainer::iterator i;
if (_bindings.empty()) return NULL;
i = _bindings.find(name);
if (i == _bindings.end())
return NULL;
return &i->second;
}
Property* getGetBinding(as_value& v, abc::MultiName& n);
Property* getSetBinding(as_value& v, abc::MultiName& n);
/// This initializes all the traits.
//
/// Note: this is only necessary because the implementation is bogus.
/// TODO: fix it.
void initTraits(AbcBlock& bl);
/// Necessary for the current bogus implementation.
void setPrototype(as_object* prototype) {
_prototype = prototype;
}
/// Necessary for the current bogus implementation.
void initPrototype();
/// Necessary for the current bogus implementation.
as_object* getPrototype() { return _prototype; }
private:
bool addBinding(string_table::key name, const Property& b) {
_bindings.insert(std::make_pair(name, b));
return true;
}
bool addStaticBinding(string_table::key name, const Property& b) {
_staticBindings.insert(std::make_pair(name, b));
return true;
}
Property *getStaticBinding(string_table::key name)
{
if (_staticBindings.empty()) return 0;
BindingContainer::iterator i = _staticBindings.find(name);
if (i == _staticBindings.end()) return 0;
return &i->second;
}
/// The Traits for instances of this class
std::vector<Trait> _instanceTraits;
/// The static Traits for this class;
std::vector<Trait> _staticTraits;
typedef std::map<string_table::key, Property> BindingContainer;
as_object *_prototype;
bool _final;
bool _sealed;
bool _dynamic;
bool _interface;
string_table::key _name;
std::list<Class*> _interfaces;
Namespace* _protectedNs;
Class* _super;
Method* _constructor;
Method* _staticConstructor;
BindingContainer _bindings;
BindingContainer _staticBindings;
bool _declared;
bool _inherited;
bool _system;
};
} // namespace abc
} // namespace gnash
#endif