#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 true;
} CYCatch(false) }
-template <typename Type_>
-static void Align(Type_ &data, size_t size) {
- data = reinterpret_cast<Type_>((reinterpret_cast<uintptr_t>(data) + (size - 1)) & ~(size - 1));
-}
-
static bool Index_(CYPool &pool, JSContextRef context, Struct_privateData *internal, JSStringRef property, ssize_t &index, uint8_t *&base) {
Type_privateData *typical(internal->type_);
sig::Type *type(typical->type_);
base:
ffi_type **elements(typical->GetFFI()->elements);
- base = reinterpret_cast<uint8_t *>(internal->value_);
+ size_t offset(0);
for (ssize_t local(0); local != index; ++local) {
- Align(base, elements[local]->alignment);
- base += elements[local]->size;
+ offset += elements[local]->size;
+ CYAlign(offset, elements[local + 1]->alignment);
}
- Align(base, elements[index]->alignment);
+ base = reinterpret_cast<uint8_t *>(internal->value_) + offset;
return true;
}
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));
- CYSetProperty(context, object, property, result, kJSPropertyAttributeDontEnum);
+ 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])));
+
+ std::vector<JSValueRef> values;
+
+ 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.push_back(CYCastJSValue(context, CYJSString(sqlite3_column_string(statement, 0))));
+
+ _sqlcall(sqlite3_finalize(statement));
+
+ return CYObjectMakeArray(context, values.size(), values.data());
+} 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"))));
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;
return reinterpret_cast<Context *>(JSObjectGetPrivate(CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s))))->context_;
}
-struct CYFile {
- void *data_;
- size_t size_;
-
- CYFile(void *data, size_t size) :
- data_(data),
- size_(size)
- {
- }
-};
-
-static void CYFileExit(void *data) {
- CYFile *file(reinterpret_cast<CYFile *>(data));
- _syscall(munmap(file->data_, file->size_));
-}
-
-static void *CYPoolFile(CYPool &pool, const char *path, size_t *psize) {
- int fd(_syscall_(open(path, O_RDONLY), 1, ENOENT));
- if (fd == -1)
- return NULL;
-
- struct stat stat;
- _syscall(fstat(fd, &stat));
- size_t size(stat.st_size);
-
- *psize = size;
-
- void *base;
- if (size == 0)
- base = pool.strndup("", 0);
- else {
- _syscall(base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0));
-
- CYFile *file(new (pool) CYFile(base, size));
- pool.atexit(&CYFileExit, file);
- }
-
- _syscall(close(fd));
- return base;
-}
-
-static CYUTF8String CYPoolFileUTF8String(CYPool &pool, const char *path) {
- CYUTF8String data;
- data.data = reinterpret_cast<char *>(CYPoolFile(pool, path, &data.size));
- return data;
-}
-
static const char *CYPoolLibraryPath(CYPool &pool) {
Dl_info addr;
_assert(dladdr(reinterpret_cast<void *>(&CYPoolLibraryPath), &addr) != 0);
_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 all(JSObjectMake(context, All_, NULL));
CYSetProperty(context, cycript, CYJSString("all"), all);
+ JSObjectRef cache(JSObjectMake(context, NULL, NULL));
+ CYSetProperty(context, cy, CYJSString("cache"), cache);
+ CYSetPrototype(context, cache, all);
+
JSObjectRef alls(_jsccall(JSObjectCallAsConstructor, context, Array, 0, NULL));
CYSetProperty(context, cycript, CYJSString("alls"), alls);
next = JSObjectGetPrototype(context, curr);
}
- CYSetPrototype(context, last, all);
+ CYSetPrototype(context, last, cache);
}
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));
}
#endif
- CYSetProperty(context, global, CYJSString("dlerror"), CYMakeFunctor(context, "dlerror", "*"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, global, CYJSString("RTLD_DEFAULT"), CYCastJSValue(context, reinterpret_cast<intptr_t>(RTLD_DEFAULT)), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, global, CYJSString("dlsym"), CYMakeFunctor(context, "dlsym", "^v^v*"), kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, cache, CYJSString("dlerror"), CYMakeFunctor(context, "dlerror", "*"), kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, cache, CYJSString("RTLD_DEFAULT"), CYCastJSValue(context, reinterpret_cast<intptr_t>(RTLD_DEFAULT)), kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, cache, CYJSString("dlsym"), CYMakeFunctor(context, "dlsym", "^v^v*"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, global, CYJSString("NULL"), CYJSNull(context), kJSPropertyAttributeDontEnum);
+ CYSetProperty(context, cache, CYJSString("NULL"), CYJSNull(context), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, global, CYJSString("bool"), CYMakeType(context, "B"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, global, CYJSString("char"), CYMakeType(context, "c"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, global, CYJSString("short"), CYMakeType(context, "s"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, global, CYJSString("int"), CYMakeType(context, "i"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, global, CYJSString("long"), CYMakeType(context, "l"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, global, CYJSString("float"), CYMakeType(context, "f"), kJSPropertyAttributeDontEnum);
- CYSetProperty(context, global, CYJSString("double"), CYMakeType(context, "d"), kJSPropertyAttributeDontEnum);
-
- CYRunScript(context, "libcycript.cy");
+ 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);
for (CYHook *hook : GetHooks())
if (hook->SetupContext != NULL)
(*hook->SetupContext)(context);
CYArrayPush(context, alls, cycript);
+
+ CYRunScript(context, "/libcycript.cy");
}
static JSGlobalContextRef context_;