Ejemplo n.º 1
0
  Class* Class::s_allocate(STATE) {
    Class* klass = as<Class>(state->memory()->new_object<Class>(state, G(klass)));
    klass->type_info(state->memory()->type_info[ObjectType]);

    return klass;
  }
Ejemplo n.º 2
0
 static void emit(Class& emitter, R(Class::*function)(FArgs...), Args&&... args)
 {
     emitter.invoke(function, std::forward<Args>(args)...);
 }
Ejemplo n.º 3
0
int main() {
    // Basic usage as function parameters that are return values.
    {
        int i = 0;
        byref(i);
        assert(i == 1);
    }

    /*
    References have the same address of the variables.

    Therefore:

    - if declared inside the same function as the value, no extra memory / dereferencing
        needs to be used for references, the compiler can figure everything out at compile time.

    - if declared as function arguments, references may be implemented as implicit pointers passing,
        sharing therefore the disadvantages of pointers.

        Therefore, if you want to be sure of efficiency, pass built-in types by value and not by reference.
    */
    {
        // They have the same address.
        {
            int i = 0;
            //int& ia = i;
            int& ia = i;
            ia = 1;
            assert(i == 1);
            assert(&i == &ia);
        }

        /*
        For the same reason, it is possible to initialize a reference from another reference.
        */
        {
            int i = 0;
            int& ia = i;
            int& ia2 = ia;
            ia2 = 2;
            assert(i == 2);
        }
    }

    /*
    ERROR: Must not initialize non-const ref with a rvalue.

    Can however do that for const references.

    The same goes for function parameters.
    */
    {
        //int& ia = 0;
        //std::string& s = getString();
        const std::string& s = getString();
        //byref(1);
    }

    /*
    ERROR: references must be initialized imediatelly
    otherwise, how can they be initalized in the future?

    For references in constructors, they must be initialized at the initialization list.
    */
    {
        //int& ia;
    }

    /*
    It is possible to get references from pointers.
    */
    {
        int i = 0;
        int* ip = &i;
        int& ia = *ip;
        ia = 1;
        assert(i == 1);

        // ERROR: & must get a variable/dereferenced pointer, not pointers themselves!
        {
            //int& ia = &i;
        }
    }

    /* It is not possible to make an array of references. */
    {
        int i = 1;
        int j = 2;

        // ERROR: array of references forbidden
        //int& is[2] = {i,i};
    }

    /*
    # const references

        References that do not allow one to modify the value of the variable.
    */
    {
        // It is possible to make a const reference from a non-const object.
        {
            int i = 1;
            const int& cia = i;

            // ERROR: const references cannot be modified
            //cia = 2;
        }

        // It is possible to make a const reference form a const object.
        {
            const int ci = 1;
            const int& cia = ci;

            // ERROR: const references cannot be modified
            //cia = 2;
        }

        // The rules imposed by the compiler make sure that it is hard
        // or impossible to cheat references by mistake.
        {
            int i = 1;
            const int& cia = i;

            // ERROR: invalid conversion
            //int& ia = cia;

            // ERROR: invalid conversion
            //int *ip = &cia;
        }

        /*
        const references can be initialized by rvalues!

        This cannot be wrong since they cannot be modified,
        so it is not possible to modify the non-existent variable.

        In this case what happens is that a simple copy takes place.

        One case in which this rule is very important is parameter passing to functions.

        For exapmle, the following would be bad:

            void f(int& i) {
                i++;
            }

            ...

            f(1);
                //does not compile

        and is impossible, but:

            void f(const int& i) {
                //i++;
                    //impossible
            }

            f(1);

        is ok, since it is impossible to change i in the function if it is const
        */
        {
            // Initialization from a literal.
            {
                const int& i = 1;
                assert(i == 1);
            }

            /*
            Initialization from a non-reference function return.

            Functions that return references return lvalues,
            so an example with such a function would not be meaningful.
            */
            {
                const int& i = getInt();
                assert(i == 0);
            }

            /*
            # Lifetime extension

                If you assign a const reference to the return of a function,
                it extends the lifetime of the returned object.

                Note that not every const reference extends lifetime, e.g. arguments don't.

                - http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
                - http://stackoverflow.com/questions/2784262/does-a-const-reference-prolong-the-life-of-a-temporary
                - http://stackoverflow.com/questions/2615162/return-value-not-a-reference-from-the-function-bound-to-a-const-reference-in
            */
            {
                struct C {
                    static std::string f() {
                        return "abc";
                    }
                };
                const std::string& s = C::f();
                assert(s == "abc");
            }
        }
    }

    /*
    # Reference to pointer

        Like for other variable, references can be made to pointer variables.
    */
    {
        {
            int i = 0;
            int j = 1;
            int *ip = &i;
            int *jp = &j;
            int*& ipa = ip;
            int*& jpa = jp;

            jpa = ip;
                //now `jp` is the same as `ip`!

            *jp = 2;
            assert(i == 2);
                //therefore modifying what `jp` points to modifies `i`!

            // ERROR: makes no sense: cannot have a pointer to `int&`
            //int&* ipaBad = ip;

            // ERROR: `&i` is an rvalue. Cannot initialize a non const reference to it.
            //int&* ipaBad = &i;
        }

        /*
        # Reference to pointer and const

            Just like for pointers to pointers in C, the rules prevent `const` variables
            from being modified.
        */
        {
            /*
            Obviously, cannot remove const qualifiers, or it would be easy to modify constants.
            */
            {
                const int c = 0;
                const int *ip = &c;
                //int *&ipa = ip;
                //int *ipa = ip;
                //*ipa = 1;
            }

            /*
            `const int*& = int*` initialization fails for the same reason that `const int* = (int*)` fails in C:
            this would allow for constant modification.
            */
            {
                //If (1) were possible below, then it would be possible to change the value of the constant c.
                {
                    /*
                        int *ip = NULL;
                        const int*& ipa = ip;   // (1) THIS is not possible
                        const int c = 0;
                        ipa = &c;               // OK because ipa is const. `ip` points to `c`
                        *ip = 1;                // OK because ip  is not const
                    */
                }

                /*
                This is different without the reference, because in this case
                it would not be possible to change the const variable.

                Just like in C, the issues only show up in pointer dimensions > 1,
                and the reference behaves like a pointer.
                */
                {
                    int *ip = NULL;
                    const int* ipa = ip;   // (1) THIS is ok without the reference, a new pointer is created
                    const int c = 0;
                    ipa = &c;              // OK because ipa is const. ip still points to NULL
                    //*ip = 1;             // does not change the constant, ip still points to NULL
                }
            }
        }

        /*
        What to do if:

        -   a function modifies what pointers point to but not the object pointed to.

            It therefore takes

        -   we want to pass pointers to that function, modify what they point to,
            and then outside of the function modify the object being pointed to?

        Is this a valid use case for `const_cast`?
        */
        {
            // The motivation: functions.
            {
                int i = 0;
                int j = 1;
                int *ip = &i;
                int *jp = &j;

                // If those were const, the function call would work,
                // but not the `*ip = 2`;
                //const int *ip = &i;
                //const int *jp = &j;

                // Cannot initialize `const int*&` with `int*&`.
                //bypointerConst(ip, jp);

                *ip = 2;
                //assert(j == 2);
            }

            // Same problem simplified without functions.
            {
                int i = 0;
                int *ip = &i;

                // Possible.
                //int*& ipa = ip;

                // TODO why is this not possible.
                //const int*& ipa = ip;
            }

            // But this is possible?
            {
                int i = 0;
                const int& ia = i;
            }
        }
    }

    /*
    Single line initialization syntax.

    Like the pointer symbol `*`, the reference symbol `&` needs to be duplicated for each new reference variable.
    */
    {
        // OK: both ia and ja are references
        {
            int i = 1;
            int j = 2;
            int &ia = i, &ja = j;

            ia = -1;
            ja = -2;

            assert(i == -1);
            assert(j == -2);
        }

        // Bad: ja is a new int, not a reference
        {
            int i = 1;
            int j = 2;
            int& ia = i, ja = j;

            ia = -1;
            ja = -2;

            assert(i == -1);
            assert(j ==  2);
        }

        // With references to pointers it looks like this.
        {
            int i = 0;
            int j = 1;
            int *ip = &i;
            int *jp = &j;

            int *& ipa = ip, *& jpa = jp;

            jpa = ip;
            *jp = 2;
            assert(i == 2);
        }
    }

    /*
    # return reference from function

        Just like for pointers, you have to watch scope.
        If the original object dies, you get a dangling reference.

        - http://stackoverflow.com/questions/752658/is-the-practice-of-returning-a-c-reference-variable-evil

        There is also some rule about const local references:

        - http://stackoverflow.com/questions/2784262/does-a-const-reference-prolong-the-life-of-a-temporary
    */
    {
        /*
        One simple case in which lifetime is simple to guarantee is
        returning members from objects which the callee owns. For example:
        */
        {
            Class c;
            int& ia = c.getRefIPublic();
            ia = 0;
            assert(c.iPublic == 0);
            ia = 1;
            assert(c.iPublic == 1);
        }

        // You can modify a private if you non-const reference to it
        {
            Class c;
            int& ia = c.getPrivateRef();
            ia = 0;
            assert(c.getPrivateRef() == 0);
            ia = 1;
            assert(c.getPrivateRef() == 1);
        }

        // If the reference is const it does not work anymore.
        {
            Class c;

            {
                const int& ia = c.getPrivateConstRef();
                //ia = 1;
            }

            // ERROR: invalid initialization
            {
                //int& ia = c.getPrivateConstRef();
            }
        }

        /*
        In C, all functions return rvalues, although if a function returns a pointer
        and that pointer is dereferenced it becomes an lvalue,
        so the following works:

            (*ret_int_ptr()) = 1;

        In C++, there is an exception: all functions that return references return lvalues directly.
        */
        {
            // OK the returned i reference is not local
            struct C {
                static int& f(int& i) {
                    i++;
                    return i;
                }
            };
            int i = 0;
            (C::f(i)) = 2;
            assert(i == 2);
        }
    }
}
Ejemplo n.º 4
0
void
JIT_execute_method_default(JIT_Handle jh, 
                           jmethodID   methodID,
                           jvalue   *return_value,
                           jvalue   *args)
{
    //assert(("Doesn't compile", 0));
    //abort();
#if 1
    Method *meth = (Method*) methodID;
    assert(!hythread_is_suspend_enabled());
    void *entry_point = meth->get_code_addr();
    int nargs = meth->get_num_args();
    uint64 arg_words[255];
    int double_nargs = 0;
    double double_args[8];
    int num_arg_words = 0;
    int arg_num = 0;
    int num_ref_args = 0;
    Arg_List_Iterator iter = meth->get_argument_list();
    uint64 i64;
    Java_Type typ;
    char msg[300];
    if(!meth->is_static()) {
        ObjectHandle h = (ObjectHandle) args[arg_num++].l;
        // this pointer
        i64 = 0;
        if (h) i64 = (uint64) h->object;
        if (VM_Global_State::loader_env->compress_references) {
            // 20030318 We are in unmanaged code where null is represented by 0/NULL. Convert a null reference
            // to the representation of null in managed code (heap_base).
            if (i64 == 0) {
                i64 = (uint64)VM_Global_State::loader_env->heap_base;
            }
        }
        arg_words[num_arg_words++] = i64;
        num_ref_args++;
    }
    while((typ = curr_arg(iter)) != JAVA_TYPE_END) {
        ObjectHandle h;
        *msg = '\0';
        switch(typ) {
        case JAVA_TYPE_LONG:
            i64 = args[arg_num++].j;
            arg_words[num_arg_words++] = i64;
            break;
        case JAVA_TYPE_CLASS:
        case JAVA_TYPE_ARRAY:
            h = (ObjectHandle) args[arg_num++].l;
            i64 = 0;
            if (h) i64 = (uint64) h->object;
            if (VM_Global_State::loader_env->compress_references) {
                // 20030318 We are in unmanaged code where null is represented by 0/NULL. Convert a null reference
                // to the representation of null in managed code (heap_base).
                if (i64 == 0) {
                    i64 = (uint64)VM_Global_State::loader_env->heap_base;
                }
            }
            arg_words[num_arg_words++] = i64;
            num_ref_args++;
#ifdef _DEBUG
            {
                if (! VM_Global_State::loader_env->compress_references ||
                    i64 != (uint64)VM_Global_State::loader_env->heap_base) {
                    ManagedObject *object = (ManagedObject *)i64;
                    if(object) {
                        Class *clss = object->vt()->clss;
                        sprintf(msg, " of class '%s'", clss->get_name()->bytes);
                    }
                }
            }
#endif
            break;
        case JAVA_TYPE_SHORT:
            i64 = (uint64)args[arg_num++].s;
            arg_words[num_arg_words++] = i64;
            break;
        case JAVA_TYPE_CHAR:
            i64 = (uint64)args[arg_num++].c;
            arg_words[num_arg_words++] = i64;
            break;
        case JAVA_TYPE_BYTE:
            i64 = (uint64)args[arg_num++].b;
            arg_words[num_arg_words++] = i64;
            break;
        case JAVA_TYPE_BOOLEAN:
            i64 = (uint64)args[arg_num++].z;
            arg_words[num_arg_words++] = i64;
            break;
        case JAVA_TYPE_DOUBLE:
            double_args[double_nargs] = args[arg_num++].d;
            double_nargs++;
            break;
        case JAVA_TYPE_FLOAT:
            double_args[double_nargs] = (double)args[arg_num++].f;
            double_nargs++;
            break;
        default:
            i64 = (uint64)args[arg_num++].i;
            arg_words[num_arg_words++] = i64;
            break;
        }
        iter = advance_arg_iterator(iter);
    }

    // assert(nargs <= 8);
    double double_result;

    static void* addr_execute = get_vm_execute_java_method();
    struct{
        void* fun;
        void* gp;
    } fptr;
    fptr.fun = addr_execute;
    fptr.gp = get_vm_gp_value();
        // gashiman - changed _cdecl to __cdecl to work on linux
    uint64 (__cdecl *fpp_exec)(void *entry_point, int nargs, uint64 args[], 
        double *double_result_addr, int double_nargs, double double_args[], 
        void *thread_pointer, uint64 tid) = (uint64 (__cdecl * )(void *entry_point, int nargs, uint64 args[],
        double *double_result_addr, int double_nargs, double double_args[], 
        void *thread_pointer, uint64 tid))&fptr;
    IDATA id = hythread_get_self_id();
    uint64 int_result = (uint64)fpp_exec(entry_point, nargs, arg_words, &double_result,
        double_nargs, double_args, p_TLS_vmthread, id);

    // Save the result
    Java_Type ret_type = meth->get_return_java_type();
    switch(ret_type) {
    case JAVA_TYPE_VOID:
        break;
    case JAVA_TYPE_ARRAY:
    case JAVA_TYPE_CLASS:
        {
            ObjectHandle h = 0;
            if (VM_Global_State::loader_env->compress_references) {
                // 20030318 Convert a null reference in managed code (represented by heap_base)
                // to the representation of null in unmanaged code (0 or NULL).
                if ((uint64)int_result == (uint64)VM_Global_State::loader_env->heap_base) {
                    int_result = 0;
                } 
            }
            if (int_result) {
                h = oh_allocate_local_handle();
                h->object = (ManagedObject*) int_result;
            }
            return_value->l = h;
        }
        break;
    case JAVA_TYPE_LONG:
        return_value->j = int_result;
        break;
    case JAVA_TYPE_INT:
        *((I_32 *)return_value) = (I_32) int_result;
        break;
    case JAVA_TYPE_SHORT:
        *((int16 *)return_value) = (int16) int_result;
        break;
    case JAVA_TYPE_CHAR:
        *((uint16 *)return_value) = (uint16) int_result;
        break;
    case JAVA_TYPE_BYTE:
        *((I_8 *)return_value) = (I_8) int_result;
        break;
    case JAVA_TYPE_BOOLEAN:
        *((U_8 *)return_value) = (U_8) int_result;
        break;
    case JAVA_TYPE_DOUBLE:
        *((double *)return_value) = double_result;
        break;
    case JAVA_TYPE_FLOAT:
        *((float *)return_value) = (float) double_result;
        break;
    default:
#ifdef _DEBUG
        std::clog << "Returned to C from "
               << meth->get_class()->get_name()->bytes << "." << meth->get_name()->bytes
               << meth->get_descriptor()->bytes << "\n";
#endif
        //DIE("Return type ");// <<  (int)ret_type << " is not implemented\n");
        std::clog << "Return type " <<  (int)ret_type << " is not implemented\n";
    }
#endif

} //vm_execute_java_method_array
Ejemplo n.º 5
0
static inline StrNR ctxClassName() {
    Class* ctx = g_context->getContextClass();
    return ctx ? ctx->nameStr() : StrNR(staticEmptyString());
}
Ejemplo n.º 6
0
  void Converter::init(STATE) {
    Class* cls = ontology::new_class_under(state, "Converter", G(encoding));

    cls->set_const(state, "INVALID_MASK", Fixnum::from(ECONV_INVALID_MASK));
    cls->set_const(state, "INVALID_REPLACE", Fixnum::from(ECONV_INVALID_REPLACE));
    cls->set_const(state, "UNDEF_MASK", Fixnum::from(ECONV_UNDEF_MASK));
    cls->set_const(state, "UNDEF_REPLACE", Fixnum::from(ECONV_UNDEF_REPLACE));
    cls->set_const(state, "UNDEF_HEX_CHARREF", Fixnum::from(ECONV_UNDEF_HEX_CHARREF));
    cls->set_const(state, "PARTIAL_INPUT", Fixnum::from(ECONV_PARTIAL_INPUT));
    cls->set_const(state, "AFTER_OUTPUT", Fixnum::from(ECONV_AFTER_OUTPUT));
    cls->set_const(state, "UNIVERSAL_NEWLINE_DECORATOR",
                   Fixnum::from(ECONV_UNIVERSAL_NEWLINE_DECORATOR));
    cls->set_const(state, "CRLF_NEWLINE_DECORATOR",
                   Fixnum::from(ECONV_CRLF_NEWLINE_DECORATOR));
    cls->set_const(state, "CR_NEWLINE_DECORATOR",
                   Fixnum::from(ECONV_CR_NEWLINE_DECORATOR));
    cls->set_const(state, "XML_TEXT_DECORATOR",
                   Fixnum::from(ECONV_XML_TEXT_DECORATOR));
    cls->set_const(state, "XML_ATTR_CONTENT_DECORATOR",
                   Fixnum::from(ECONV_XML_ATTR_CONTENT_DECORATOR));
    cls->set_const(state, "XML_ATTR_QUOTE_DECORATOR",
                   Fixnum::from(ECONV_XML_ATTR_QUOTE_DECORATOR));
  }
Ejemplo n.º 7
0
void ClassTestSuite::testClass()
{
	//Class test = ClassOf<Test1>();

	Class test = Class::lookup("ClassTest::Test1");

	TS_ASSERT_EQUALS(test.simpleName(), "Test1");

#ifndef NO_RTTI
	TS_ASSERT(test.describes<ClassTest::Test1>())

	Class test2 = Class::lookup(typeid(ClassTest::Test1));
	TS_ASSERT_EQUALS(test2.simpleName(), "Test1");
	TS_ASSERT_EQUALS(test, test2);
#endif

	Class::ClassList superClasses = test.superclasses();

	TS_ASSERT_EQUALS(superClasses.size(), 2);

	Class base1;
	Class base2;

	TS_ASSERT_THROWS(base1.simpleName(), std::runtime_error); // uninitialized handle

	for(const Class& c: superClasses) {
		if (c.fullyQualifiedName() == "ClassTest::TestBase1") {
			base1 = c;
		} else if (c.fullyQualifiedName() == "ClassTest::TestBase2") {
			base2 = c;
		}
	}

	TS_ASSERT_EQUALS(base1.fullyQualifiedName(), "ClassTest::TestBase1");
	TS_ASSERT_EQUALS(base1.simpleName(), "TestBase1");
	TS_ASSERT_EQUALS(base2.fullyQualifiedName(), "ClassTest::TestBase2");
	TS_ASSERT_EQUALS(base2.simpleName(), "TestBase2");

	TS_ASSERT(inheritanceRelation(test, base1));
	TS_ASSERT(inherits(test, base1));
	TS_ASSERT(inheritedBy(base1, test));

	TS_ASSERT(inheritanceRelation(test, base2));
	TS_ASSERT(inherits(test, base2));
	TS_ASSERT(inheritedBy(base2, test));

	TS_ASSERT(!inheritanceRelation(base1, base2));

	Class::ConstructorList base1Constructors = base1.constructors();
	TS_ASSERT_EQUALS(base1.constructors().size(), 1);

	Constructor base1Constructor = base1Constructors.front();

	TS_ASSERT_EQUALS(base1Constructor.numberOfArguments(), 0);
	TS_ASSERT_THROWS(base1Constructor.call(), std::runtime_error); // abstract class


	Class::ConstructorList base2Constructors = base2.constructors();
	TS_ASSERT_EQUALS(base2.constructors().size(), 1);

	Constructor base2Constructor = base2Constructors.front();

	TS_ASSERT_EQUALS(base2Constructor.numberOfArguments(), 0);

	VariantValue b2Inst = base2Constructor.call();
	TS_ASSERT(b2Inst.isValid());

	TS_ASSERT_EQUALS(base2.attributes().size(), 0);
	Class::MethodList base2Methods = base2.methods();
	TS_ASSERT_EQUALS(base2Methods.size(), 1);

	Method base2Method1 = base2Methods.front();

	TS_ASSERT_EQUALS(base2Method1.name(), "base2Method1");
	TS_ASSERT(base2Method1.isConst());
	TS_ASSERT(!base2Method1.isVolatile());
	TS_ASSERT(!base2Method1.isStatic());
	TS_ASSERT_EQUALS(base2Method1.numberOfArguments(), 0);
	TS_ASSERT_EQUALS(base2Method1.call(b2Inst).value<int>(), 6);


	Class::ConstructorList testConstructors = test.constructors();
	Class::AttributeList   attributes       = test.attributes();

	TS_ASSERT_EQUALS(attributes.size(), 2);
	Attribute attr = attributes.front();

	WITH_RTTI(TS_ASSERT(attr.type() == typeid(int)));

	TS_ASSERT_EQUALS(testConstructors.size(), 3);

	Constructor defaultConstr;
	Constructor intConstr;

	TS_ASSERT_THROWS(defaultConstr.argumentSpellings(), std::runtime_error);

	for (const Constructor& c: testConstructors) {
		if (c.numberOfArguments() == 0) {
			defaultConstr = c;
		} else if (c.numberOfArguments() == 1  && c.argumentSpellings()[0] == "int"){
			intConstr = c;
		}
	}


	TS_ASSERT_EQUALS(defaultConstr.numberOfArguments(), 0);
	TS_ASSERT_EQUALS(intConstr.numberOfArguments(), 1);

	VariantValue testInst1 = defaultConstr.call();

	TS_ASSERT(testInst1.isA<Test1>());


#ifndef NO_RTTI
	Class test3 = Class::lookup(testInst1.typeId());
	TS_ASSERT_EQUALS(test3.simpleName(), "Test1");
	TS_ASSERT_EQUALS(test, test3);
#endif

    TS_ASSERT_EQUALS(attr.get(testInst1).value<const int&>(), 3);


	VariantValue testInst2 = intConstr.call(77);

	TS_ASSERT(testInst2.isA<Test1>());
    TS_ASSERT_EQUALS(attr.get(testInst2).value<const int&>(), 77);

	Class::MethodList methods = test.methods();

	TS_ASSERT_EQUALS(methods.size(), 9);

	Method base1Method1;
	Method method1;
	Method method2;
	Method staticMethod;


	for (const Method& m: methods) {
		if (m.name() == "base1Method1") {
			base1Method1 = m;
		} else if (m.name() == "base2Method1") {
			base2Method1 = m;
		} else if (m.name() == "method1") {
			method1 = m;
		} else if (m.name() == "method2") {
			method2 = m;
		} else if (m.name() == "staticMethod") {
			staticMethod = m;
		}
	}

	TS_ASSERT_EQUALS(base1Method1.name(), "base1Method1");
	TS_ASSERT(!base1Method1.isConst());
	TS_ASSERT(!base1Method1.isStatic());
	TS_ASSERT(!base1Method1.isVolatile());
	WITH_RTTI(TS_ASSERT(base1Method1.returnType() == typeid(int)));
	TS_ASSERT_EQUALS(base1Method1.numberOfArguments(), 0);
	TS_ASSERT_EQUALS(base1Method1.call(testInst2).value<int>(), 5);

	TS_ASSERT_EQUALS(base2Method1.name(), "base2Method1");
	TS_ASSERT(base2Method1.isConst());
	TS_ASSERT(!base2Method1.isStatic());
	TS_ASSERT(!base2Method1.isVolatile());
	WITH_RTTI(TS_ASSERT(base2Method1.returnType() == typeid(int)));
	TS_ASSERT_EQUALS(base2Method1.numberOfArguments(), 0);
	TS_ASSERT_EQUALS(base2Method1.call(testInst2).value<int>(), 6);

	TS_ASSERT_EQUALS(method2.name(), "method2");
	TS_ASSERT(!method2.isConst());
	TS_ASSERT(!method2.isStatic());
	TS_ASSERT(!method2.isVolatile());
	WITH_RTTI(TS_ASSERT(method2.returnType() == typeid(double)));
	TS_ASSERT_EQUALS(method2.numberOfArguments(), 1);
	WITH_RTTI(TS_ASSERT(*method2.argumentTypes()[0] == typeid(double)));
	TS_ASSERT_EQUALS(method2.call(testInst2, 2).value<double>(), 6.28);

	TS_ASSERT_EQUALS(staticMethod.name(), "staticMethod");
	TS_ASSERT(!staticMethod.isConst());
	TS_ASSERT(staticMethod.isStatic());
	TS_ASSERT(!staticMethod.isVolatile());
	WITH_RTTI(TS_ASSERT(staticMethod.returnType() == typeid(double)));
	TS_ASSERT_EQUALS(staticMethod.numberOfArguments(), 0);
	TS_ASSERT_EQUALS(staticMethod.call().value<double>(), 3.14);

    ClassTest::Test1 t(666);
    VariantValue inst3;
    inst3.construct<ClassTest::TestBase1&>(t);
    TS_ASSERT_THROWS_ANYTHING(method1.call(inst3).value<string>());

    VariantValue inst4 = test.castUp(inst3, base1);
    TS_ASSERT(inst4.isValid());
    bool success = false;
    ClassTest::Test1& derivedRef = inst4.convertTo<ClassTest::Test1&>(&success);
    TS_ASSERT(success);
    TS_ASSERT_EQUALS(derivedRef.attribute1, 666);
    TS_ASSERT_EQUALS(method1.call(inst4).value<string>(), "this is a test");

    Class test_3 = Class::lookup("ClassTest::Test3");

    ClassTest::Test3 t2(666);
    TS_ASSERT_EQUALS(t2.attribute1, 333);
    TS_ASSERT_EQUALS(t2.attribute3, 666);
    VariantValue inst5;
    inst5.construct<ClassTest::TestBase1&>(t2);
    VariantValue inst6 = test_3.castUp(inst5, base1);
    TS_ASSERT(inst6.isValid());
    success = false;
    ClassTest::Test3& derivedRef2 = inst6.convertTo<ClassTest::Test3&>(&success);
    TS_ASSERT(success);
    TS_ASSERT_EQUALS(derivedRef2.attribute1, 333);
    TS_ASSERT_EQUALS(derivedRef2.attribute3, 666);

    t2.attribute1 = 787;
    t2.attribute3 = 13;
    TS_ASSERT_EQUALS(derivedRef2.attribute1, 787);
    TS_ASSERT_EQUALS(derivedRef2.attribute3, 13);

    ClassTest::Test1 t3(666);
    VariantValue inst7;
    inst7.construct<ClassTest::TestBase1&>(t3);
    VariantValue inst8 = test_3.castUp(inst7, base1);
    TS_ASSERT(!inst8.isValid());

    Class test_2 = Class::lookup("ClassTest::Test2");
    VariantValue inst9 = test_2.castUp(inst7, base1);
    TS_ASSERT(!inst9.isValid());
}
Ejemplo n.º 8
0
void ClassLoader::resolvePool(Class * thisClass, int nameptr)
{
	int constant_pool_size = thisClass->constantPool->GetSize();
	for (int i = 1; i < constant_pool_size; i++)
	{

		int item_tag = thisClass->constantPool->get(i)->tag;
		//DEBUG_PRINT("resolve pool %d %d\n",i,item_tag);
		switch (item_tag)
		{
		case  ConstantPoolTag::CONSTANT_Class: {

			if (thisClass->constantPool->get(i)->classInfo.classPtr == nullptr)
			{
				resolveClassPointer(thisClass, i, nameptr);
			}

			break;}
		case  ConstantPoolTag::CONSTANT_Fieldref:
		{
			//classptr
			int class_index = thisClass->constantPool->get(i)->fieldInfo.class_index;
			if (thisClass->constantPool->get(class_index)->classInfo.classPtr == nullptr)
			{
				resolveClassPointer(thisClass, class_index, nameptr);
			}

			Class * myClass = thisClass->constantPool->get(class_index)->classInfo.classPtr;
			thisClass->constantPool->setClassPtr(i, myClass);

			//field ptr
			//if (myClass != nullptr)
			//{
			int name_index = thisClass->constantPool->get(i)->fieldInfo.name_and_type_index;
			int descriptor_index = thisClass->constantPool->get(name_index)->nameAndTypeInfo.descriptor_index;
			name_index = thisClass->constantPool->get(name_index)->nameAndTypeInfo.name_index;
			Utf8String item_name = Utf8String(thisClass->constantPool->get(name_index)->utf8Info.bytes, thisClass->constantPool->get(name_index)->utf8Info.length);
			Utf8String item_descriptor = Utf8String(thisClass->constantPool->get(descriptor_index)->utf8Info.bytes, thisClass->constantPool->get(descriptor_index)->utf8Info.length);

			Field* field = myClass->getField(item_name, item_descriptor);
			thisClass->constantPool->setFieldPtr(i, field);
			//}
		}
		break;
		case  ConstantPoolTag::CONSTANT_Methodref: {
			//classptr
			int class_index = thisClass->constantPool->get(i)->methodInfo.class_index;
			if (thisClass->constantPool->get(class_index)->classInfo.classPtr == nullptr)
			{

				resolveClassPointer(thisClass, class_index , nameptr);

			}
			Class * myClass = thisClass->constantPool->get(class_index)->classInfo.classPtr;
			thisClass->constantPool->setClassPtr(i, myClass);
			//merhod ptr


			int name_index = thisClass->constantPool->get(i)->methodInfo.name_and_type_index;
			int descriptor_index = thisClass->constantPool->get(name_index)->nameAndTypeInfo.descriptor_index;
			name_index = thisClass->constantPool->get(name_index)->nameAndTypeInfo.name_index;
			Utf8String item_name = Utf8String(thisClass->constantPool->get(name_index)->utf8Info.bytes, thisClass->constantPool->get(name_index)->utf8Info.length);
			Utf8String item_descriptor = Utf8String(thisClass->constantPool->get(descriptor_index)->utf8Info.bytes, thisClass->constantPool->get(descriptor_index)->utf8Info.length);

			if (thisClass->methodArea.getMethod(item_name, item_descriptor) != nullptr)
			{
				thisClass->constantPool->setMethodPtr(i, thisClass->methodArea.getMethod(item_name, item_descriptor));
			}
			else if (myClass != nullptr && myClass->methodArea.getMethod(item_name, item_descriptor) != nullptr)
			{
				thisClass->constantPool->setMethodPtr(i, myClass->methodArea.getMethod(item_name, item_descriptor));
			}


			break;}
		case  ConstantPoolTag::CONSTANT_InterfaceMethodref: {
			//classptr
			int class_index = thisClass->constantPool->get(i)->interfaceMethodInfo.class_index;
			if (thisClass->constantPool->get(class_index)->classInfo.classPtr == nullptr)
			{
				resolveClassPointer(thisClass, class_index,nameptr);
			}
			Class * myClass = thisClass->constantPool->get(class_index)->classInfo.classPtr;
			thisClass->constantPool->setClassPtr(i, myClass);
			//method ptr
			//if (myClass != nullptr)
			//{
			int name_index = thisClass->constantPool->get(i)->interfaceMethodInfo.name_and_type_index;
			int descriptor_index = thisClass->constantPool->get(name_index)->nameAndTypeInfo.descriptor_index;
			name_index = thisClass->constantPool->get(name_index)->nameAndTypeInfo.name_index;
			Utf8String item_name = Utf8String(thisClass->constantPool->get(name_index)->utf8Info.bytes, thisClass->constantPool->get(name_index)->utf8Info.length);
			Utf8String item_descriptor = Utf8String(thisClass->constantPool->get(descriptor_index)->utf8Info.bytes, thisClass->constantPool->get(descriptor_index)->utf8Info.length);
			if (thisClass->methodArea.getMethod(item_name, item_descriptor) != nullptr)
			{
				thisClass->constantPool->setMethodPtr(i, thisClass->methodArea.getMethod(item_name, item_descriptor));
			}
			else if (myClass != nullptr &&  myClass->methodArea.getMethod(item_name, item_descriptor) != nullptr)
			{
				thisClass->constantPool->setMethodPtr(i, myClass->methodArea.getMethod(item_name, item_descriptor));
			}
			//}

			break;}
		case  ConstantPoolTag::CONSTANT_Double:
		case  ConstantPoolTag::CONSTANT_Long:
			i++;
			break;
		default:
			break;
		}
	}
	//DEBUG_PRINT("resolving finnished\n");
}
Ejemplo n.º 9
0
bool doFetchLesson(Class t, ThreadSafeQueue<Class> *classList, std::atomic<int> *totalLessons)
{
	std::string buffer;
	CURL *curl;
	CURLcode res;
	
	weekAmountList.lock();
	int weekAmount = -1;
	for (int i = 0; i < weekAmountList.size(); i++)
	{
		if (weekAmountList.at(i).departmentStringId == t.departmentString() && weekAmountList.at(i).cpath == t.cpath())
		{
			weekAmount = weekAmountList.at(i).amountOfWeeks;
			break;
		}
	}
	if(weekAmount == -1)
		printf("ERROR: NOT FOUND: %s - %s\n", t.departmentString().c_str(), t.cpath().c_str());
	weekAmountList.unlock();
	
	char postFields[1024] = "";
	for (int i = 1; i < weekAmount+1; i++)
	{
		int n = sprintf(postFields, "%sweken[]=%d&", postFields, i);
		postFields[n] = '\0';
	}
	int n = sprintf(postFields, "%ssleutelveld=%s&object=%s&filter=%s", postFields, t.classIdString().c_str(), t.cpath().c_str(), t.departmentString().c_str());
	postFields[n] = '\0';
	//printf("%s\n", postFields);
	curl = curl_easy_init();
	curl_easy_setopt(curl, CURLOPT_URL, "https://rooster.nhl.nl/1516/rooster.php");
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postFields);
	//curl_easy_setopt(curl, CURLOPT_REFERER, NHL_REFERER);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, CURL_TIMEOUT); // 5 sec time out on whole request
	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, CURL_CONNECT_TIMEOUT); // 10 sec connect time out
	res = curl_easy_perform(curl);
	//printf("------\n%s------\n\n", buffer.c_str());
	if (res == CURLE_OK)
	{
		GumboOutput* output = gumbo_parse(buffer.c_str());
		GumboNode* node = GetTBodyNode(output->root);
		if (node == NULL)
		{
			if (t.cpath() == "ttstud"){
				printf("[%s] FAIL(%s-%s-%s)\n", currentDateTime().c_str(), t.className().c_str(), t.departmentString().c_str(), t.cpath().c_str());
				curl_easy_cleanup(curl);
			}
			else{
				printf("[%s] FAIL(%s-%s-%s), aborting program\n", currentDateTime().c_str(), t.className().c_str(), t.departmentString().c_str(), t.cpath().c_str());
				curl_easy_cleanup(curl);
				exit(1);
			}
			return true;
		}
		GumboVector* children = &node->v.element.children;
		bool newDay = false;
		int lessonAmount = 0;
		int yearOffset = -1;
		int titleOffset = -1;
		int locationOffset = -1;
		int teacherOffset = -1;
		int typeOffset = -1;
		int commentOffset = -1;
		int endOffset = -1;
		std::string date;
		char dayName[128];
		int day;
		int month;
		int year;
		for (unsigned int i = 0; i < children->length; ++i) {
			GumboNode *node1 = static_cast<GumboNode*>(children->data[i]);
			if (node1->v.element.tag == GUMBO_TAG_TR){

				GumboAttribute *att = gumbo_get_attribute(&node1->v.element.attributes, "class");
				if (att)
				{
					//printf("TR CLASS: %s\n", att->value);
					std::string value = att->value;
					if (value == "datarij")
					{
						std::string yearType = "";
						GumboNode *startTimeNode = static_cast<GumboNode*>(node1->v.element.children.data[0]);
						std::string endDate = "";
						if (endOffset != -1)
						{
							GumboNode *endTimeNode = static_cast<GumboNode*>(node1->v.element.children.data[endOffset]);
							endDate = GetTextFromElement(endTimeNode);
						}
						if (yearOffset != -1)
						{
							GumboNode *yearNode = static_cast<GumboNode*>(node1->v.element.children.data[yearOffset]); // optional
							if (yearNode)
								yearType = GetTextFromElement(yearNode);
						}
						std::string typeStr = "";
						GumboNode *titleNode = static_cast<GumboNode*>(node1->v.element.children.data[titleOffset]);
						GumboNode *locationNode = static_cast<GumboNode*>(node1->v.element.children.data[locationOffset]);
						std::string teacher = "";
						if (teacherOffset != -1)
						{
							GumboNode *teacherNode = static_cast<GumboNode*>(node1->v.element.children.data[teacherOffset]);
							teacher = GetTextFromElement(teacherNode);
						}
						//if(teacher == "" && t.departmentString() == "TEE" && t.cpath() == "stud"){
						//printf("Teacher empty: %s - %s\n", GetTextFromElement(titleNode).c_str(), GetTextFromElement(startTimeNode).c_str());
						//printf("Buffer:\n%s\n----\n", buffer.c_str());
						//}
						//printf("%s\n", teacher.c_str());
						if (typeOffset != -1)
						{							
							GumboNode *typeNode = static_cast<GumboNode*>(node1->v.element.children.data[typeOffset]);
							typeStr = GetTextFromElement(typeNode);
						}
						GumboNode *commentsNode = static_cast<GumboNode*>(node1->v.element.children.data[commentOffset]);
						std::string startDate = GetTextFromElement(startTimeNode);
						int startHour;
						int startMinute;
						sscanf(startDate.c_str(), "%02d:%02d", &startHour, &startMinute);
						char newStartDate[128];
						//YYYY-MM-DDTHH:MM:SS
						int n = sprintf(newStartDate, "%04d-%02d-%02dT%02d:%02d:00", year, month, day, startHour, startMinute);
						newStartDate[n] = '\0';

						char newEndDate[128];
						if (endDate != "") {
							int endHour;
							int endMinute;
							sscanf(endDate.c_str(), "%02d:%02d", &endHour, &endMinute);
							//YYYY-MM-DDTHH:MM:SS
							int ne = sprintf(newEndDate, "%04d-%02d-%02dT%02d:%02d:00", year, month, day, endHour, endMinute);
							newEndDate[ne] = '\0';
						}else
							newEndDate[0] = '\0';

						//printf("%s - %s - %s - %s - %s (YEAR: %s)\n", GetTextFromElement(titleNode).c_str(), newStartDate, newEndDate, GetTextFromElement(teacherNode).c_str(), GetTextFromElement(locationNode).c_str(), yearType.c_str());
						int weekNr = getWeekNrFromDate(newStartDate);

						// Calculate time difference to remove old lessons
						time_t timeStampThisWeek = getTimeStampFromDate(newStartDate);
						time_t timeStampCurrentWeek;
						time(&timeStampCurrentWeek);
						//printf("Current week: %d - Lesson week: %d\n", getCurrentWeekNumber(), weekNr);
						double diff = difftime(timeStampThisWeek, timeStampCurrentWeek);
						double weeks = diff / 604800;
						//printf("Time difference: %.f\n", weeks);
						if (weeks > -2)
						{ // ignore old lessons
							t.addLesson(shared_ptr<Lesson>(new Lesson(GetTextFromElement(titleNode), GetTextFromElement(commentsNode), teacher, replaceAll(GetTextFromElement(locationNode), "    ", ", "), newStartDate, newEndDate, weekNr, yearType, typeStr)));
							++*totalLessons;
						}
						lessonAmount++;
					}
					else if (value == "weekheader")
					{
						yearOffset = -1;
						titleOffset = -1;
						locationOffset = -1;
						teacherOffset = -1;
						typeOffset = -1;
						commentOffset = -1;
						GumboVector* children = &node1->v.element.children;
						for (unsigned int i = 0; i < children->length; ++i)
						{
							GumboNode *child = static_cast<GumboNode*>(children->data[i]);
							std::string text = GetTextFromElement(child);
							if (text == "jaar")
								yearOffset = i;
							else if (text == "activiteit")
								titleOffset = i;
							else if (text == "lokaal")
								locationOffset = i;
							else if (text == "docent(en)" || text == "klas(en)")
								teacherOffset = i;
							else if (text == "werkvorm")
								typeOffset = i;
							else if (text == "opmerkingen")
								commentOffset = i;
							else if (text == "eind")
								endOffset = i;
						}
					}
				}
				else
				{
					// no class
					GumboNode *td = static_cast<GumboNode*>(node1->v.element.children.data[0]);
					if (td->v.element.tag == GUMBO_TAG_TD) {
						GumboAttribute *classAtt = gumbo_get_attribute(&td->v.element.attributes, "class");
						if (classAtt)
						{
							std::string dayRow = classAtt->value;
							if (dayRow == "dagrij")
							{
								GumboNode *dateNode = static_cast<GumboNode*>(td->v.element.children.data[0]);
								date = dateNode->v.text.text; // get date with sscanf

								sscanf(date.c_str(), "%s %02d-%02d-%04d", &dayName, &day, &month, &year);
								//printf("New day @ %s\n", date.c_str());
							}
						}
					}
				}
			}
		}
		//printf("Lessons: %d\n", lessonAmount);
		gumbo_destroy_output(&kGumboDefaultOptions, output);
		curl_easy_cleanup(curl);
		classList->lock();
		classList->push(t);
		classList->unlock();
		return true;
	}
	else{
		//printf("[%s] Fail: %s, aborting program", currentDateTime().c_str(), curl_easy_strerror(res));
		curl_easy_cleanup(curl);
		//exit(1);
		return false;
	}
		/* New ICAL style as of semester starting at 01-09-2015 */
		/*
		icalcomponent *rootNode = icalparser_parse_string(cstr);
		icalcomponent *comp = icalcomponent_get_first_component(rootNode, ICAL_VEVENT_COMPONENT);
		//icalcomponent *zoneComp = icalcomponent_get_first_component(rootNode, ICAL_VTIMEZONE_COMPONENT);
		//icaltimezone *zone = icaltimezone_get_builtin_timezone("Europe/Amsterdam");
	
		//icalcomponent *next = icalcomponent_get_next_component(rootNode, ICAL_VEVENT_COMPONENT);
		while (comp != NULL){
			//printf("%s\n", icalcomponent_as_ical_string(comp));
			std::string summary = icalcomponent_get_summary(comp);
			icaltimetype dtstart = icalcomponent_get_dtstart(comp);
			
			std::string starttime = formatDateTime(getTimeStampFromDateAlt(icaltime_as_ical_string(dtstart)));
			icaltimetype dtend = icalcomponent_get_dtend(comp);

			std::string endtime = formatDateTime(getTimeStampFromDateAlt(icaltime_as_ical_string(dtend)));
			const char *locationStr = icalcomponent_get_location(comp); // can be null
			std::string location = "";
			if (locationStr){
				location = locationStr;
				location = replaceAll(location, "    ", ", ");
			}
			std::string commentStr = (char *)icalcomponent_get_comment(comp);
			printf("Comment: %s\n", commentStr.c_str());
			char *comment = (char *)commentStr.c_str();
			char *line = strtok(comment, "\n");
			std::string docenten;
			while (line != NULL){
				if (strstr(line, "Docent(en): ")){
					line += 12; // 12 is length of Docent(en)
					int length = strlen(line);
					docenten = line;
				}
				line = strtok(NULL, "\n");
			}
			int weekNr = getWeekNrFromDate(starttime);
			//printf("%s - %s\n", summary.c_str(), starttime.c_str());
			if (weekNr > getCurrentWeekNumber() - 2) { // ignore old lessons
				t.addLesson(shared_ptr<Lesson>(new Lesson(summary, summary, docenten, location, starttime, endtime, weekNr)));
				printf("1Add Lesson(%s): %s - %s - %s - %s(%s)\n", t.className().c_str(), summary.c_str(), starttime.c_str(), endtime.c_str(), docenten.c_str(), commentStr.c_str());
			}
			icalcomponent_free(comp);
			comp = icalcomponent_get_next_component(rootNode, ICAL_VEVENT_COMPONENT);
		}
		icalcomponent_free(comp);
		icalcomponent_free(rootNode);
		classList->lock();
		classList->push(t);
		classList->unlock();
	*/
		// delete our garbage
		//delete[] refererUrlBuffer;
		//delete[] urlBuffer;
		//delete[] cstr;
		//curl_free(classIdStringEscaped);
		//curl_easy_cleanup(curl);

		//return true;
		/* Old XML Style
		xml_document<> doc;
		doc.parse<0>(cstr);
		xml_node<> *pRoot = doc.first_node();
		if (pRoot == 0)
		{
			std::cout << "doFetchLesson() ERROR: Invalid rootnode" << std::endl;
			exit(1); // Immediately abort program as the document is unreadable
		}
		else if (pRoot != NULL)
		{
			pRoot = pRoot->first_node();
			if (pRoot == 0)
			{
				std::cout << "doFetchLesson() ERROR: Rootnode has an invalid first node" << std::endl;
				exit(1); // Immediately abort program as the document is unreadable
			}
		}
		for (xml_node<> *pNode = pRoot->first_node("item"); pNode; pNode = pNode->next_sibling())
		{
			std::string title = pNode->first_node("title") ? pNode->first_node("title")->value() : "";
			if (title.length() > 2)
				title = title.substr(title.find(": ") + 2, title.length());
			std::string description = pNode->first_node("description") ? pNode->first_node("description")->value() : "";
			std::string teacher = getStringBetween(" - ", " -", description, "([a-zA-Z,. ]+)");

			std::string location = pNode->first_node("ev:location") ? pNode->first_node("ev:location")->value() : "";
			location = trim(location);
			char *locationDecoded = curl_easy_unescape(curl, location.c_str(), 0, NULL);
			location = std::string(locationDecoded);
			curl_free(locationDecoded);
			std::string startdate = pNode->first_node("ev:startdate") ? pNode->first_node("ev:startdate")->value() : "";
			std::string enddate = pNode->first_node("ev:enddate") ? pNode->first_node("ev:enddate")->value() : "";
			int weekNr = getWeekNrFromDate(startdate);
			if (weekNr > getCurrentWeekNumber() - 2) // ignore old lessons
				t.addLesson(shared_ptr<Lesson>(new Lesson(title, description, teacher, location, startdate, enddate, weekNr)));
		}
		// ready to push back the class
		classList->lock();
		classList->push_back(t);
		classList->unlock();

		// delete our garbage
		delete[] refererUrlBuffer;
		delete[] urlBuffer;
		delete[] cstr;
		curl_free(classIdStringEscaped);
		curl_easy_cleanup(curl);
		
		return true;*/
}
Ejemplo n.º 10
0
void Util::preparse(QSet<Type*> *usedTypes, QSet<const Class*> *superClasses, const QList<QString>& keys)
{
    Class& globalSpace = classes["QGlobalSpace"];
    globalSpace.setName("QGlobalSpace");
    globalSpace.setKind(Class::Kind_Class);
    globalSpace.setIsNameSpace(true);
    
    // add all functions as methods to a class called 'QGlobalSpace' or a class that represents a namespace
    for (QHash<QString, Function>::const_iterator it = functions.constBegin(); it != functions.constEnd(); it++) {
        const Function& fn = it.value();
        
        QString fnString = fn.toString();
        
        // gcc doesn't like this function... for whatever reason
        if (fn.name() == "_IO_ftrylockfile"
            // functions in named namespaces are covered by the class list - only check for top-level functions here
            || (fn.nameSpace().isEmpty() && !Options::functionNameIncluded(fn.qualifiedName()) && !Options::functionSignatureIncluded(fnString))
            || Options::typeExcluded(fnString))
        {
            // we don't want that function...
            continue;
        }
        
        Class* parent = &globalSpace;
        if (!fn.nameSpace().isEmpty()) {
            parent = &classes[fn.nameSpace()];
            if (parent->name().isEmpty()) {
                parent->setName(fn.nameSpace());
                parent->setKind(Class::Kind_Class);
                parent->setIsNameSpace(true);
            }
        }
        
        Method meth = Method(parent, fn.name(), fn.type(), Access_public, fn.parameters());
        meth.setFlag(Method::Static);
        parent->appendMethod(meth);
        // map this method to the function, so we can later retrieve the header it was defined in
        globalFunctionMap[&parent->methods().last()] = &fn;
        
        int methIndex = parent->methods().size() - 1;
        addOverloads(meth);
        // handle the methods appended by addOverloads()
        for (int i = parent->methods().size() - 1; i > methIndex; --i)
            globalFunctionMap[&parent->methods()[i]] = &fn;

        (*usedTypes) << meth.type();
        foreach (const Parameter& param, meth.parameters())
            (*usedTypes) << param.type();
    }
    
    // all enums that don't have a parent are put under QGlobalSpace, too
    for (QHash<QString, Enum>::iterator it = enums.begin(); it != enums.end(); it++) {
        Enum& e = it.value();
        if (!e.parent()) {
            Class* parent = &globalSpace;
            if (!e.nameSpace().isEmpty()) {
                parent = &classes[e.nameSpace()];
                if (parent->name().isEmpty()) {
                    parent->setName(e.nameSpace());
                    parent->setKind(Class::Kind_Class);
                    parent->setIsNameSpace(true);
                }
            }

            Type *t = 0;
            if (e.name().isEmpty()) {
                // unnamed enum
                Type longType = Type("long");
                longType.setIsIntegral(true);
                t = Type::registerType(longType);
            } else {
                t = Type::registerType(Type(&e));
            }
            (*usedTypes) << t;
            parent->appendChild(&e);
        }
    }
    
    foreach (const QString& key, keys) {
        Class& klass = classes[key];
        foreach (const Class::BaseClassSpecifier base, klass.baseClasses()) {
            superClasses->insert(base.baseClass);
        }
        if (!klass.isNameSpace()) {
            addDefaultConstructor(&klass);
            addCopyConstructor(&klass);
            addDestructor(&klass);
            checkForAbstractClass(&klass);
            foreach (const Method& m, klass.methods()) {
                if (m.access() == Access_private)
                    continue;
                if ((m.type()->getClass() && m.type()->getClass()->access() == Access_private)
                    || Options::typeExcluded(m.toString(false, true)))
                {
                    klass.methodsRef().removeOne(m);
                    continue;
                }
                addOverloads(m);
                (*usedTypes) << m.type();
                foreach (const Parameter& param, m.parameters())
                    (*usedTypes) << param.type();
            }
            foreach (const Field& f, klass.fields()) {
                if (f.access() == Access_private)
                    continue;
                if (Options::typeExcluded(f.toString(false, true))) {
                    klass.fieldsRef().removeOne(f);
                    continue;
                }
            }
            foreach (const Field& f, klass.fields()) {
                if (f.access() == Access_private)
                    continue;
                addAccessorMethods(f, usedTypes);
            }
        }
Ejemplo n.º 11
0
Class& Symbols::enterClassScope(const string name) {
    Class *c = new Class(name, currentScope());
    define(*c);
    enterScope(c->scope());
    return *c;
}
Ejemplo n.º 12
0
void ClassInfoModel::SetClassItem(const Class &cClass)
{
	const Class *pClass = &cClass;

	beginResetModel();

	DeleteChilds(m_pCommonCategory);
	DeleteChilds(m_pAttributeCategory);
	DeleteChilds(m_pSlotsCategory);
	DeleteChilds(m_pSignalsCategory);
	DeleteChilds(m_pPropertiesCategory);
	DeleteChilds(m_pConstructorsCategory);
	DeleteChilds(m_pMethodsCategory);

	// Add common information items
	new ClassListItem(pClass, NameRole, m_pCommonCategory);
	new ClassListItem(pClass, DescriptionRole, m_pCommonCategory);

	// Add attributes
	const List<VarDesc*> &attr = cClass.GetAttributes();
	for (uint32 i=0; i<attr.GetNumOfElements(); ++i) {
		VarDesc *pVarDesc = attr[i];
		new ClassInfoAttributeTreeItem(*pVarDesc, m_pAttributeCategory);
	}

	// Add slots
	const List<EventHandlerDesc*> &cSlots = cClass.GetSlots();
	for (uint32 i=0; i<cSlots.GetNumOfElements(); ++i) {
		EventHandlerDesc *pVarDesc = cSlots[i];
		new ClassInfoMemberWithSignatureDescTreeItem<EventHandlerDesc>(tr("Slot"), *pVarDesc, m_pSlotsCategory);
	}

	// Add signals
	const List<EventDesc*> &cSignals = cClass.GetSignals();
	for (uint32 i=0; i<cSignals.GetNumOfElements(); ++i) {
		EventDesc *pVarDesc = cSignals[i];
		new ClassInfoMemberWithSignatureDescTreeItem<EventDesc>(tr("Signal"), *pVarDesc, m_pSignalsCategory);
	}

	// Add properties
	const HashMap<String, String> &cProps = cClass.GetProperties();
	Iterator<String> cIterator = cProps.GetKeyIterator();
	while (cIterator.HasNext()) {
		const String sName  = cIterator.Next();
		const String sValue = cProps.Get(sName);
		new ClassInfoPropertyTreeItem(QtStringAdapter::PLToQt(sName), QtStringAdapter::PLToQt(sValue), m_pPropertiesCategory);
	}

	// Add constructors
	const List<ConstructorDesc*> &cConstructors = cClass.GetConstructors();
	for (uint32 i=0; i<cConstructors.GetNumOfElements(); ++i) {
		ConstructorDesc *pVarDesc = cConstructors[i];
		new ClassInfoMemberWithSignatureDescTreeItem<ConstructorDesc>(tr("Constructor"), *pVarDesc, m_pConstructorsCategory);
	}

	// Add methods
	const List<FuncDesc*> &cMethods = cClass.GetMethods();
	for (uint32 i=0; i<cMethods.GetNumOfElements(); ++i) {
		FuncDesc *pVarDesc = cMethods[i];
		new ClassInfoMemberWithSignatureDescTreeItem<FuncDesc>(tr("Method"), *pVarDesc, m_pMethodsCategory);
	}

	endResetModel();
}
Ejemplo n.º 13
0
String f_hphp_get_original_class_name(CStrRef name) {
  Class* cls = Unit::loadClass(name.get());
  if (!cls) return empty_string;
  return cls->nameRef();
}
Ejemplo n.º 14
0
    bool UmlAttribute::manage_enum_item(WrapperStr name, UmlClass * cl
#ifdef ROUNDTRIP
                                        , bool roundtrip,
                                        QList<UmlItem *> & expected_order
#endif
                                       )
    {
        WrapperStr comment = Lex::get_comments();
        WrapperStr description = Lex::get_description();
        UmlAttribute * item = 0;	// initialize to avoid warning
#ifdef ROUNDTRIP
        Class * container = 0;	// initialize to avoid warning
        bool created = FALSE;		// initialize to avoid warning
#endif

        if (!Package::scanning()) {
#ifdef ROUNDTRIP
            container = cl->get_class();

            if (!roundtrip ||
                ((item = search_attr(container, name)) == 0)) {
#endif

                if ((item = UmlBaseAttribute::create(cl, name)) == 0) {
                    JavaCatWindow::trace(WrapperStr("<font face=helvetica><b>cannot add enum item <i>")
                                         + name + "</i> in <i>" + cl->name()
                                         + "</i></b></font><br>");
                    return FALSE;
                }

                item->set_Visibility(PublicVisibility);
#ifdef ROUNDTRIP

                if (roundtrip)
                    container->set_updated();

                created = TRUE;
            }

#endif
        }

        Lex::mark();

        WrapperStr aux;
        WrapperStr s;

        if ((s = Lex::read_word()).isEmpty()) {
            if (! Package::scanning())
                Lex::premature_eof();

            return FALSE;
        }
        else if ((s == ";") || (s == "}")) {
            aux = Lex::region();
            Lex::unread_word(s);
        }
        else if (s == ",") {
            aux = Lex::region();
            Lex::finish_line();
            comment = Lex::get_comments(comment);
            description = Lex::get_description(description);
        }
        else if ((s == "(") || (s == "{")) {
            char c = UmlOperation::skip_expr(1);	// goes after opt init and body

            if (c == 0) {
                if (! Package::scanning())
                    Lex::premature_eof();

                return FALSE;
            }

            // c is ',' or ';'
            if (c == ';')
                Lex::unread_word(";");

            aux = Lex::region();
        }
        else {
            if (! Package::scanning())
                Lex::error_near(s);

            return FALSE;
        }

        if (!Package::scanning()) {
            // here aux = opt init and body + final character , ; or }
            WrapperStr decl = JavaSettings::enumItemDecl();
            int index;

            if ((decl.find("${name}") == -1) ||
                ((index = decl.find("${value}")) == -1)) {
                decl = "  ${name}${value},${comment}";
                index = decl.find("${value}");
            }

            //aux.resize(aux.length()); // remove , ; or }, warning resize count \000 //warn_WrapperStr

            if (!aux.stripWhiteSpace().isEmpty())
                decl.replace(index, 8, aux);

#ifdef ROUNDTRIP

            if (roundtrip && !created) {
                if (decl.find("${description}") != -1) {
                    if (nequal(item->description(), description)) {
                        item->set_Description(description);
                        container->set_updated();
                    }
                }
                else if (nequal(item->description(), Lex::simplify_comment(comment))) {
                    item->set_Description(comment); // comment was changed
                    container->set_updated();
                }

                if (neq(item->javaDecl(), decl)) {
                    item->set_JavaDecl(decl);
                    container->set_updated();
                }

                item->set_usefull();

                expected_order.append(item);
            }
            else {
#endif

                if (!comment.isEmpty())
                    item->set_Description((decl.find("${description}") != -1)
                                          ? description : Lex::simplify_comment(comment));

                item->set_JavaDecl(decl);

#ifdef ROUNDTRIP

                if (roundtrip)
                    expected_order.append(item);
            }

#endif
        }

        return TRUE;
    }
Ejemplo n.º 15
0
void unserializeVariant(Variant& self, VariableUnserializer *uns,
                        UnserializeMode mode /* = UnserializeMode::Value */) {

  // NOTE: If you make changes to how serialization and unserialization work,
  // make sure to update the reserialize() method in "runtime/ext/ext_apc.cpp"
  // and to update test_apc_reserialize() in "test/ext/test_ext_apc.cpp".

  char type = uns->readChar();
  char sep = uns->readChar();

  if (type != 'R') {
    uns->add(&self, mode);
  }

  if (type == 'N') {
    if (sep != ';') throw Exception("Expected ';' but got '%c'", sep);
    self.setNull(); // NULL *IS* the value, without we get undefined warnings
    return;
  }
  if (sep != ':') {
    throw Exception("Expected ':' but got '%c'", sep);
  }

  switch (type) {
  case 'r':
    {
      int64_t id = uns->readInt();
      Variant *v = uns->getByVal(id);
      if (v == nullptr) {
        throw Exception("Id %" PRId64 " out of range", id);
      }
      self = *v;
    }
    break;
  case 'R':
    {
      int64_t id = uns->readInt();
      Variant *v = uns->getByRef(id);
      if (v == nullptr) {
        throw Exception("Id %" PRId64 " out of range", id);
      }
      self.assignRef(*v);
    }
    break;
  case 'b': { int64_t v = uns->readInt(); self = (bool)v; } break;
  case 'i': { int64_t v = uns->readInt(); self = v;       } break;
  case 'd':
    {
      double v;
      char ch = uns->peek();
      bool negative = false;
      char buf[4];
      if (ch == '-') {
        negative = true;
        ch = uns->readChar();
        ch = uns->peek();
      }
      if (ch == 'I') {
        uns->read(buf, 3); buf[3] = '\0';
        if (strcmp(buf, "INF")) {
          throw Exception("Expected 'INF' but got '%s'", buf);
        }
        v = atof("inf");
      } else if (ch == 'N') {
        uns->read(buf, 3); buf[3] = '\0';
        if (strcmp(buf, "NAN")) {
          throw Exception("Expected 'NAN' but got '%s'", buf);
        }
        v = atof("nan");
      } else {
        v = uns->readDouble();
      }
      self = negative ? -v : v;
    }
    break;
  case 's':
    {
      String v;
      v.unserialize(uns);
      self = std::move(v);
      if (!uns->endOfBuffer()) {
        // Semicolon *should* always be required,
        // but PHP's implementation allows omitting it
        // and still functioning.
        // Worse, it throws it away without any check.
        // So we'll do the same.  Sigh.
        uns->readChar();
      }
    }
    return;
  case 'S':
    if (uns->type() == VariableUnserializer::Type::APCSerialize) {
      union {
        char buf[8];
        StringData *sd;
      } u;
      uns->read(u.buf, 8);
      self = u.sd;
    } else {
      throw Exception("Unknown type '%c'", type);
    }
    break;
  case 'a':
    {
      // Check stack depth to avoid overflow.
      check_recursion_throw();
      auto v = Array::Create();
      v.unserialize(uns);
      self = std::move(v);
    }
    return; // array has '}' terminating
  case 'L':
    {
      int64_t id = uns->readInt();
      uns->expectChar(':');
      String rsrcName;
      rsrcName.unserialize(uns);
      uns->expectChar('{');
      uns->expectChar('}');
      auto rsrc = makeSmartPtr<DummyResource>();
      rsrc->o_setResourceId(id);
      rsrc->m_class_name = rsrcName;
      self = std::move(rsrc);
    }
    return; // resource has '}' terminating
  case 'O':
  case 'V':
  case 'K':
    {
      String clsName;
      clsName.unserialize(uns);

      uns->expectChar(':');
      int64_t size = uns->readInt();
      uns->expectChar(':');
      uns->expectChar('{');

      const bool allowObjectFormatForCollections = true;

      Class* cls;
      // If we are potentially dealing with a collection, we need to try to
      // load the collection class under an alternate name so that we can
      // deserialize data that was serialized before the migration of
      // collections to the HH namespace.

      if (type != 'O') {
        // Collections are CPP builtins; don't attempt to autoload
        cls = Unit::getClass(clsName.get(), /* autoload */ false);
        if (!cls) {
          cls = tryAlternateCollectionClass(clsName.get());
        }
      } else if (allowObjectFormatForCollections) {
        // In order to support the legacy {O|V}:{Set|Vector|Map}
        // serialization, we defer autoloading until we know that there's
        // no alternate (builtin) collection class.
        cls = Unit::getClass(clsName.get(), /* autoload */ false);
        if (!cls) {
          cls = tryAlternateCollectionClass(clsName.get());
        }
        if (!cls) {
          cls = Unit::loadClass(clsName.get()); // with autoloading
        }
      } else {
        cls = Unit::loadClass(clsName.get()); // with autoloading
      }

      Object obj;
      if (RuntimeOption::UnserializationWhitelistCheck &&
          (type == 'O') &&
          !uns->isWhitelistedClass(clsName)) {
        const char* err_msg =
          "The object being unserialized with class name '%s' "
          "is not in the given whitelist. "
          "See http://fburl.com/SafeSerializable for more detail";
        if (RuntimeOption::UnserializationWhitelistCheckWarningOnly) {
          raise_warning(err_msg, clsName.c_str());
        } else {
          raise_error(err_msg, clsName.c_str());
        }
      }
      if (cls) {
        // Only unserialize CPP extension types which can actually
        // support it. Otherwise, we risk creating a CPP object
        // without having it initialized completely.
        if (cls->instanceCtor() && !cls->isCppSerializable()) {
          assert(obj.isNull());
          throw_null_pointer_exception();
        } else {
          obj = Object{cls};
          if (UNLIKELY(collections::isType(cls, CollectionType::Pair) &&
                       (size != 2))) {
            throw Exception("Pair objects must have exactly 2 elements");
          }
        }
      } else {
        obj = Object{SystemLib::s___PHP_Incomplete_ClassClass};
        obj->o_set(s_PHP_Incomplete_Class_Name, clsName);
      }
      assert(!obj.isNull());
      self = obj;

      if (size > 0) {
        // Check stack depth to avoid overflow.
        check_recursion_throw();

        if (type == 'O') {
          // Collections are not allowed
          if (obj->isCollection()) {
            throw Exception("%s does not support the 'O' serialization "
                            "format", clsName.data());
          }

          Variant serializedNativeData = init_null();
          bool hasSerializedNativeData = false;

          /*
            Count backwards so that i is the number of properties
            remaining (to be used as an estimate for the total number
            of dynamic properties when we see the first dynamic prop).
            see getVariantPtr
          */
          for (int64_t i = size; i--; ) {
            Variant v;
            unserializeVariant(v, uns, UnserializeMode::Key);
            String key = v.toString();
            int ksize = key.size();
            const char *kdata = key.data();
            int subLen = 0;
            if (key == ObjectData::s_serializedNativeDataKey) {
              unserializeVariant(serializedNativeData, uns);
              hasSerializedNativeData = true;
            } else if (kdata[0] == '\0') {
              if (UNLIKELY(!ksize)) {
                raise_error("Cannot access empty property");
              }
              // private or protected
              subLen = strlen(kdata + 1) + 2;
              if (UNLIKELY(subLen >= ksize)) {
                if (subLen == ksize) {
                  raise_error("Cannot access empty property");
                } else {
                  throw Exception("Mangled private object property");
                }
              }
              String k(kdata + subLen, ksize - subLen, CopyString);
              Class* ctx = (Class*)-1;
              if (kdata[1] != '*') {
                ctx = Unit::lookupClass(
                  String(kdata + 1, subLen - 2, CopyString).get());
              }
              unserializeProp(uns, obj.get(), k, ctx, key, i + 1);
            } else {
              unserializeProp(uns, obj.get(), key, nullptr, key, i + 1);
            }

            if (i > 0) {
              auto lastChar = uns->peekBack();
              if ((lastChar != ';') && (lastChar != '}')) {
                throw Exception("Object property not terminated properly");
              }
            }
          }

          // nativeDataWakeup is called last to ensure that all properties are
          // already unserialized. We also ensure that nativeDataWakeup is
          // invoked regardless of whether or not serialized native data exists
          // within the serialized content.
          if (obj->getAttribute(ObjectData::HasNativeData) &&
              obj->getVMClass()->getNativeDataInfo()->isSerializable()) {
            Native::nativeDataWakeup(obj.get(), serializedNativeData);
          } else if (hasSerializedNativeData) {
            raise_warning("%s does not expect any serialized native data.",
                          clsName.data());
          }
        } else {
          assert(type == 'V' || type == 'K');
          if (!obj->isCollection()) {
            throw Exception("%s is not a collection class", clsName.data());
          }
          collections::unserialize(obj.get(), uns, size, type);
        }
      }
      uns->expectChar('}');

      if (uns->type() != VariableUnserializer::Type::DebuggerSerialize ||
          (cls && cls->instanceCtor() && cls->isCppSerializable())) {
        // Don't call wakeup when unserializing for the debugger, except for
        // natively implemented classes.
        obj->invokeWakeup();
      }

      check_request_surprise_unlikely();
    }
    return; // object has '}' terminating
  case 'C':
    {
      if (uns->type() == VariableUnserializer::Type::DebuggerSerialize) {
        raise_error("Debugger shouldn't call custom unserialize method");
      }
      String clsName;
      clsName.unserialize(uns);

      uns->expectChar(':');
      String serialized;
      serialized.unserialize(uns, '{', '}');

      auto const obj = [&]() -> Object {
        if (auto const cls = Unit::loadClass(clsName.get())) {
          return Object::attach(g_context->createObject(cls, init_null_variant,
                                                        false /* init */));
        }
        if (!uns->allowUnknownSerializableClass()) {
          raise_error("unknown class %s", clsName.data());
        }
        Object ret = create_object_only(s_PHP_Incomplete_Class);
        ret->o_set(s_PHP_Incomplete_Class_Name, clsName);
        ret->o_set("serialized", serialized);
        return ret;
      }();

      if (!obj->instanceof(SystemLib::s_SerializableClass)) {
        raise_warning("Class %s has no unserializer",
                      obj->getClassName().data());
      } else {
        obj->o_invoke_few_args(s_unserialize, 1, serialized);
        obj.get()->clearNoDestruct();
      }

      self = std::move(obj);
    }
    return; // object has '}' terminating
  default:
    throw Exception("Unknown type '%c'", type);
  }
  uns->expectChar(';');
}
Ejemplo n.º 16
0
void ClassTestSuite::testClass()
{
    //Class test = ClassOf<Test1>();

    Class test = Class::lookup("ClassTest::Test1");

    TS_ASSERT_EQUALS(test.simpleName(), "Test1");

    Class::ClassList superClasses = test.superclasses();

    TS_ASSERT_EQUALS(superClasses.size(), 2);

    Class base1;
    Class base2;

    TS_ASSERT_THROWS(base1.simpleName(), std::runtime_error); // uninitialized handle

    for(const Class& c: superClasses) {
        if (c.fullyQualifiedName() == "ClassTest::TestBase1") {
            base1 = c;
        } else if (c.fullyQualifiedName() == "ClassTest::TestBase2") {
            base2 = c;
        }
    }

    TS_ASSERT_EQUALS(base1.fullyQualifiedName(), "ClassTest::TestBase1");
    TS_ASSERT_EQUALS(base1.simpleName(), "TestBase1");
    TS_ASSERT_EQUALS(base2.fullyQualifiedName(), "ClassTest::TestBase2");
    TS_ASSERT_EQUALS(base2.simpleName(), "TestBase2");

    Class::ConstructorList base1Constructors = base1.constructors();
    TS_ASSERT_EQUALS(base1.constructors().size(), 1);

    Constructor base1Constructor = base1Constructors.front();

    TS_ASSERT_EQUALS(base1Constructor.numberOfArguments(), 0);
    TS_ASSERT_THROWS(base1Constructor.call(), std::runtime_error); // abstract class


    Class::ConstructorList base2Constructors = base2.constructors();
    TS_ASSERT_EQUALS(base2.constructors().size(), 1);

    Constructor base2Constructor = base2Constructors.front();

    TS_ASSERT_EQUALS(base2Constructor.numberOfArguments(), 0);

    VariantValue b2Inst = base2Constructor.call();
    TS_ASSERT(b2Inst.isValid());

    TS_ASSERT_EQUALS(base2.attributes().size(), 0);
    Class::MethodList base2Methods = base2.methods();
    TS_ASSERT_EQUALS(base2Methods.size(), 1);

    Method base2Method1 = base2Methods.front();

    TS_ASSERT_EQUALS(base2Method1.name(), "base2Method1");
    TS_ASSERT(base2Method1.isConst());
    TS_ASSERT(!base2Method1.isVolatile());
    TS_ASSERT(!base2Method1.isStatic());
    TS_ASSERT_EQUALS(base2Method1.numberOfArguments(), 0);
    TS_ASSERT_EQUALS(base2Method1.call(b2Inst).value<int>(), 6);


    Class::ConstructorList testConstructors = test.constructors();
    Class::AttributeList   attributes       = test.attributes();

    TS_ASSERT_EQUALS(attributes.size(), 2);
    Attribute attr = attributes.front();

    WITH_RTTI(TS_ASSERT(attr.type() == typeid(int)));

    TS_ASSERT_EQUALS(testConstructors.size(), 3);

    Constructor defaultConstr;
    Constructor intConstr;

    TS_ASSERT_THROWS(defaultConstr.argumentSpellings(), std::runtime_error);

    for (const Constructor& c: testConstructors) {
        if (c.numberOfArguments() == 0) {
            defaultConstr = c;
        } else if (c.numberOfArguments() == 1  && c.argumentSpellings()[0] == "int") {
            intConstr = c;
        }
    }


    TS_ASSERT_EQUALS(defaultConstr.numberOfArguments(), 0);
    TS_ASSERT_EQUALS(intConstr.numberOfArguments(), 1);

    VariantValue testInst1 = defaultConstr.call();

    TS_ASSERT(testInst1.isA<Test1>());

    TS_ASSERT_EQUALS(attr.get(testInst1).value<int>(), 3);


    VariantValue testInst2 = intConstr.call(77);

    TS_ASSERT(testInst2.isA<Test1>());
    TS_ASSERT_EQUALS(attr.get(testInst2).value<int>(), 77);

    Class::MethodList methods = test.methods();

    TS_ASSERT_EQUALS(methods.size(), 7);

    Method base1Method1;
    Method method1;
    Method method2;
    Method staticMethod;


    for (const Method& m: methods) {
        if (m.name() == "base1Method1") {
            base1Method1 = m;
        } else if (m.name() == "base2Method1") {
            base2Method1 = m;
        } else if (m.name() == "method1") {
            method1 = m;
        } else if (m.name() == "method2") {
            method2 = m;
        } else if (m.name() == "staticMethod") {
            staticMethod = m;
        }
    }

    TS_ASSERT_EQUALS(base1Method1.name(), "base1Method1");
    TS_ASSERT(!base1Method1.isConst());
    TS_ASSERT(!base1Method1.isStatic());
    TS_ASSERT(!base1Method1.isVolatile());
    WITH_RTTI(TS_ASSERT(base1Method1.returnType() == typeid(int)));
    TS_ASSERT_EQUALS(base1Method1.numberOfArguments(), 0);
    TS_ASSERT_EQUALS(base1Method1.call(testInst2).value<int>(), 5);

    TS_ASSERT_EQUALS(base2Method1.name(), "base2Method1");
    TS_ASSERT(base2Method1.isConst());
    TS_ASSERT(!base2Method1.isStatic());
    TS_ASSERT(!base2Method1.isVolatile());
    WITH_RTTI(TS_ASSERT(base2Method1.returnType() == typeid(int)));
    TS_ASSERT_EQUALS(base2Method1.numberOfArguments(), 0);
    TS_ASSERT_EQUALS(base2Method1.call(testInst2).value<int>(), 6);

    TS_ASSERT_EQUALS(method2.name(), "method2");
    TS_ASSERT(!method2.isConst());
    TS_ASSERT(!method2.isStatic());
    TS_ASSERT(!method2.isVolatile());
    WITH_RTTI(TS_ASSERT(method2.returnType() == typeid(double)));
    TS_ASSERT_EQUALS(method2.numberOfArguments(), 1);
    WITH_RTTI(TS_ASSERT(*method2.argumentTypes()[0] == typeid(double)));
    TS_ASSERT_EQUALS(method2.call(testInst2, 2).value<double>(), 6.28);

    TS_ASSERT_EQUALS(staticMethod.name(), "staticMethod");
    TS_ASSERT(!staticMethod.isConst());
    TS_ASSERT(staticMethod.isStatic());
    TS_ASSERT(!staticMethod.isVolatile());
    WITH_RTTI(TS_ASSERT(staticMethod.returnType() == typeid(double)));
    TS_ASSERT_EQUALS(staticMethod.numberOfArguments(), 0);
    TS_ASSERT_EQUALS(staticMethod.call().value<double>(), 3.14);
}
Ejemplo n.º 17
0
int main(int argc, char**argv)
{
  Arguments info;
  if(!parseOptions (argc, argv, info))
    return 1;

  ESMReader esm;
  esm.setEncoding(info.encoding);

  string filename = info.filename;
  cout << "\nFile: " << filename << endl;

  try {

  if(info.raw_given)
    {
      cout << "RAW file listing:\n";

      esm.openRaw(filename);

      printRaw(esm);

      return 0;
    }

  bool quiet = info.quiet_given;
  bool loadCells = info.loadcells_given;

  esm.open(filename);

  cout << "Author: " << esm.getAuthor() << endl;
  cout << "Description: " << esm.getDesc() << endl;
  cout << "File format version: " << esm.getFVer() << endl;
  cout << "Special flag: " << esm.getSpecial() << endl;
  cout << "Masters:\n";
  ESMReader::MasterList m = esm.getMasters();
  for(unsigned int i=0;i<m.size();i++)
    cout << "  " << m[i].name << ", " << m[i].size << " bytes\n";

  // Loop through all records
  while(esm.hasMoreRecs())
    {
      NAME n = esm.getRecName();
      esm.getRecHeader();
      string id = esm.getHNOString("NAME");
      if(!quiet)
        cout << "\nRecord: " << n.toString()
             << " '" << id << "'\n";

      switch(n.val)
        {
        case REC_ACTI:
          {
            Activator ac;
            ac.load(esm);
            if(quiet) break;
            cout << "  Name: " << ac.name << endl;
            cout << "  Mesh: " << ac.model << endl;
            cout << "  Script: " << ac.script << endl;
            break;
          }
        case REC_ALCH:
          {
            Potion p;
            p.load(esm);
            if(quiet) break;
            cout << "  Name: " << p.name << endl;
            break;
          }
        case REC_APPA:
          {
            Apparatus p;
            p.load(esm);
            if(quiet) break;
            cout << "  Name: " << p.name << endl;
            break;
          }
        case REC_ARMO:
          {
            Armor am;
            am.load(esm);
            if(quiet) break;
            cout << "  Name: " << am.name << endl;
            cout << "  Mesh: " << am.model << endl;
            cout << "  Icon: " << am.icon << endl;
            cout << "  Script: " << am.script << endl;
            cout << "  Enchantment: " << am.enchant << endl;
            cout << "  Type: " << am.data.type << endl;
            cout << "  Weight: " << am.data.weight << endl;
            break;
          }
        case REC_BODY:
          {
            BodyPart bp;
            bp.load(esm);
            if(quiet) break;
            cout << "  Name: " << bp.name << endl;
            cout << "  Mesh: " << bp.model << endl;
            break;
          }
        case REC_BOOK:
          {
            Book b;
            b.load(esm);
            if(quiet) break;
            cout << "  Name: " << b.name << endl;
            cout << "  Mesh: " << b.model << endl;
            break;
          }
        case REC_BSGN:
          {
            BirthSign bs;
            bs.load(esm);
            if(quiet) break;
            cout << "  Name: " << bs.name << endl;
            cout << "  Texture: " << bs.texture << endl;
            cout << "  Description: " << bs.description << endl;
            break;
          }
        case REC_CELL:
          {
            Cell b;
            b.load(esm);
            if(!quiet)
              {
                cout << "  Name: " << b.name << endl;
                cout << "  Region: " << b.region << endl;
              }
            if(loadCells)
              loadCell(b, esm, quiet);
            break;
          }
        case REC_CLAS:
          {
            Class b;
            b.load(esm);
            if(quiet) break;
            cout << "  Name: " << b.name << endl;
            cout << "  Description: " << b.description << endl;
            break;
          }
        case REC_CLOT:
          {
            Clothing b;
            b.load(esm);
            if(quiet) break;
            cout << "  Name: " << b.name << endl;
            break;
          }
        case REC_CONT:
          {
            Container b;
            b.load(esm);
            if(quiet) break;
            cout << "  Name: " << b.name << endl;
            break;
          }
        case REC_CREA:
          {
            Creature b;
            b.load(esm, id);
            if(quiet) break;
            cout << "  Name: " << b.name << endl;
            break;
          }
        case REC_DIAL:
          {
            Dialogue b;
            b.load(esm);
            break;
          }
        case REC_DOOR:
          {
            Door d;
            d.load(esm);
            if(quiet) break;
            cout << "  Name: " << d.name << endl;
            cout << "  Mesh: " << d.model << endl;
            cout << "  Script: " << d.script << endl;
            cout << "  OpenSound: " << d.openSound << endl;
            cout << "  CloseSound: " << d.closeSound << endl;
            break;
          }
        case REC_ENCH:
          {
            Enchantment b;
            b.load(esm);
            break;
          }
        case REC_GMST:
          {
            GameSetting b;
            b.id = id;
            b.load(esm);
            if(quiet) break;
            cout << "  Value: ";
            if(b.type == VT_String)
              cout << "'" << b.str << "' (string)";
            else if(b.type == VT_Float)
              cout << b.f << " (float)";
            else if(b.type == VT_Int)
              cout << b.i << " (int)";
            cout << "\n  Dirty: " << b.dirty << endl;
            break;
          }
        case REC_INFO:
          {
            DialInfo p;
            p.load(esm);
            if(quiet) break;
            cout << "  Id: " << p.id << endl;
            cout << "  Text: " << p.response << endl;
            break;
          }
        case REC_SOUN:
          {
            Sound d;
            d.load(esm);
            if(quiet) break;
            cout << "  Sound: " << d.sound << endl;
            cout << "  Volume: " << (int)d.data.volume << endl;
            break;
          }
        case REC_SPEL:
          {
            Spell s;
            s.load(esm);
            if(quiet) break;
            cout << "  Name: " << s.name << endl;
            break;
          }
        default:
          esm.skipRecord();
          if(quiet) break;
          cout << "  Skipping\n";
        }
    }

  } catch(exception &e)
    {
      cout << "\nERROR:\n\n  " << e.what() << endl;
      return 1;
    }

  return 0;
}
Ejemplo n.º 18
0
/* Look at this class and it's superclass contents (which includes
 * included modules) and calculate out how to allocate the slots.
 *
 * This locks the class so that construction is serialized.
 */
void Class::auto_pack(STATE, GCToken gct, CallFrame* call_frame) {
    Class* self = this;
    OnStack<1> os(state, self);

    hard_lock(state, gct, call_frame);

    // If another thread did this work while we were waiting on the lock,
    // don't redo it.
    if(self->type_info_->type == PackedObject::type) {
        self->hard_unlock(state, gct, call_frame);
        return;
    }

    size_t slots = 0;

    LookupTable* lt = LookupTable::create(state);

    // If autopacking is enabled, figure out how many slots to use.
    if(state->shared().config.gc_autopack) {
        Module* mod = self;

        int slot = 0;

        while(!mod->nil_p()) {
            Array* info = 0;

            if(Class* cls = try_as<Class>(mod)) {
                info = cls->seen_ivars();
            } else if(IncludedModule* im = try_as<IncludedModule>(mod)) {
                info = im->module()->seen_ivars();
            }

            if(info && !info->nil_p()) {
                for(native_int i = 0; i < info->size(); i++) {
                    if(Symbol* sym = try_as<Symbol>(info->get(state, i))) {
                        bool found = false;
                        lt->fetch(state, sym, &found);

                        if(!found) {
                            lt->store(state, sym, Fixnum::from(slot++));
                        }
                    }

                    // Limit the number of packed ivars to 25.
                    if(slot > 25) break;
                }
            }

            mod = mod->superclass();
        }
        slots = lt->entries()->to_native();
    }

    self->set_packed_size(sizeof(Object) + (slots * sizeof(Object*)));
    self->packed_ivar_info(state, lt);

    atomic::memory_barrier();
    self->set_object_type(state, PackedObject::type);

    self->hard_unlock(state, gct, call_frame);
}
Ejemplo n.º 19
0
void Context::create_classes()
{
	// Construct classes
	Class *obc = new Class( 0 ); obc->set_name("Object"); 
	Class *clc = new Class( 0 ); clc->set_name("Class"); clc->clas = obc->clas = clc;
	Class *nic = new Class(clc); nic->set_name("Nil");   
	Class *inc = new Class(clc); inc->set_name("Integer");
	Class *nac = new Class(clc); nac->set_name("Native");      
	Class *stc = new Class(clc); stc->set_name("String");      
	Class *trc = new Class(clc); trc->set_name("True");
	Class *fac = new Class(clc); fac->set_name("False");

	obc->set_base( 0 , TYPE_OBJECT);
	clc->set_base(obc, TYPE_CLASS);
	nic->set_base(obc, TYPE_NIL);
	inc->set_base(obc, TYPE_INTEGER);
	nac->set_base(obc, TYPE_NATIVE);
	stc->set_base(obc, TYPE_STRING);
	trc->set_base(obc, TYPE_TRUE);
	fac->set_base(obc, TYPE_FALSE);

	// Add classes
	this->object_class = obc;
	this->class_class = clc;
	this->nil_class = nic;
	this->integer_class = inc;
	this->native_class = nac;
	this->string_class = stc;
	this->true_class = trc;
	this->false_class = fac;

	// Add objects
	this->true_obj = Value(new True(trc));
	this->false_obj = Value(new False(fac));
	this->nil_obj = Value((Object*)0);

	// Finally (!), add methods to classes.
	Object::install_methods(obc);
	True::install_methods(trc);
	False::install_methods(fac);
	Nil::install_methods(nic);
	Class::install_methods(clc);
	Native::install_methods(nac);
	String::install_methods(stc);
	Integer::install_methods(inc);
}
Ejemplo n.º 20
0
bool Class::load_ancestors(Global_Env* env)
{
    m_state = ST_LoadingAncestors;

    const String* superName = get_super_class_name();

    if(superName == NULL) {
        if(env->InBootstrap() || get_name() != env->JavaLangClass_String) {
            // This class better be java.lang.Object
            if(get_name() != env->JavaLangObject_String) {
                // ClassFormatError
                std::stringstream ss;
                ss << get_name()->bytes
                    << ": class does not have superclass "
                    << "but the class is not java.lang.Object";
                REPORT_FAILED_CLASS_CLASS(m_class_loader, this,
                    "java/lang/ClassFormatError", ss.str().c_str());
                return false;
            }
        }
    } else {
        // Load super class
        Class* superClass;
        m_super_class.name = NULL;
        superClass = m_class_loader->LoadVerifyAndPrepareClass(env, superName);
        if(superClass == NULL) {
            assert(exn_raised());
            return false;
        }

        if(superClass->is_interface()) {
            REPORT_FAILED_CLASS_CLASS(m_class_loader, this,
                "java/lang/IncompatibleClassChangeError",
                "class " << m_name->bytes << " has interface "
                << superClass->get_name()->bytes << " as super class");
            return false;
        }
        if(superClass->is_final()) {
            REPORT_FAILED_CLASS_CLASS(m_class_loader, this,
                "java/lang/VerifyError",
                m_name->bytes << " cannot inherit from final class "
                << superClass->get_name()->bytes);
            return false;
        }

        // super class was successfully loaded
        m_super_class.clss = superClass;
        if(m_super_class.cp_index) {
            m_const_pool.resolve_entry(m_super_class.cp_index, superClass);
        }

        // if it's an interface, its superclass must be java/lang/Object
        if(is_interface()) {
            if((env->JavaLangObject_Class != NULL) && (superClass != env->JavaLangObject_Class)) {
                std::stringstream ss;
                ss << get_name()->bytes << ": interface superclass is not java.lang.Object";
                REPORT_FAILED_CLASS_CLASS(m_class_loader, this,
                    "java/lang/ClassFormatError", ss.str().c_str());
                return false;
            }
        }

        // Update the cha_first_child and cha_next_sibling fields.
        m_cha_first_child = NULL;
        if(has_super_class())
        {
            m_cha_next_sibling = get_super_class()->m_cha_first_child;
            get_super_class()->m_cha_first_child = this;
        }
    }

    //
    // load in super interfaces
    //
    for(unsigned i = 0; i < m_num_superinterfaces; i++ ) {
        const String* intfc_name = m_superinterfaces[i].name;
        Class* intfc = m_class_loader->LoadVerifyAndPrepareClass(env, intfc_name);
        if(intfc == NULL) {
            assert(exn_raised());
            return false;
        }
        if(!intfc->is_interface()) {
            REPORT_FAILED_CLASS_CLASS(m_class_loader, this,
                "java/lang/IncompatibleClassChangeError",
                get_name()->bytes << ": " << intfc->get_name()->bytes
                << " is not an interface");
            return false;
        }

        // superinterface was successfully loaded
        m_superinterfaces[i].clss = intfc;
        if(m_superinterfaces[i].cp_index != 0) {
            // there are no constant pool entries for array classes
            m_const_pool.resolve_entry(m_superinterfaces[i].cp_index, intfc);
        }
    }
    // class, superclass, and superinterfaces successfully loaded

    m_state = ST_Loaded;
    if(!is_array())
        m_package = m_class_loader->ProvidePackage(env, m_name, NULL);

    return true;
}
Ejemplo n.º 21
0
static bool
Snapshot(JSContext *cx, JSObject *obj, uintN flags, AutoIdVector *props)
{
    IdSet ht(cx);
    if (!ht.init(32))
        return NULL;

    JSObject *pobj = obj;
    do {
        Class *clasp = pobj->getClass();
        if (pobj->isNative() &&
            !pobj->getOps()->enumerate &&
            !(clasp->flags & JSCLASS_NEW_ENUMERATE)) {
            if (!clasp->enumerate(cx, pobj))
                return false;
            if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props))
                return false;
        } else if (pobj->isDenseArray()) {
            if (!EnumerateDenseArrayProperties(cx, obj, pobj, flags, ht, props))
                return false;
        } else {
            if (pobj->isProxy()) {
                AutoIdVector proxyProps(cx);
                if (flags & JSITER_OWNONLY) {
                    if (flags & JSITER_HIDDEN) {
                        if (!JSProxy::getOwnPropertyNames(cx, pobj, proxyProps))
                            return false;
                    } else {
                        if (!JSProxy::keys(cx, pobj, proxyProps))
                            return false;
                    }
                } else {
                    if (!JSProxy::enumerate(cx, pobj, proxyProps))
                        return false;
                }
                for (size_t n = 0, len = proxyProps.length(); n < len; n++) {
                    if (!Enumerate(cx, obj, pobj, proxyProps[n], true, flags, ht, props))
                        return false;
                }
                /* Proxy objects enumerate the prototype on their own, so we are done here. */
                break;
            }
            Value state;
            JSIterateOp op = (flags & JSITER_HIDDEN) ? JSENUMERATE_INIT_ALL : JSENUMERATE_INIT;
            if (!pobj->enumerate(cx, op, &state, NULL))
                return false;
            if (state.isMagic(JS_NATIVE_ENUMERATE)) {
                if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props))
                    return false;
            } else {
                while (true) {
                    jsid id;
                    if (!pobj->enumerate(cx, JSENUMERATE_NEXT, &state, &id))
                        return false;
                    if (state.isNull())
                        break;
                    if (!Enumerate(cx, obj, pobj, id, true, flags, ht, props))
                        return false;
                }
            }
        }

        if ((flags & JSITER_OWNONLY) || pobj->isXML())
            break;
    } while ((pobj = pobj->getProto()) != NULL);

    return true;
}
Ejemplo n.º 22
0
void COutputStreamSerializer::SavePackage (std::ostream *s, void *rootObj, Class *rootObjClass)
{
	PackageHeader ph;

	stream = s;
	unsigned startOffset = stream->tellp();

	stream->seekp (startOffset + sizeof (PackageHeader));
	ph.objDataOffset = (int)stream->tellp();

	// Insert the first object that will provide references to everything
	ObjectID obj;
	obj.class_ = rootObjClass;
	obj.isEmbedded = false;
	obj.id = 0;
	ptrToID[rootObj] = obj;
	pendingObjects.push_back (ptrToID.find(rootObj));
	objects.push_back (&ptrToID[rootObj]);

	// Save until all the referenced objects have been stored
	while (!pendingObjects.empty ())
	{
		vector <ObjIDmap::iterator> po = pendingObjects;
		pendingObjects.clear ();

		for (vector<ObjIDmap::iterator>::iterator i=po.begin();i!=po.end();++i)
		{
			ObjectID& obj = (*i)->second;
			obj.class_->SerializeInstance (this, (*i)->first);
		}
	}

	// Collect a set of all used classes
	map<creg::Class *,ClassRef> classMap;
	vector <ClassRef*> classRefs;
	for (ObjIDmap::iterator oi = ptrToID.begin(); oi != ptrToID.end(); ++oi) {
		//printf ("Obj: %s\n", oi->second.class_->name.c_str());
		map<creg::Class*,ClassRef>::iterator cr = classMap.find (oi->second.class_);
		if (cr == classMap.end()) {
			ClassRef *pRef = &classMap[oi->second.class_];
			pRef->index = classRefs.size();
			pRef->class_ = oi->second.class_;

			classRefs.push_back (pRef);
			oi->second.classIndex = pRef->index;
		} else 
			oi->second.classIndex = cr->second.index;
	}

	// Write the class references
	ph.numObjClassRefs = classRefs.size();
	ph.objClassRefOffset = (int)stream->tellp();
	for (uint a=0;a<classRefs.size();a++) {
		WriteZStr (*stream, classRefs[a]->class_->name);
		// write a checksum (unused atm)
		int checksum = swabdword(0);
		stream->write ((char*)&checksum, sizeof(int));
	}

	// Write object info
	ph.objTableOffset = (int)stream->tellp();
	ph.numObjects = objects.size();
	for (uint a=0;a<objects.size();a++)
	{
		ObjectID *o = objects[a];
		PackageObject d;

		d.classRefIndex = o->classIndex;
		d.isEmbedded = o->isEmbedded ? 1 : 0;

		d.SwapBytes ();
		stream->write ((char*)&d, sizeof(PackageObject));
	}

	// Calculate a checksum for metadata verification
	ph.metadataChecksum = 0;
	for (uint a=0;a<classRefs.size();a++)
	{
		Class *c = classRefs[a]->class_;
		c->CalculateChecksum (ph.metadataChecksum);
	}
	printf("Checksum: %d\n", ph.metadataChecksum);

	stream->seekp (startOffset);
	memcpy(ph.magic, CREG_PACKAGE_FILE_ID, 4);
	ph.SwapBytes ();
	stream->write ((const char *)&ph, sizeof(PackageHeader));

	objects.clear();
	ptrToID.clear();
}
Ejemplo n.º 23
0
xdebug_xml_node* xdebug_var_export_xml_node(const char* name,
                                            const char* fullName,
                                            const char* facet,
                                            const Variant& var,
                                            XDebugExporter& exporter) {
  // Setup the node. Each const cast is necessary due to xml api
  xdebug_xml_node* node = xdebug_xml_node_init("property");
  if (name != nullptr) {
    xdebug_xml_add_attribute_ex(node, "name", const_cast<char*>(name), 0, 1);
  }
  if (fullName != nullptr) {
    xdebug_xml_add_attribute_ex(node, "fullname", const_cast<char*>(fullName),
                                0, 1);
  }
  if (facet != nullptr) {
    xdebug_xml_add_attribute_ex(node, "facet", const_cast<char*>(facet), 0, 1);
  }
  xdebug_xml_add_attribute_ex(node, "address",
                              xdebug_sprintf("%ld", (long) &var), 0, 1);

  // Case on the type for the rest
  if (var.isBoolean()) {
    xdebug_xml_add_attribute(node, "type", "bool");
    xdebug_xml_add_text(node, xdebug_sprintf("%d",  var.toBoolean()));
  } else if (var.isNull()) {
    xdebug_xml_add_attribute(node, "type", "null");
  } else if (var.isInteger()) {
    xdebug_xml_add_attribute(node, "type", "int");
    xdebug_xml_add_text(node, xdebug_sprintf("%ld", var.toInt64()));
  } else if (var.isDouble()) {
    xdebug_xml_add_attribute(node, "type", "float");
    xdebug_xml_add_text(node, xdebug_sprintf("%lG", var.toDouble()));
  } else if (var.isString()) {
    // Add the type and the original size
    String str = var.toString();
    xdebug_xml_add_attribute(node, "type", "string");
    xdebug_xml_add_attribute_ex(node, "size",
                                xdebug_sprintf("%d", str.size()), 0, 1);

    // Possibly shrink the string, then add it to the node
    if (exporter.max_data != 0 && str.size() > exporter.max_data) {
      str = str.substr(0, exporter.max_data);
    }
    xdebug_xml_add_text_encodel(node, xdstrdup(str.data()), str.size());
  } else if (var.isArray()) {
    Array arr = var.toArray();
    xdebug_xml_add_attribute(node, "type", "array");
    xdebug_xml_add_attribute(node, "children",
                             const_cast<char*>(arr.size() > 0 ? "1" : "0"));

    // If we've already seen this object, return
    if (exporter.counts[arr.get()]++ > 0) {
      xdebug_xml_add_attribute(node, "recursive", "1");
      return node;
    }

    // Write the # of children then short-circuit if we are too deep
    xdebug_xml_add_attribute_ex(node, "numchildren",
                                xdebug_sprintf("%d", arr.size()), 0, 1);
    if (exporter.level++ >= exporter.max_depth) {
      return node;
    }

    // Compute the page and the start/end indices
    // Note that php xdebug doesn't support pages except for at the top level
    uint32_t page = exporter.level == 0 ? exporter.page : 0;
    uint32_t start = page * exporter.max_children;
    uint32_t end = (page + 1) * exporter.max_children;
    xdebug_xml_add_attribute_ex(node, "page", xdebug_sprintf("%d", page), 0, 1);
    xdebug_xml_add_attribute_ex(node, "pagesize",
                                xdebug_sprintf("%d", exporter.max_children),
                                0, 1);
    // Add each child
    ArrayIter iter(arr);
    iter.setPos(start);
    for (uint32_t i = start; i < end && iter; i++, ++iter) {
      xdebug_array_element_export_xml_node(*node, name,
                                           iter.first(),
                                           iter.second(),
                                           exporter);
    }

    // Done at this level
    exporter.level--;
    exporter.counts[arr.get()]--;
  } else if (var.isObject()) {
    // TODO(#4489053) This could be merged into the above array code. For now,
    // it's separate as this was pulled originally from xdebug
    ObjectData* obj = var.toObject().get();
    Class* cls = obj->getVMClass();
    Array props = get_object_props(obj);

    // Add object info
    xdebug_xml_add_attribute(node, "type", "object");
    xdebug_xml_add_attribute_ex(node, "classname",
                                xdstrdup(cls->name()->data()), 0, 1);
    xdebug_xml_add_attribute(node, "children",
                             const_cast<char*>(props.size() ? "1" : "0"));

    // If we've already seen this object, return
    if (exporter.counts[obj]++ > 0) {
      return node;
    }

    // Add the # of props then short circuit if we are too deep
    xdebug_xml_add_attribute_ex(node, "numchildren",
                                xdebug_sprintf("%d", props.size()), 0, 1);
    if (exporter.level++ >= exporter.max_depth) {
      return node;
    }

    // Compute the page and the start/end indices
    // Note that php xdebug doesn't support pages except for at the top level
    uint32_t page = exporter.level == 1 ? exporter.page : 0;
    uint32_t start = page * exporter.max_children;
    uint32_t end = (page + 1) * exporter.max_children;
    xdebug_xml_add_attribute_ex(node, "page", xdebug_sprintf("%d", page), 0, 1);
    xdebug_xml_add_attribute_ex(node, "pagesize",
                                xdebug_sprintf("%d", exporter.max_children),
                                0, 1);

    // Add each property
    ArrayIter iter(props);
    iter.setPos(start);
    for (uint32_t i = start; i < end && iter; i++, ++iter) {
      xdebug_object_element_export_xml_node(*node, name, obj,
                                            iter.first(),
                                            iter.second(),
                                            exporter);
    }

    // Done at this level
    exporter.level--;
    exporter.counts[(void*) obj]--;
  } else if (var.isResource()) {
    ResourceData* res = var.toResource().get();
    xdebug_xml_add_attribute(node, "type", "resource");
    const char* text = xdebug_sprintf("resource id='%ld' type='%s'",
                                      res->o_getId(),
                                      res->o_getResourceName().data());
    xdebug_xml_add_text(node, const_cast<char*>(text));
  } else {
    xdebug_xml_add_attribute(node, "type", "null");
  }
  return node;
}
Ejemplo n.º 24
0
static inline const String& ctxClassName() {
  Class* ctx = g_vmContext->getContextClass();
  return ctx ? ctx->nameRef() : empty_string;
}
Ejemplo n.º 25
0
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj_, JSPropertyDescArray *pda)
{
    RootedObject obj(cx, obj_);

    assertSameCompartment(cx, obj);
    uint32_t i = 0;
    JSPropertyDesc *pd = NULL;

    if (obj->isDebugScope()) {
        AutoIdVector props(cx);
        if (!Proxy::enumerate(cx, obj, props))
            return false;

        pd = (JSPropertyDesc *)cx->calloc_(props.length() * sizeof(JSPropertyDesc));
        if (!pd)
            return false;

        for (i = 0; i < props.length(); ++i) {
            pd[i].id = JSVAL_NULL;
            pd[i].value = JSVAL_NULL;
            if (!js_AddRoot(cx, &pd[i].id, NULL))
                goto bad;
            pd[i].id = IdToValue(props[i]);
            if (!js_AddRoot(cx, &pd[i].value, NULL))
                goto bad;
            if (!Proxy::get(cx, obj, obj, props.handleAt(i), MutableHandleValue::fromMarkedLocation(&pd[i].value)))
                goto bad;
        }

        pda->length = props.length();
        pda->array = pd;
        return true;
    }

    Class *clasp;
    clasp = obj->getClass();
    if (!obj->isNative() || (clasp->flags & JSCLASS_NEW_ENUMERATE)) {
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                             JSMSG_CANT_DESCRIBE_PROPS, clasp->name);
        return false;
    }
    if (!clasp->enumerate(cx, obj))
        return false;

    /* Return an empty pda early if obj has no own properties. */
    if (obj->nativeEmpty()) {
        pda->length = 0;
        pda->array = NULL;
        return true;
    }

    pd = (JSPropertyDesc *)cx->malloc_(obj->propertyCount() * sizeof(JSPropertyDesc));
    if (!pd)
        return false;
    for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront()) {
        pd[i].id = JSVAL_NULL;
        pd[i].value = JSVAL_NULL;
        pd[i].alias = JSVAL_NULL;
        if (!js_AddRoot(cx, &pd[i].id, NULL))
            goto bad;
        if (!js_AddRoot(cx, &pd[i].value, NULL))
            goto bad;
        Shape *shape = const_cast<Shape *>(&r.front());
        if (!GetPropertyDesc(cx, obj, shape, &pd[i]))
            goto bad;
        if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
            goto bad;
        if (++i == obj->propertyCount())
            break;
    }
    pda->length = i;
    pda->array = pd;
    return true;

bad:
    pda->length = i + 1;
    pda->array = pd;
    JS_PutPropertyDescArray(cx, pda);
    return false;
}
Ejemplo n.º 26
0
llvm::Value* FunctionCall::load(Context &context) {
	std::vector<Type*> actual_type;
	for (std::list<Expression*>::iterator it = arg_list.begin(); it != arg_list.end(); it++)
		actual_type.push_back((*it)->getType(context));

	Symbol *symbol = NULL;
	Class *targetClass = NULL;
	if (target == NULL) {
		// static call or self call
		if (identifier->getName().rfind("::") != std::string::npos) {
			// static call

			// find class
			targetClass = context.findClass(identifier->getName().substr(0, identifier->getName().rfind("::")));
			if (!targetClass)
				throw SymbolNotFound("Class '" + identifier->getName().substr(0, identifier->getName().rfind("::")) + "'");

			// find function
			symbol = targetClass->findSymbol(identifier->getName().substr(identifier->getName().rfind("::") + 2));
			if (!symbol)
				throw SymbolNotFound("Function '" + identifier->getName() + "'");

			// match the best override
			symbol = bestMatch(symbol, actual_type, context);
			if (!symbol)
				throw SymbolNotFound("No matching call for '" + Function::genName(identifier->getName(), actual_type) + "'");

			// check symbol is static function
			if (symbol->type != Symbol::STATIC_FUNCTION)
				throw InvalidType("'" + symbol->data.function.function->getName() + "' is not a static function");

			// check symbol's permission
			if (symbol->data.static_function.isPrivate && targetClass != context.currentClass)
				throw CompileException("function '" + symbol->data.static_function.function->getName() + "' is private");
			if (symbol->data.static_function.isProtected && !Class::isA(context.currentClass, targetClass))
				throw CompileException("function '" + symbol->data.static_function.function->getName() + "' is protected");
		} else {
			// self call
			targetClass = context.currentClass;

			// find function
			symbol = targetClass->findSymbol(identifier->getName());
			if (!symbol)
				throw SymbolNotFound("'" + identifier->getName() + "'");

			symbol = bestMatch(symbol, actual_type, context);
			if (!symbol)
				throw SymbolNotFound("No matching call for '" + Function::genName(identifier->getName(), actual_type) + "'");
		}
	} else {
		// member function call
		targetClass = target->getType(context)->getClass();
		
		// find function
		symbol = targetClass->findSymbol(identifier->getName());
		if (!symbol)
			throw SymbolNotFound("Function '" + identifier->getName() + "'");

		symbol = bestMatch(symbol, actual_type, context);
		if (!symbol)
			throw SymbolNotFound("No matching call for '" + Function::genName(identifier->getName(), actual_type) + "'");

		// check symbol is normal function
		if (symbol->type != Symbol::FUNCTION)
			throw InvalidType("function '" + symbol->data.static_function.function->getName() + "' is not a member function");

		// check symbol's permission
		if (symbol->data.static_function.isPrivate && targetClass != context.currentClass)
			throw CompileException("function '" + symbol->data.static_function.function->getName() + "' is private");
		if (symbol->data.static_function.isProtected && !Class::isA(context.currentClass, targetClass))
			throw CompileException("function '" + symbol->data.static_function.function->getName() + "' is protected");
	}

	llvm::Value *function;
	std::vector<llvm::Value*> arg_code;
	switch (symbol->type) {
	case Symbol::FUNCTION: {
		Expression *tmpTarget = target ? target : new Identifier("this");
		if (!tmpTarget->getType(context)->isObject())
			throw InvalidType(std::string("calling a function of ") + tmpTarget->getType(context)->getName());
		llvm::Value *thisval = tmpTarget->load(context);
		if (!target)
			delete tmpTarget;

		if (targetClass->getMangleName()[0] == 'J') {
			// locate vtable
			function = addDebugLoc(
					context,
					context.getBuilder().CreateLoad(
							thisval
					),
					loc
			);
			// for interface call, we have to recalculate the object base address
			// load offset from vtable
			llvm::Value *baseOffset = addDebugLoc(
					context,
					context.getBuilder().CreateLoad(
							addDebugLoc(
									context,
									context.getBuilder().CreateStructGEP(
											nullptr,
											function,
											0
									),
									loc
							)
					),
					loc
			);
			// calculate the base address
			thisval = addDebugLoc(
					context,
					context.getBuilder().CreateIntToPtr(
							addDebugLoc(
									context,
									context.getBuilder().CreateSub(
											addDebugLoc(
													context,
													context.getBuilder().CreatePtrToInt(
															thisval,
															context.getBuilder().getInt32Ty()
													),
													loc
											),
											baseOffset
									),
									loc
							),
							context.getBuilder().getInt8PtrTy(0)
					),
					loc
			);
		} else {
			// locate vtable
			function = addDebugLoc(
					context,
					context.getBuilder().CreateLoad(
							addDebugLoc(
									context,
									context.getBuilder().CreateStructGEP(
											nullptr,
											thisval,
											symbol->data.function.vtableOffset
									),
									loc
							)
					),
					loc
			);

			// for object call, we only need type cast
			thisval = context.getBuilder().CreatePointerCast(
					thisval,
					context.getBuilder().getInt8PtrTy(0)
			);
		}
		// add thisval as the first argument
		arg_code.push_back(thisval);
		// load function pointer from vtable
		function = addDebugLoc(
				context,
				context.getBuilder().CreateLoad(
						addDebugLoc(
								context,
								context.getBuilder().CreateStructGEP(
										nullptr,
										function,
										symbol->data.function.funcPtrOffset
								),
								loc
						)
				),
				loc
		);
		break; }
	case Symbol::STATIC_FUNCTION:
		function = symbol->data.static_function.function->getLLVMFunction(context);
		if (target)
			throw CompileException("Calling a static function of an object");
		break;
	default:
		throw InvalidType("calling a symbol which is not a function");
	}

	// load remaining arguments
	{
		Function *func = symbol->type == Symbol::FUNCTION ? symbol->data.function.function : symbol->data.static_function.function;
		Function::arg_iterator it2 = func->arg_begin();
		for (std::list<Expression*>::iterator it = arg_list.begin(); it != arg_list.end(); it++, it2++)
			arg_code.push_back(Type::cast(context, (*it)->getType(context), (*it)->load(context), it2->first));
	}

	// do the call
	llvm::Value *ans = addDebugLoc(
			context,
			context.getBuilder().CreateCall(function, llvm::ArrayRef<llvm::Value*>(arg_code)),
			loc);
	return ans;
}
Ejemplo n.º 27
0
Array createBacktrace(const BacktraceArgs& btArgs) {
  Array bt = Array::Create();

  // If there is a parser frame, put it at the beginning of
  // the backtrace
  if (btArgs.m_parserFrame) {
    bt.append(
      make_map_array(
        s_file, btArgs.m_parserFrame->filename,
        s_line, btArgs.m_parserFrame->lineNumber
      )
    );
  }

  VMRegAnchor _;
  if (!vmfp()) {
    // If there are no VM frames, we're done
    return bt;
  }

  int depth = 0;
  ActRec* fp = nullptr;
  Offset pc = 0;

  // Get the fp and pc of the top frame (possibly skipping one frame)
  {
    if (btArgs.m_skipTop) {
      fp = g_context->getPrevVMState(vmfp(), &pc);
      if (!fp) {
        // We skipped over the only VM frame, we're done
        return bt;
      }
    } else {
      fp = vmfp();
      Unit *unit = vmfp()->m_func->unit();
      assert(unit);
      pc = unit->offsetOf(vmpc());
    }

    // Handle the top frame
    if (btArgs.m_withSelf) {
      // Builtins don't have a file and line number
      if (!fp->m_func->isBuiltin()) {
        Unit* unit = fp->m_func->unit();
        assert(unit);
        const char* filename = fp->m_func->filename()->data();
        Offset off = pc;

        ArrayInit frame(btArgs.m_parserFrame ? 4 : 2, ArrayInit::Map{});
        frame.set(s_file, filename);
        frame.set(s_line, unit->getLineNumber(off));
        if (btArgs.m_parserFrame) {
          frame.set(s_function, s_include);
          frame.set(s_args, Array::Create(btArgs.m_parserFrame->filename));
        }
        bt.append(frame.toVariant());
        depth++;
      }
    }
  }
  // Handle the subsequent VM frames
  Offset prevPc = 0;
  for (ActRec* prevFp = g_context->getPrevVMState(fp, &prevPc);
       fp != nullptr && (btArgs.m_limit == 0 || depth < btArgs.m_limit);
       fp = prevFp, pc = prevPc,
         prevFp = g_context->getPrevVMState(fp, &prevPc)) {
    // do not capture frame for HPHP only functions
    if (fp->m_func->isNoInjection()) {
      continue;
    }

    ArrayInit frame(7, ArrayInit::Map{});

    auto const curUnit = fp->m_func->unit();
    auto const curOp = *reinterpret_cast<const Op*>(curUnit->at(pc));
    auto const isReturning =
      curOp == Op::RetC || curOp == Op::RetV ||
      curOp == Op::CreateCont || curOp == Op::Await ||
      fp->localsDecRefd();

    // Builtins and generators don't have a file and line number
    if (prevFp && !prevFp->m_func->isBuiltin() && !fp->resumed()) {
      auto const prevUnit = prevFp->m_func->unit();
      auto prevFile = prevUnit->filepath();
      if (prevFp->m_func->originalFilename()) {
        prevFile = prevFp->m_func->originalFilename();
      }
      assert(prevFile);
      frame.set(s_file, const_cast<StringData*>(prevFile));

      // In the normal method case, the "saved pc" for line number printing is
      // pointing at the cell conversion (Unbox/Pop) instruction, not the call
      // itself. For multi-line calls, this instruction is associated with the
      // subsequent line which results in an off-by-n. We're subtracting one
      // in order to look up the line associated with the FCall/FCallArray
      // instruction. Exception handling and the other opcodes (ex. BoxR)
      // already do the right thing. The emitter associates object access with
      // the subsequent expression and this would be difficult to modify.
      auto const opAtPrevPc =
        *reinterpret_cast<const Op*>(prevUnit->at(prevPc));
      Offset pcAdjust = 0;
      if (opAtPrevPc == OpPopR || opAtPrevPc == OpUnboxR) {
        pcAdjust = 1;
      }
      frame.set(s_line,
                prevFp->m_func->unit()->getLineNumber(prevPc - pcAdjust));
    }

    // check for include
    String funcname = const_cast<StringData*>(fp->m_func->name());
    if (fp->m_func->isClosureBody()) {
      static StringData* s_closure_label =
        makeStaticString("{closure}");
      funcname = s_closure_label;
    }

    // check for pseudomain
    if (funcname.empty()) {
      if (!prevFp) continue;
      funcname = s_include;
    }

    frame.set(s_function, funcname);

    if (!funcname.same(s_include)) {
      // Closures have an m_this but they aren't in object context
      Class* ctx = arGetContextClass(fp);
      if (ctx != nullptr && !fp->m_func->isClosureBody()) {
        frame.set(s_class, ctx->name()->data());
        if (fp->hasThis() && !isReturning) {
          if (btArgs.m_withThis) {
            frame.set(s_object, Object(fp->getThis()));
          }
          frame.set(s_type, "->");
        } else {
          frame.set(s_type, "::");
        }
      }
    }

    Array args = Array::Create();
    if (btArgs.m_ignoreArgs) {
      // do nothing
    } else if (funcname.same(s_include)) {
      if (depth) {
        args.append(const_cast<StringData*>(curUnit->filepath()));
        frame.set(s_args, args);
      }
    } else if (!RuntimeOption::EnableArgsInBacktraces || isReturning) {
      // Provide an empty 'args' array to be consistent with hphpc
      frame.set(s_args, args);
    } else {
      const int nparams = fp->m_func->numNonVariadicParams();
      int nargs = fp->numArgs();
      int nformals = std::min(nparams, nargs);

      if (UNLIKELY(fp->hasVarEnv() && fp->getVarEnv()->getFP() != fp)) {
        // VarEnv is attached to eval or debugger frame, other than the current
        // frame. Access locals thru VarEnv.
        auto varEnv = fp->getVarEnv();
        auto func = fp->func();
        for (int i = 0; i < nformals; i++) {
          TypedValue *arg = varEnv->lookup(func->localVarName(i));
          args.append(tvAsVariant(arg));
        }
      } else {
        for (int i = 0; i < nformals; i++) {
          TypedValue *arg = frame_local(fp, i);
          args.append(tvAsVariant(arg));
        }
      }

      /* builtin extra args are not stored in varenv */
      if (nargs > nparams && fp->hasExtraArgs()) {
        for (int i = nparams; i < nargs; i++) {
          TypedValue *arg = fp->getExtraArg(i - nparams);
          args.append(tvAsVariant(arg));
        }
      }
      frame.set(s_args, args);
    }

    bt.append(frame.toVariant());
    depth++;
  }
  return bt;

}
Ejemplo n.º 28
0
void SourceFile::parse()
{
    bool any = false;
    Parser p( contents() );
    p.scan( "/*" "!" );
    while ( !p.atEnd() ) {
        any = true;
        p.whitespace();
        Function * f = 0;
        Class * c = 0;
        Intro * i = 0;
        EString d;
        uint l = p.line();
        if ( p.lookingAt( "\\fn " ) ) {
            p.scan( " " );
            f = function( &p );
            d = p.textUntil( "*/" );
        }
        else if ( p.lookingAt( "\\chapter " ) ) {
            p.scan( " " );
            EString name = p.word();
            if ( name.isEmpty() )
                (void)new Error( this, p.line(),
                                 "\\chapter must be followed by name" );
            i = new Intro( name );
            p.whitespace();
            d = p.textUntil( "*/" );
        }
        else if ( p.lookingAt( "\\class " ) ) {
            p.scan( " " );
            EString className = p.identifier();
            if ( className.isEmpty() ) {
                (void)new Error( this, l,
                                 "\\class must be followed by a class name" );
            }
            c = Class::find( className );
            if ( !c )
                c = new Class( className, 0, 0 );
            p.whitespace();
            EString hn = p.word();
            while ( p.lookingAt( "." ) ) {
                p.step();
                hn.append( "." );
                hn.append( p.word() );
            }
            if ( hn.length() < 2 || hn.mid( hn.length() - 2) != ".h" ) {
                (void)new Error( this, l,
                                 "Missing header file name" );
            }
            else {
                if ( !contents().contains( "\n#include \"" + hn + "\"" ) &&
                        !contents().contains( "\n#include <" + hn + ">" ) )
                    (void)new Error( this, l,
                                     "File does not include " + hn );
                HeaderFile * h = HeaderFile::find( hn );
                if ( !h ) {
                    if ( name().contains( "/" ) ) {
                        EString dir = name();
                        uint i = dir.length()-1;
                        while ( i > 0 && dir[i] != '/' )
                            i--;
                        hn = dir.mid( 0, i+1 ) + hn;
                    }
                    h = new HeaderFile( hn );
                    if ( !h->valid() )
                        (void)new Error( this, l,
                                         "Cannot find header file " + hn +
                                         " (for class " + className + ")" );
                }
                if ( !c->members() || c->members()->isEmpty() )
                    (void)new Error( this, l,
                                     "Cannot find any " + className +
                                     " members in " + hn );
            }
            d = p.textUntil( "*/" );
        }
        else if ( p.lookingAt( "\\nodoc" ) ) {
            any = true;
            d = "hack";
        }
        else {
            d = p.textUntil( "*/" );
            f = function( &p );
        }
        if ( d.isEmpty() )
            (void)new Error( this, l, "Comment contains no documentation" );
        else if ( f )
            (void)new DocBlock( this, l, d, f );
        else if ( c )
            (void)new DocBlock( this, l, d, c );
        else if ( i )
            (void)new DocBlock( this, l, d, i );
        p.scan( "/" /* udoc must not see that as one string */ "*!" );
    }
    if ( !any ) {
        Parser p( contents() );
        p.scan( "::" ); // any source in this file at all?
        if ( !p.atEnd() )
            (void)new Error( this, p.line(),
                             "File contains no documentation" );
    }
}
Ejemplo n.º 29
0
void PRMDisplay::RBNToGraph(const double attributeWeight, const double FKWeight) {
	Class aClass;
	VertexDescriptor vd;
	std::map<std::string, VertexDescriptor> container;
	positionMap = boost::get(&VertexProperties::point, graph);
	vertexIdPropertyMap = boost::get(&VertexProperties::index, graph);
	WeightPropertyMap weightPropertyMap = boost::get(&EdgeProperty::weight, graph);
	RelationalSchema schema = rbn->getSchema();
	std::vector<std::string> classnames = schema.getClassNames();
	for(std::vector<std::string>::iterator it = classnames.begin(); it != classnames.end(); ++it)
	{
		std::string classname = *it;

		aClass = schema.getClass(classname);
		std::vector<std::string> attributesName = aClass.getAttributeNames();
		//std::vector<std::string>::iterator it2 = attributesName.begin();

		//pour chaque attribut, ajout d'un nouveau sommet aux coordonnée (1,1)
		for(std::vector<std::string>::iterator it1 = attributesName.begin(); it1!=attributesName.end(); it1++)
		{
			std::stringstream ss;
			ss << classname << "." << *it1;

			vd = boost::add_vertex(graph);

			vertexIdPropertyMap[vd] = ss.str();
			container[ss.str()] = vd;
			positionMap[vd][0]=1;
			positionMap[vd][1]=1;
			// si l'itérateur est différent de begin, alors on itere pour ajouter une arête jusqu'à l'itérateur it1 actuel
			if(attributesName.begin() != it1)
			{
				//Ajout d'arête entre le nouveau sommet et ceux du graphe qui appartiennent à la même classe. Le poid est de 2
				for(std::vector<std::string>::iterator it3 = attributesName.begin(); it3 != it1; it3++)
				{
					std::stringstream ss2;
					ss2 << classname << "." << *it3;
					boost::add_edge(container[ss.str()], container[ss2.str()], EdgeProperty(attributeWeight), graph);
				}
			}
		} 
	}
	
	/***** ajout d'arête pour chaque clé étrangère ****/
	RefSlotsMultimap foreignKeys = schema.getRefSlots();
	std::string attPK;
	std::string classPK;
	std::string classFK;
	for(RefSlotsMultimap::iterator rb = foreignKeys.begin(); rb != foreignKeys.end(); ++rb){
		classPK=rb->second.second->getName().c_str();
		attPK= rbn->getSchema().getClass(classPK).getPK().front();
		classPK.append(".");
		classPK.append(attPK);
		//std::cout << "\t primaryKey "<<classPK;
		classFK=rb->first.c_str();;
		classFK.append(".");
		classFK.append(rb->second.first.getName());
		//std::cout << "\t foriegnKey "<<classFK;
		boost::add_edge(container[classFK], container[classPK], EdgeProperty(FKWeight), graph);
	}
}
Ejemplo n.º 30
0
void Variant::unserialize(VariableUnserializer *uns,
                          Uns::Mode mode /* = Uns::Mode::Value */) {

    // NOTE: If you make changes to how serialization and unserialization work,
    // make sure to update the reserialize() method in "runtime/ext/ext_apc.cpp"
    // and to update test_apc_reserialize() in "test/ext/test_ext_apc.cpp".

    char type, sep;
    type = uns->readChar();
    sep = uns->readChar();

    if (type != 'R') {
        uns->add(this, mode);
    }

    if (type == 'N') {
        if (sep != ';') throw Exception("Expected ';' but got '%c'", sep);
        setNull(); // NULL *IS* the value, without we get undefined warnings
        return;
    }
    if (sep != ':') {
        throw Exception("Expected ':' but got '%c'", sep);
    }

    switch (type) {
    case 'r':
    {
        int64_t id = uns->readInt();
        Variant *v = uns->getByVal(id);
        if (v == nullptr) {
            throw Exception("Id %" PRId64 " out of range", id);
        }
        operator=(*v);
    }
    break;
    case 'R':
    {
        int64_t id = uns->readInt();
        Variant *v = uns->getByRef(id);
        if (v == nullptr) {
            throw Exception("Id %" PRId64 " out of range", id);
        }
        assignRef(*v);
    }
    break;
    case 'b': {
        int64_t v = uns->readInt();
        operator=((bool)v);
    }
    break;
    case 'i': {
        int64_t v = uns->readInt();
        operator=(v);
    }
    break;
    case 'd':
    {
        double v;
        char ch = uns->peek();
        bool negative = false;
        char buf[4];
        if (ch == '-') {
            negative = true;
            ch = uns->readChar();
            ch = uns->peek();
        }
        if (ch == 'I') {
            uns->read(buf, 3);
            buf[3] = '\0';
            if (strcmp(buf, "INF")) {
                throw Exception("Expected 'INF' but got '%s'", buf);
            }
            v = atof("inf");
        } else if (ch == 'N') {
            uns->read(buf, 3);
            buf[3] = '\0';
            if (strcmp(buf, "NAN")) {
                throw Exception("Expected 'NAN' but got '%s'", buf);
            }
            v = atof("nan");
        } else {
            v = uns->readDouble();
        }
        operator=(negative ? -v : v);
    }
    break;
    case 's':
    {
        String v;
        v.unserialize(uns);
        operator=(v);
    }
    break;
    case 'S':
        if (uns->getType() == VariableUnserializer::Type::APCSerialize) {
            union {
                char buf[8];
                StringData *sd;
            } u;
            uns->read(u.buf, 8);
            operator=(u.sd);
        } else {
            throw Exception("Unknown type '%c'", type);
        }
        break;
    case 'a':
    {
        Array v = Array::Create();
        v.unserialize(uns);
        operator=(v);
        return; // array has '}' terminating
    }
    break;
    case 'L':
    {
        int64_t id = uns->readInt();
        sep = uns->readChar();
        if (sep != ':') {
            throw Exception("Expected ':' but got '%c'", sep);
        }
        String rsrcName;
        rsrcName.unserialize(uns);
        sep = uns->readChar();
        if (sep != '{') {
            throw Exception("Expected '{' but got '%c'", sep);
        }
        sep = uns->readChar();
        if (sep != '}') {
            throw Exception("Expected '}' but got '%c'", sep);
        }
        DummyResource* rsrc = NEWOBJ(DummyResource);
        rsrc->o_setResourceId(id);
        rsrc->m_class_name = rsrcName;
        operator=(rsrc);
        return; // resource has '}' terminating
    }
    break;
    case 'O':
    case 'V':
    case 'K':
    {
        String clsName;
        clsName.unserialize(uns);

        sep = uns->readChar();
        if (sep != ':') {
            throw Exception("Expected ':' but got '%c'", sep);
        }
        int64_t size = uns->readInt();
        char sep = uns->readChar();
        if (sep != ':') {
            throw Exception("Expected ':' but got '%c'", sep);
        }
        sep = uns->readChar();
        if (sep != '{') {
            throw Exception("Expected '{' but got '%c'", sep);
        }

        const bool allowObjectFormatForCollections = true;

        Class* cls;
        // If we are potentially dealing with a collection, we need to try to
        // load the collection class under an alternate name so that we can
        // deserialize data that was serialized before the migration of
        // collections to the HH namespace.

        if (type != 'O') {
            // Collections are CPP builtins; don't attempt to autoload
            cls = Unit::getClass(clsName.get(), /* autoload */ false);
            if (!cls) {
                cls = tryAlternateCollectionClass(clsName.get());
            }
        } else if (allowObjectFormatForCollections) {
            // In order to support the legacy {O|V}:{Set|Vector|Map}
            // serialization, we defer autoloading until we know that there's
            // no alternate (builtin) collection class.
            cls = Unit::getClass(clsName.get(), /* autoload */ false);
            if (!cls) {
                cls = tryAlternateCollectionClass(clsName.get());
            }
            if (!cls) {
                cls = Unit::loadClass(clsName.get()); // with autoloading
            }
        } else {
            cls = Unit::loadClass(clsName.get()); // with autoloading
        }

        Object obj;
        if (RuntimeOption::UnserializationWhitelistCheck &&
                (type == 'O') &&
                !uns->isWhitelistedClass(clsName)) {
            const char* err_msg =
                "The object being unserialized with class name '%s' "
                "is not in the given whitelist. "
                "See http://fburl.com/SafeSerializable for more detail";
            if (RuntimeOption::UnserializationWhitelistCheckWarningOnly) {
                raise_warning(err_msg, clsName.c_str());
            } else {
                raise_error(err_msg, clsName.c_str());
            }
        }
        if (cls) {
            // Only unserialize CPP extension types which can actually
            // support it. Otherwise, we risk creating a CPP object
            // without having it initialized completely.
            if (cls->instanceCtor() && !cls->isCppSerializable()) {
                assert(obj.isNull());
            } else {
                obj = ObjectData::newInstance(cls);
                if (UNLIKELY(cls == c_Pair::classof() && size != 2)) {
                    throw Exception("Pair objects must have exactly 2 elements");
                }
            }
        } else {
            obj = ObjectData::newInstance(
                      SystemLib::s___PHP_Incomplete_ClassClass);
            obj->o_set(s_PHP_Incomplete_Class_Name, clsName);
        }
        operator=(obj);

        if (size > 0) {
            if (type == 'O') {
                // Collections are not allowed
                if (obj->isCollection()) {
                    if (size > 0) {
                        throw Exception("%s does not support the 'O' serialization "
                                        "format", clsName.data());
                    }
                    // Be lax and tolerate the 'O' serialization format for collection
                    // classes if there are 0 properties.
                    raise_warning("%s does not support the 'O' serialization "
                                  "format", clsName.data());
                }
                /*
                  Count backwards so that i is the number of properties
                  remaining (to be used as an estimate for the total number
                  of dynamic properties when we see the first dynamic prop).
                  see getVariantPtr
                */
                for (int64_t i = size; i--; ) {
                    String key = uns->unserializeKey().toString();
                    int ksize = key.size();
                    const char *kdata = key.data();
                    int subLen = 0;
                    if (kdata[0] == '\0') {
                        if (UNLIKELY(!ksize)) {
                            throw EmptyObjectPropertyException();
                        }
                        // private or protected
                        subLen = strlen(kdata + 1) + 2;
                        if (UNLIKELY(subLen >= ksize)) {
                            if (subLen == ksize) {
                                throw EmptyObjectPropertyException();
                            } else {
                                throw Exception("Mangled private object property");
                            }
                        }
                        String k(kdata + subLen, ksize - subLen, CopyString);
                        Class* ctx = (Class*)-1;
                        if (kdata[1] != '*') {
                            ctx = Unit::lookupClass(
                                      String(kdata + 1, subLen - 2, CopyString).get());
                        }
                        unserializeProp(uns, obj.get(), k, ctx, key, i + 1);
                    } else {
                        unserializeProp(uns, obj.get(), key, nullptr, key, i + 1);
                    }
                }
            } else {
                assert(type == 'V' || type == 'K');
                if (!obj->isCollection()) {
                    throw Exception("%s is not a collection class", clsName.data());
                }
                collectionUnserialize(obj.get(), uns, size, type);
            }
        }
        sep = uns->readChar();
        if (sep != '}') {
            throw Exception("Expected '}' but got '%c'", sep);
        }

        obj->invokeWakeup();
        return; // object has '}' terminating
    }
    break;
    case 'C':
    {
        String clsName;
        clsName.unserialize(uns);

        sep = uns->readChar();
        if (sep != ':') {
            throw Exception("Expected ':' but got '%c'", sep);
        }
        String serialized;
        serialized.unserialize(uns, '{', '}');

        Object obj;
        try {
            obj = create_object_only(clsName);
        } catch (ClassNotFoundException &e) {
            if (!uns->allowUnknownSerializableClass()) {
                throw;
            }
            obj = create_object_only(s_PHP_Incomplete_Class);
            obj->o_set(s_PHP_Incomplete_Class_Name, clsName);
            obj->o_set("serialized", serialized);
        }

        if (!obj->instanceof(SystemLib::s_SerializableClass)) {
            raise_warning("Class %s has no unserializer",
                          obj->o_getClassName().data());
        } else {
            obj->o_invoke_few_args(s_unserialize, 1, serialized);
            obj.get()->clearNoDestruct();
        }

        operator=(obj);
        return; // object has '}' terminating
    }
    break;
    default:
        throw Exception("Unknown type '%c'", type);
    }
    sep = uns->readChar();
    if (sep != ';') {
        throw Exception("Expected ';' but got '%c'", sep);
    }
}