+
+ bool IsUninitialized() const {
+ return (flags_ & Uninitialized) != 0;
+ }
+};
+
+namespace sig {
+
+void Copy(apr_pool_t *pool, Type &lhs, Type &rhs);
+
+void Copy(apr_pool_t *pool, Element &lhs, Element &rhs) {
+ lhs.name = apr_pstrdup(pool, rhs.name);
+ if (rhs.type == NULL)
+ lhs.type = NULL;
+ else {
+ lhs.type = new(pool) Type;
+ Copy(pool, *lhs.type, *rhs.type);
+ }
+ lhs.offset = rhs.offset;
+}
+
+void Copy(apr_pool_t *pool, Signature &lhs, Signature &rhs) {
+ size_t count(rhs.count);
+ lhs.count = count;
+ lhs.elements = new(pool) Element[count];
+ for (size_t index(0); index != count; ++index)
+ Copy(pool, lhs.elements[index], rhs.elements[index]);
+}
+
+void Copy(apr_pool_t *pool, Type &lhs, Type &rhs) {
+ lhs.primitive = rhs.primitive;
+ lhs.name = apr_pstrdup(pool, rhs.name);
+ lhs.flags = rhs.flags;
+
+ if (sig::IsAggregate(rhs.primitive))
+ Copy(pool, lhs.data.signature, rhs.data.signature);
+ else {
+ if (rhs.data.data.type != NULL) {
+ lhs.data.data.type = new(pool) Type;
+ Copy(pool, *lhs.data.data.type, *rhs.data.data.type);
+ }
+
+ lhs.data.data.size = rhs.data.data.size;
+ }
+}
+
+void Copy(apr_pool_t *pool, ffi_type &lhs, ffi_type &rhs) {
+ lhs.size = rhs.size;
+ lhs.alignment = rhs.alignment;
+ lhs.type = rhs.type;
+ if (rhs.elements == NULL)
+ lhs.elements = NULL;
+ else {
+ size_t count(0);
+ while (rhs.elements[count] != NULL)
+ ++count;
+
+ lhs.elements = new(pool) ffi_type *[count + 1];
+ lhs.elements[count] = NULL;
+
+ for (size_t index(0); index != count; ++index) {
+ // XXX: if these are libffi native then you can just take them
+ ffi_type *ffi(new(pool) ffi_type);
+ lhs.elements[index] = ffi;
+ sig::Copy(pool, *ffi, *rhs.elements[index]);
+ }
+ }
+}
+
+}
+
+struct CStringMapLess :
+ std::binary_function<const char *, const char *, bool>
+{
+ _finline bool operator ()(const char *lhs, const char *rhs) const {
+ return strcmp(lhs, rhs) < 0;
+ }
+};
+
+void Structor_(apr_pool_t *pool, const char *name, const char *types, sig::Type *&type) {
+ if (name == NULL)
+ return;
+
+ CYPoolTry {
+ if (NSMutableArray *entry = [[Bridge_ objectAtIndex:2] objectForKey:[NSString stringWithUTF8String:name]])
+ switch ([[entry objectAtIndex:0] intValue]) {
+ case 0: {
+ sig::Parse(pool, &type->data.signature, [[entry objectAtIndex:1] UTF8String], &Structor_);
+ } break;
+
+ case 1: {
+ sig::Signature signature;
+ sig::Parse(pool, &signature, [[entry objectAtIndex:1] UTF8String], &Structor_);
+ type = signature.elements[0].type;
+ } break;
+ }
+ } CYPoolCatch()
+}
+
+struct Type_privateData :
+ CYData
+{
+ ffi_type *ffi_;
+ sig::Type *type_;
+
+ void Set(sig::Type *type) {
+ type_ = new(pool_) sig::Type;
+ sig::Copy(pool_, *type_, *type);
+ }
+
+ Type_privateData(const char *type) :
+ ffi_(NULL)
+ {
+ sig::Signature signature;
+ sig::Parse(pool_, &signature, type, &Structor_);
+ type_ = signature.elements[0].type;
+ }
+
+ Type_privateData(sig::Type *type) :
+ ffi_(NULL)
+ {
+ if (type != NULL)
+ Set(type);
+ }
+
+ Type_privateData(sig::Type *type, ffi_type *ffi) {
+ ffi_ = new(pool_) ffi_type;
+ sig::Copy(pool_, *ffi_, *ffi);
+ Set(type);
+ }
+
+ ffi_type *GetFFI() {
+ if (ffi_ == NULL) {
+ ffi_ = new(pool_) ffi_type;
+
+ sig::Element element;
+ element.name = NULL;
+ element.type = type_;
+ element.offset = 0;
+
+ sig::Signature signature;
+ signature.elements = &element;
+ signature.count = 1;
+
+ ffi_cif cif;
+ sig::sig_ffi_cif(pool_, &sig::ObjectiveC, &signature, &cif);
+ *ffi_ = *cif.rtype;
+ }
+
+ return ffi_;
+ }
+};
+
+struct Pointer :
+ CYValue
+{
+ JSObjectRef owner_;
+ Type_privateData *type_;
+
+ Pointer(void *value, sig::Type *type, JSObjectRef owner) :
+ CYValue(value),
+ owner_(owner),
+ type_(new(pool_) Type_privateData(type))
+ {
+ }
+};
+
+struct Struct_privateData :
+ CYValue
+{
+ JSObjectRef owner_;
+ Type_privateData *type_;
+
+ Struct_privateData(JSObjectRef owner) :
+ owner_(owner)
+ {
+ }
+};
+
+typedef std::map<const char *, Type_privateData *, CStringMapLess> TypeMap;
+static TypeMap Types_;
+
+JSObjectRef CYMakeStruct(JSContextRef context, void *data, sig::Type *type, ffi_type *ffi, JSObjectRef owner) {
+ Struct_privateData *internal(new Struct_privateData(owner));
+ apr_pool_t *pool(internal->pool_);
+ Type_privateData *typical(new(pool) Type_privateData(type, ffi));
+ internal->type_ = typical;
+
+ if (owner != NULL)
+ internal->value_ = data;
+ else {
+ size_t size(typical->GetFFI()->size);
+ void *copy(apr_palloc(internal->pool_, size));
+ memcpy(copy, data, size);
+ internal->value_ = copy;
+ }
+
+ return JSObjectMake(context, Struct_, internal);
+}
+
+struct Functor_privateData :
+ CYValue
+{
+ sig::Signature signature_;
+ ffi_cif cif_;
+
+ Functor_privateData(const char *type, void (*value)()) :
+ CYValue(reinterpret_cast<void *>(value))
+ {
+ sig::Parse(pool_, &signature_, type, &Structor_);
+ sig::sig_ffi_cif(pool_, &sig::ObjectiveC, &signature_, &cif_);
+ }
+};
+
+struct ffoData :
+ Functor_privateData
+{
+ JSContextRef context_;
+ JSObjectRef function_;
+
+ ffoData(const char *type) :
+ Functor_privateData(type, NULL)
+ {
+ }