/** * PANDA 3D SOFTWARE * Copyright (c) Carnegie Mellon University. All rights reserved. * * All use of this software is subject to the terms of the revised BSD * license. You should have received a copy of this license along * with this source code in a file named "LICENSE." * * @file p3dObject.cxx * @author drose * @date 2009-06-30 */ #include "p3dObject.h" #include "p3dBoolObject.h" #include "p3dIntObject.h" #include "p3dFloatObject.h" #include "p3dStringObject.h" #include "p3dInstanceManager.h" #include // strncpy using std::string; // The following functions are C-style wrappers around the below P3DObject // virtual methods; they are defined to allow us to create the C-style // P3D_class_definition method table to store in the P3D_object structure. static void object_finish(P3D_object *object) { delete (P3DObject *)object; } static P3D_object_type object_get_type(P3D_object *object) { return ((P3DObject *)object)->get_type(); } static bool object_get_bool(P3D_object *object) { return ((P3DObject *)object)->get_bool(); } static int object_get_int(P3D_object *object) { return ((P3DObject *)object)->get_int(); } static double object_get_float(P3D_object *object) { return ((P3DObject *)object)->get_float(); } static int object_get_string(P3D_object *object, char *buffer, int buffer_length) { return ((P3DObject *)object)->get_string(buffer, buffer_length); } static int object_get_repr(P3D_object *object, char *buffer, int buffer_length) { return ((P3DObject *)object)->get_repr(buffer, buffer_length); } static P3D_object * object_get_property(P3D_object *object, const char *property) { return ((P3DObject *)object)->get_property(property); } static bool object_set_property(P3D_object *object, const char *property, bool needs_response, P3D_object *value) { return ((P3DObject *)object)->set_property(property, needs_response, value); } static bool object_has_method(P3D_object *object, const char *method_name) { return ((P3DObject *)object)->has_method(method_name); } static P3D_object * object_call(P3D_object *object, const char *method_name, bool needs_response, P3D_object *params[], int num_params) { if (method_name == nullptr) { method_name = ""; } return ((P3DObject *)object)->call(method_name, needs_response, params, num_params); } static P3D_object * object_eval(P3D_object *object, const char *expression) { return ((P3DObject *)object)->eval(expression); } P3D_class_definition P3DObject::_object_class = { &object_finish, &object_get_type, &object_get_bool, &object_get_int, &object_get_float, &object_get_string, &object_get_repr, &object_get_property, &object_set_property, &object_has_method, &object_call, &object_eval, }; // The next functions are used to construct the generic P3D_class_definition // class returned by P3D_make_class_definition(). These are pointers to no-op // functions, which the host may or may not choose to override. static void generic_finish(P3D_object *object) { // You must override finish(), though, otherwise it's a leak. The core API // has no idea how to delete your object. nout << "Warning! default object_finish() method does nothing; object will leak.\n"; } static P3D_object_type generic_get_type(P3D_object *object) { // We assume anyone going through the trouble of subclassing this will want // to return an object, not one of the other fundamental types. return P3D_OT_object; } static bool generic_get_bool(P3D_object *object) { return false; } static int generic_get_int(P3D_object *object) { return 0; } static double generic_get_float(P3D_object *object) { return 0.0; } static int generic_get_string(P3D_object *object, char *buffer, int buffer_length) { return 0; } static int generic_get_repr(P3D_object *object, char *buffer, int buffer_length) { return 0; } static P3D_object * generic_get_property(P3D_object *object, const char *property) { return nullptr; } static bool generic_set_property(P3D_object *object, const char *property, bool needs_response, P3D_object *value) { return false; } static bool generic_has_method(P3D_object *object, const char *method_name) { return false; } static P3D_object * generic_call(P3D_object *object, const char *method_name, bool needs_response, P3D_object *params[], int num_params) { return nullptr; } static P3D_object * generic_eval(P3D_object *object, const char *expression) { return nullptr; } P3D_class_definition P3DObject::_generic_class = { &generic_finish, &generic_get_type, &generic_get_bool, &generic_get_int, &generic_get_float, &generic_get_string, &generic_get_repr, &generic_get_property, &generic_set_property, &generic_has_method, &generic_call, &generic_eval, }; /** * */ P3DObject:: ~P3DObject() { assert(_ref_count == 0); } /** * Returns the object value coerced to an integer, if possible. */ int P3DObject:: get_int() { return 0; } /** * Returns the object value coerced to a floating-point value, if possible. */ double P3DObject:: get_float() { return get_int(); } /** * Stores a string that represents the object value in the indicated buffer; a * null character is included if there is space. Returns the number of * characters needed in the output (which might be more than the actual number * of characters stored if buffer_length was too small). */ int P3DObject:: get_string(char *buffer, int buffer_length) { string result; make_string(result); strncpy(buffer, result.c_str(), buffer_length); return (int)result.size(); } /** * Returns a user-friendly representation of the object, similar to * get_string(), above. */ int P3DObject:: get_repr(char *buffer, int buffer_length) { std::ostringstream strm; output(strm); string result = strm.str(); strncpy(buffer, result.c_str(), buffer_length); return (int)result.size(); } /** * Returns the named property element in the object. The return value is a * new-reference P3D_object, or NULL on error. */ P3D_object *P3DObject:: get_property(const string &property) { return nullptr; } /** * Modifies (or deletes, if value is NULL) the named property element in the * object. Returns true on success, false on failure. */ bool P3DObject:: set_property(const string &property, bool needs_response, P3D_object *value) { return false; } /** * Returns true if the named method exists on this object, false otherwise. */ bool P3DObject:: has_method(const string &method_name) { return false; } /** * Invokes the named method on the object, passing the indicated parameters. * If the method name is empty, invokes the object itself. * * If needs_response is true, the return value is a new-reference P3D_object * on success, or NULL on failure. If needs_response is false, the return * value is always NULL, and there is no way to determine success or failure. */ P3D_object *P3DObject:: call(const string &method_name, bool needs_response, P3D_object *params[], int num_params) { return nullptr; } /** * Evaluates an arbitrary JavaScript expression. None of the P3DObject * classes implement this. */ P3D_object *P3DObject:: eval(const string &expression) { return nullptr; } /** * Writes a formatted representation of the value to the indicated string. * This is intended for developer assistance. */ void P3DObject:: output(std::ostream &out) { string value; make_string(value); out << value; } /** * If this object has a valid XML representation for the indicated session * (that hasn't already been implemented by the generic code in P3DSession), * this method will apply it to the indicated "value" element and return true. * Otherwise, this method will leave the element unchanged and return false. */ bool P3DObject:: fill_xml(TiXmlElement *xvalue, P3DSession *session) { return false; } /** * Returns a pointer to the array of objects represented by this object, if * any, or NULL if the object does not represent an array of objects. This * may also return NULL for a zero-length array; use get_object_array_size() * to differentiate. */ P3D_object **P3DObject:: get_object_array() { return nullptr; } /** * Returns the number of elements in the array returned by get_object_array(), * or -1 if this object does not representan array of objects. */ int P3DObject:: get_object_array_size() { return -1; } /** * Returns this object, downcast to a P3DPythonObject, if it is in fact an * object of that type; or NULL if it is not. */ P3DPythonObject *P3DObject:: as_python_object() { return nullptr; } /** * Returns the value of the named property, as a boolean. Returns 0 if the * property does not exist. */ bool P3DObject:: get_bool_property(const string &property) { P3D_object *result = get_property(property); if (result == nullptr) { return 0; } bool bresult = P3D_OBJECT_GET_BOOL(result); P3D_OBJECT_DECREF(result); return bresult; } /** * Changes the value of the named property to the indicated boolean value. */ void P3DObject:: set_bool_property(const string &property, bool value) { P3D_object *bvalue = new P3DBoolObject(value); set_property(property, false, bvalue); P3D_OBJECT_DECREF(bvalue); } /** * Returns the value of the named property, as an integer. Returns 0 if the * property does not exist. */ int P3DObject:: get_int_property(const string &property) { P3D_object *result = get_property(property); if (result == nullptr) { return 0; } int iresult = P3D_OBJECT_GET_INT(result); P3D_OBJECT_DECREF(result); return iresult; } /** * Changes the value of the named property to the indicated integer value. */ void P3DObject:: set_int_property(const string &property, int value) { P3D_object *ivalue = new P3DIntObject(value); set_property(property, false, ivalue); P3D_OBJECT_DECREF(ivalue); } /** * Returns the value of the named property, as a floating-point number. * Returns 0.0 if the property does not exist. */ double P3DObject:: get_float_property(const string &property) { P3D_object *result = get_property(property); if (result == nullptr) { return 0.0; } double fresult = P3D_OBJECT_GET_FLOAT(result); P3D_OBJECT_DECREF(result); return fresult; } /** * Changes the value of the named property to the indicated floating-point * value. */ void P3DObject:: set_float_property(const string &property, double value) { P3D_object *fvalue = new P3DFloatObject(value); set_property(property, false, fvalue); P3D_OBJECT_DECREF(fvalue); } /** * Returns the value of the named property, as a string. Returns empty string * if the property does not exist. */ string P3DObject:: get_string_property(const string &property) { P3D_object *result = get_property(property); if (result == nullptr) { return string(); } int size = P3D_OBJECT_GET_STRING(result, nullptr, 0); char *buffer = new char[size]; P3D_OBJECT_GET_STRING(result, buffer, size); string sresult(buffer, size); delete[] buffer; P3D_OBJECT_DECREF(result); return sresult; } /** * Changes the value of the named property to the indicated string value. */ void P3DObject:: set_string_property(const string &property, const string &value) { P3D_object *svalue = new P3DStringObject(value); set_property(property, false, svalue); P3D_OBJECT_DECREF(svalue); } /** * Changes the value of the named property to the undefined value. */ void P3DObject:: set_undefined_property(const string &property) { P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); P3D_object *uvalue = inst_mgr->new_undefined_object(); set_property(property, false, uvalue); P3D_OBJECT_DECREF(uvalue); }