+static NSArray *Bridge_;
+
+struct CYData {
+ apr_pool_t *pool_;
+
+ virtual ~CYData() {
+ }
+
+ void *operator new(size_t size) {
+ apr_pool_t *pool;
+ apr_pool_create(&pool, NULL);
+ void *data(apr_palloc(pool, size));
+ reinterpret_cast<CYData *>(data)->pool_ = pool;
+ return data;;
+ }
+
+ static void Finalize(JSObjectRef object) {
+ CYData *data(reinterpret_cast<CYData *>(JSObjectGetPrivate(object)));
+ data->~CYData();
+ apr_pool_destroy(data->pool_);
+ }
+};
+
+struct Pointer_privateData :
+ CYData
+{
+ void *value_;
+ sig::Type type_;
+
+ Pointer_privateData() {
+ }
+
+ Pointer_privateData(void *value) :
+ value_(value)
+ {
+ }
+};
+
+struct Selector_privateData : Pointer_privateData {
+ Selector_privateData(SEL value) :
+ Pointer_privateData(value)
+ {
+ }
+
+ SEL GetValue() const {
+ return reinterpret_cast<SEL>(value_);
+ }
+};
+
+struct Instance_privateData :
+ Pointer_privateData
+{
+ bool transient_;
+
+ Instance_privateData(id value, bool transient) :
+ Pointer_privateData(value)
+ {
+ }
+
+ virtual ~Instance_privateData() {
+ if (!transient_)
+ [GetValue() release];
+ }
+
+ id GetValue() const {
+ return reinterpret_cast<id>(value_);
+ }
+};
+
+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;
+ }
+};
+
+struct Type_privateData {
+ sig::Type type_;
+ ffi_type ffi_;
+
+ Type_privateData(apr_pool_t *pool, sig::Type *type, ffi_type *ffi) {
+ sig::Copy(pool, type_, *type);
+ sig::Copy(pool, ffi_, *ffi);
+ }
+};
+
+struct Struct_privateData :
+ Pointer_privateData
+{
+ JSObjectRef owner_;
+ Type_privateData *type_;
+
+ Struct_privateData() {
+ }
+};
+
+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());
+ apr_pool_t *pool(internal->pool_);
+ Type_privateData *typical(new(pool) Type_privateData(pool, type, ffi));
+ internal->type_ = typical;
+
+ if (owner != NULL) {
+ internal->owner_ = owner;
+ internal->value_ = data;
+ } else {
+ internal->owner_ = NULL;
+
+ size_t size(typical->ffi_.size);
+ void *copy(apr_palloc(internal->pool_, size));
+ memcpy(copy, data, size);
+ internal->value_ = copy;
+ }
+
+ return JSObjectMake(context, Struct_, internal);
+}
+
+void Structor_(apr_pool_t *pool, const char *name, const char *types, sig::Type *type) {
+ CYPoolTry {
+ if (NSMutableArray *entry = [[Bridge_ objectAtIndex:2] objectForKey:[NSString stringWithUTF8String:name]]) {
+ switch ([[entry objectAtIndex:0] intValue]) {
+ case 0:
+ static CYPool Pool_;
+ sig::Parse(Pool_, &type->data.signature, [[entry objectAtIndex:1] UTF8String], &Structor_);
+ break;
+ }
+ }
+ } CYPoolCatch()
+}
+
+struct Functor_privateData :
+ Pointer_privateData
+{
+ sig::Signature signature_;
+ ffi_cif cif_;
+
+ Functor_privateData(const char *type, void (*value)()) :
+ Pointer_privateData(reinterpret_cast<void *>(value))
+ {
+ sig::Parse(pool_, &signature_, type, &Structor_);
+ sig::sig_ffi_cif(pool_, &sig::ObjectiveC, &signature_, &cif_);
+ }
+};