#include "Pooling.hpp"
#include "String.hpp"
+const char *sqlite3_column_string(sqlite3_stmt *stmt, int n) {
+ return reinterpret_cast<const char *>(sqlite3_column_text(stmt, n));
+}
+
char *sqlite3_column_pooled(CYPool &pool, sqlite3_stmt *stmt, int n) {
- if (const unsigned char *value = sqlite3_column_text(stmt, n))
- return pool.strdup(reinterpret_cast<const char *>(value));
+ if (const char *value = sqlite3_column_string(stmt, n))
+ return pool.strdup(value);
else return NULL;
}
}
/* }}} */
+static JSObjectRef (*JSObjectMakeArray$)(JSContextRef, size_t, const JSValueRef[], JSValueRef *);
+
+static JSObjectRef CYObjectMakeArray(JSContextRef context, size_t length, const JSValueRef values[]) {
+ if (JSObjectMakeArray$ != NULL)
+ return _jsccall(*JSObjectMakeArray$, context, length, values);
+ else {
+ JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array")));
+ JSValueRef value(CYCallAsFunction(context, Array, NULL, length, values));
+ return CYCastJSObject(context, value);
+ }
+}
+
static JSClassRef All_;
static JSClassRef Context_;
static JSClassRef CString_;
return _jsccall(JSObjectGetPropertyAtIndex, context, array, index);
}
-void CYArrayPush(JSContextRef context, JSObjectRef array, JSValueRef value) {
- JSValueRef arguments[1];
- arguments[0] = value;
+void CYArrayPush(JSContextRef context, JSObjectRef array, size_t length, const JSValueRef arguments[]) {
JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype")));
- _jsccall(JSObjectCallAsFunction, context, CYCastJSObject(context, CYGetProperty(context, Array, push_s)), array, 1, arguments);
+ _jsccall(JSObjectCallAsFunction, context, CYCastJSObject(context, CYGetProperty(context, Array, push_s)), array, length, arguments);
}
+void CYArrayPush(JSContextRef context, JSObjectRef array, JSValueRef value) {
+ return CYArrayPush(context, array, 1, &value);
+}
+
+template <size_t Size_>
+class CYArrayBuilder {
+ private:
+ JSContextRef context_;
+ JSObjectRef &array_;
+ size_t size_;
+ JSValueRef values_[Size_];
+
+ void flush() {
+ if (array_ == NULL)
+ array_ = CYObjectMakeArray(context_, size_, values_);
+ else
+ CYArrayPush(context_, array_, size_, values_);
+ }
+
+ public:
+ CYArrayBuilder(JSContextRef context, JSObjectRef &array) :
+ context_(context),
+ array_(array),
+ size_(0)
+ {
+ }
+
+ ~CYArrayBuilder() {
+ flush();
+ }
+
+ void operator ()(JSValueRef value) {
+ if (size_ == Size_) {
+ flush();
+ size_ = 0;
+ }
+
+ values_[size_++] = value;
+ }
+};
+
static JSValueRef System_print(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
FILE *file(stdout);
break;
CYPoolFFI_(uchar, unsigned char)
- CYPoolFFI_(char, char)
+ CYPoolFFI_(schar, signed char)
CYPoolFFI_(ushort, unsigned short)
CYPoolFFI_(short, short)
CYPoolFFI_(ulong, unsigned long)
case sig::void_P:
break;
+ // XXX: implement a conversion from a single character string?
+ CYPoolFFI_(char, char)
+
default:
for (CYHook *hook : GetHooks())
if (hook->PoolFFI != NULL)
return CYCastJSValue(context, *reinterpret_cast<native *>(data)); \
CYFromFFI_(uchar, unsigned char)
- CYFromFFI_(char, char)
+ CYFromFFI_(schar, signed char)
CYFromFFI_(ushort, unsigned short)
CYFromFFI_(short, short)
CYFromFFI_(ulong, unsigned long)
case sig::void_P:
return CYJSUndefined(context);
+ CYFromFFI_(char, char)
+
null:
return CYJSNull(context);
default:
return CYCallAsFunction(context, functor, _this, count, arguments);
} CYCatch(NULL) }
-JSObjectRef CYMakeType(JSContextRef context, const char *encoding) {
- Type_privateData *internal(new Type_privateData(encoding));
+JSObjectRef CYMakeType(JSContextRef context, sig::Primitive primitive) {
+ Type_privateData *internal(new Type_privateData(primitive));
return JSObjectMake(context, Type_privateData::Class_, internal);
}
return CYMakeType(context, &type);
}
-extern "C" const char *CYBridgeHash(CYPool &pool, CYUTF8String name) {
+extern "C" bool CYBridgeHash(CYPool &pool, CYUTF8String name, const char *&code, unsigned &flags) {
sqlite3_stmt *statement;
_sqlcall(sqlite3_prepare(database_,
"select "
- "\"cache\".\"value\" "
+ "\"cache\".\"code\", "
+ "\"cache\".\"flags\" "
"from \"cache\" "
"where"
" \"cache\".\"system\" & " CY_SYSTEM " == " CY_SYSTEM " and"
_sqlcall(sqlite3_bind_text(statement, 1, name.data, name.size, SQLITE_STATIC));
- const char *value;
+ bool success;
if (_sqlcall(sqlite3_step(statement)) == SQLITE_DONE)
- value = NULL;
- else
- value = sqlite3_column_pooled(pool, statement, 0);
+ success = false;
+ else {
+ success = true;
+ code = sqlite3_column_pooled(pool, statement, 0);
+ flags = sqlite3_column_int(statement, 1);
+ }
_sqlcall(sqlite3_finalize(statement));
- return value;
+ return success;
}
static bool All_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) {
+ if (JSStringIsEqualToUTF8CString(property, "errno"))
+ return true;
+
JSObjectRef global(CYGetGlobalObject(context));
JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript"))));
JSObjectRef alls(CYCastJSObject(context, CYGetProperty(context, cycript, CYJSString("alls"))));
return true;
CYPool pool;
- if (CYBridgeHash(pool, CYPoolUTF8String(pool, context, property)) != NULL)
+ const char *code;
+ unsigned flags;
+ if (CYBridgeHash(pool, CYPoolUTF8String(pool, context, property), code, flags))
return true;
return false;
}
static JSValueRef All_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+ if (JSStringIsEqualToUTF8CString(property, "errno"))
+ return CYCastJSValue(context, errno);
+
JSObjectRef global(CYGetGlobalObject(context));
JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript"))));
JSObjectRef alls(CYCastJSObject(context, CYGetProperty(context, cycript, CYJSString("alls"))));
return value;
CYPool pool;
- if (const char *code = CYBridgeHash(pool, CYPoolUTF8String(pool, context, property))) {
- JSValueRef result(_jsccall(JSEvaluateScript, context, CYJSString(CYPoolCode(pool, code)), NULL, NULL, 0));
- JSObjectRef cache(CYGetCachedObject(context, CYJSString("cache")));
- CYSetProperty(context, cache, property, result);
+ const char *code;
+ unsigned flags;
+ if (CYBridgeHash(pool, CYPoolUTF8String(pool, context, property), code, flags)) {
+ CYUTF8String parsed;
+
+ try {
+ parsed = CYPoolCode(pool, code);
+ } catch (const CYException &error) {
+ CYThrow("%s", pool.strcat("error caching ", CYPoolCString(pool, context, property), ": ", error.PoolCString(pool), NULL));
+ }
+
+ JSValueRef result(_jsccall(JSEvaluateScript, context, CYJSString(parsed), NULL, NULL, 0));
+
+ if (flags == 0) {
+ JSObjectRef cache(CYGetCachedObject(context, CYJSString("cache")));
+ CYSetProperty(context, cache, property, result);
+ }
+
return result;
}
return NULL;
} CYCatch(NULL) }
+static JSValueRef All_complete_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+ _assert(count == 1);
+ CYPool pool;
+ CYUTF8String prefix(CYPoolUTF8String(pool, context, CYJSString(context, arguments[0])));
+
+ JSObjectRef array(NULL);
+
+ {
+ CYArrayBuilder<1024> values(context, array);
+
+ sqlite3_stmt *statement;
+
+ if (prefix.size == 0)
+ _sqlcall(sqlite3_prepare(database_,
+ "select "
+ "\"cache\".\"name\" "
+ "from \"cache\" "
+ "where"
+ " \"cache\".\"system\" & " CY_SYSTEM " == " CY_SYSTEM
+ , -1, &statement, NULL));
+ else {
+ _sqlcall(sqlite3_prepare(database_,
+ "select "
+ "\"cache\".\"name\" "
+ "from \"cache\" "
+ "where"
+ " \"cache\".\"name\" >= ? and \"cache\".\"name\" < ? and "
+ " \"cache\".\"system\" & " CY_SYSTEM " == " CY_SYSTEM
+ , -1, &statement, NULL));
+
+ _sqlcall(sqlite3_bind_text(statement, 1, prefix.data, prefix.size, SQLITE_STATIC));
+
+ char *after(pool.strndup(prefix.data, prefix.size));
+ ++after[prefix.size - 1];
+ _sqlcall(sqlite3_bind_text(statement, 2, after, prefix.size, SQLITE_STATIC));
+ }
+
+ while (_sqlcall(sqlite3_step(statement)) != SQLITE_DONE)
+ values(CYCastJSValue(context, CYJSString(sqlite3_column_string(statement, 0))));
+
+ _sqlcall(sqlite3_finalize(statement));
+ }
+
+ return array;
+} CYCatch(NULL) }
+
static void All_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) {
JSObjectRef global(CYGetGlobalObject(context));
JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript"))));
if (false) {
} else if (count == 1) {
- const char *type(CYPoolCString(pool, context, arguments[0]));
- return CYMakeType(context, type);
+ const char *encoding(CYPoolCString(pool, context, arguments[0]));
+ sig::Signature signature;
+ sig::Parse(pool, &signature, encoding, &Structor_);
+ return CYMakeType(context, signature.elements[0].type);
} else if (count == 2) {
JSObjectRef types(CYCastJSObject(context, arguments[0]));
size_t count(CYArrayLength(context, types));
sig::Type type(*internal->type_);
switch (type.primitive) {
- case sig::char_P: case sig::uchar_P: type.primitive = sig::char_P; break;
+ case sig::char_P: case sig::schar_P: case sig::uchar_P: type.primitive = sig::schar_P; break;
case sig::short_P: case sig::ushort_P: type.primitive = sig::short_P; break;
case sig::int_P: case sig::uint_P: type.primitive = sig::int_P; break;
case sig::long_P: case sig::ulong_P: type.primitive = sig::long_P; break;
sig::Type type(*internal->type_);
switch (type.primitive) {
- case sig::char_P: case sig::uchar_P: type.primitive = sig::uchar_P; break;
+ case sig::char_P: case sig::schar_P: case sig::uchar_P: type.primitive = sig::uchar_P; break;
case sig::short_P: case sig::ushort_P: type.primitive = sig::ushort_P; break;
case sig::int_P: case sig::uint_P: type.primitive = sig::uint_P; break;
case sig::long_P: case sig::ulong_P: type.primitive = sig::ulong_P; break;
return Type_callAsFunction_toString(context, object, _this, count, arguments, exception);
}
+static JSStaticFunction All_staticFunctions[2] = {
+ {"cy$complete", &All_complete_callAsFunction, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+ {NULL, NULL, 0}
+};
+
static JSStaticFunction CString_staticFunctions[6] = {
{"toCYON", &CString_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"toJSON", &CYValue_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{NULL, NULL, 0}
};
-static JSObjectRef (*JSObjectMakeArray$)(JSContextRef, size_t, const JSValueRef[], JSValueRef *);
-
_visible void CYSetArgs(int argc, const char *argv[]) {
JSContextRef context(CYGetJSContext());
JSValueRef args[argc];
for (int i(0); i != argc; ++i)
args[i] = CYCastJSValue(context, argv[i]);
- JSObjectRef array;
- if (JSObjectMakeArray$ != NULL)
- array = _jsccall(*JSObjectMakeArray$, context, argc, args);
- else {
- JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array")));
- JSValueRef value(CYCallAsFunction(context, Array, NULL, argc, args));
- array = CYCastJSObject(context, value);
- }
-
+ JSObjectRef array(CYObjectMakeArray(context, argc, args));
JSObjectRef System(CYGetCachedObject(context, CYJSString("System")));
CYSetProperty(context, System, CYJSString("args"), array);
}
definition = kJSClassDefinitionEmpty;
definition.className = "All";
+ definition.staticFunctions = All_staticFunctions;
definition.hasProperty = &All_hasProperty;
definition.getProperty = &All_getProperty;
definition.getPropertyNames = &All_getPropertyNames;
_assert(slash != NULL);
*slash = '\0';
+ slash = strrchr(lib, '/');
+ if (slash != NULL && strcmp(slash, "/.libs") == 0)
+ *slash = '\0';
+
return lib;
}
static bool CYRunScript(JSGlobalContextRef context, const char *path) {
CYPool pool;
- CYUTF8String code(CYPoolFileUTF8String(pool, path));
+ CYUTF8String code(CYPoolFileUTF8String(pool, pool.strcat(CYPoolLibraryPath(pool), path, NULL)));
if (code.data == NULL)
return false;
JSObjectRef System(JSObjectMake(context, NULL, NULL));
CYSetProperty(context, cy, CYJSString("System"), System);
- CYSetProperty(context, all, CYJSString("require"), &require_callAsFunction, kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, global, CYJSString("require"), &require_callAsFunction, kJSPropertyAttributeDontEnum);
CYSetProperty(context, global, CYJSString("system"), System);
CYSetProperty(context, System, CYJSString("args"), CYJSNull(context));
CYSetProperty(context, cache, CYJSString("NULL"), CYJSNull(context), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, cache, CYJSString("bool"), CYMakeType(context, "B"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, cache, CYJSString("char"), CYMakeType(context, "c"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, cache, CYJSString("short"), CYMakeType(context, "s"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, cache, CYJSString("int"), CYMakeType(context, "i"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, cache, CYJSString("long"), CYMakeType(context, "l"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, cache, CYJSString("float"), CYMakeType(context, "f"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, cache, CYJSString("double"), CYMakeType(context, "d"), kJSPropertyAttributeDontEnum);
-
- CYRunScript(context, "libcycript.cy");
+ CYSetProperty(context, cache, CYJSString("bool"), CYMakeType(context, sig::boolean_P), kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, cache, CYJSString("char"), CYMakeType(context, sig::char_P), kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, cache, CYJSString("short"), CYMakeType(context, sig::short_P), kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, cache, CYJSString("int"), CYMakeType(context, sig::int_P), kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, cache, CYJSString("long"), CYMakeType(context, sig::long_P), kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, cache, CYJSString("float"), CYMakeType(context, sig::float_P), kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, cache, CYJSString("double"), CYMakeType(context, sig::double_P), kJSPropertyAttributeDontEnum);
for (CYHook *hook : GetHooks())
if (hook->SetupContext != NULL)
(*hook->SetupContext)(context);
CYArrayPush(context, alls, cycript);
+
+ CYRunScript(context, "/libcycript.cy");
}
static JSGlobalContextRef context_;