struct upkg_export_priv {
struct upkg_export pub;
- long class, super;
+ long super;
unsigned long size, offset;
};
}
len = 0;
- rc = upkg_decode_index(&export->class, buf+len, nbuf-len);
+ rc = upkg_decode_index(&export->pub.class, buf+len, nbuf-len);
if (rc == 0) goto err;
len += rc;
export = &pkg->exports[idx];
/* Assumption: class references are always imports. */
- format_assert(export->class <= 0, return NULL);
+ format_assert(export->pub.class <= 0, return NULL);
/* Get the class. */
- if (export->class == 0) {
+ if (export->pub.class == 0) {
if (package) *package = "Core";
return "Class";
}
- pkg_idx = -(export->class + 1);
+ pkg_idx = -(export->pub.class + 1);
if (pkg_idx >= pkg->pub.import_count)
return NULL;
iclass = &pkg->imports[pkg_idx];
#include <ltdl.h>
#include <uobject/module.h>
+#include <uobject/uobject.h>
#include <uobject/package.h>
+#include <upkg.h>
#include "avl.h"
static unsigned initialized;
return 0;
}
-GType u_object_module_get_class(const char *package, const char *class)
+static int lookup_module(GTypeModule **out, const char *name)
{
- char buf[strlen(package) + strlen(class) + 1];
- GTypeModule search = { .name = str_cpy_lower(buf, package) };
+ struct { GTypeModule pkg; char buf[]; } *search_key;
+ GTypeModule *result;
- GTypeModule *mod = avl_find(package_tree, &search);
- if (!mod) {
+ search_key = malloc(sizeof *search_key + strlen(name) + 1);
+ if (!search_key)
+ return -1;
+
+ search_key->pkg = (GTypeModule) {
+ .name = str_cpy_lower(search_key->buf, name),
+ };
+
+ result = avl_find(package_tree, search_key);
+ free(search_key);
+
+ *out = result;
+ return 0;
+}
+
+GTypeModule *
+u_module_get_from_import(GTypeModule *pkg, const struct upkg_import *i)
+{
+ GTypeModule *result;
+
+ while (i->parent != NULL)
+ i = i->parent;
+
+ if (strcmp(i->class_package, "Core") != 0
+ || strcmp(i->class_name, "Package") != 0) {
+ u_err(pkg, "import root must be an instance of Core.Package");
+ return NULL;
+ }
+
+ if (lookup_module(&result, i->name) != 0) {
+ u_err(pkg, "fatal error performing package lookup");
+ return NULL;
+ }
+
+ if (!result) {
void **p;
- mod = u_pkg_open(package);
- if (!mod) {
- return 0;
+ result = u_pkg_open(i->name);
+ if (!result) {
+ u_warn(pkg, "failed to open package: %s", i->name);
+ return NULL;
}
- p = avl_probe(package_tree, mod);
+ p = avl_probe(package_tree, result);
if (!p) {
- g_object_unref(mod);
+ u_err(pkg, "fatal error inserting package");
+ g_object_unref(result);
+ return NULL;
+ }
+ }
+
+ return result;
+}
+
+GType u_object_module_get_class(GTypeModule *pkg, long class)
+{
+ GTypeModule *mod;
+ const char *classname;
+
+ if (class == 0) {
+ u_warn(pkg, "class implementations not supported yet");
+ return 0;
+ } else if (class < 0) {
+ const struct upkg_import *import;
+
+ import = upkg_get_import(U_PKG(pkg)->pkg, -(class+1));
+ if (!import) {
+ u_err(pkg, "invalid package import: %ld", -(class+1));
return 0;
}
+
+ mod = u_module_get_from_import(pkg, import);
+ if (!mod)
+ return 0;
+
+ classname = import->name;
+ } else if (class > 0) {
+ const struct upkg_export *export;
+
+ export = upkg_get_export(U_PKG(pkg)->pkg, class-1);
+ if (!export) {
+ u_err(pkg, "invalid package export: %ld", class-1);
+ return 0;
+ }
+
+ mod = pkg;
+ classname = export->name;
}
if (!g_type_module_use(mod))
return 0;
- str_cpy_lower(buf+strlen(package), class);
- buf[0] = toupper(buf[0]);
- buf[strlen(package)] = toupper(buf[strlen(package)]);
- return g_type_from_name(buf);
+ /* XXX: Do this better. */
+ char typename[strlen(mod->name) + strlen(classname) + 1];
+ str_cpy_lower(typename, mod->name);
+ str_cpy_lower(typename+strlen(mod->name), classname);
+ typename[0] = toupper(typename[0]);
+ typename[strlen(mod->name)] = toupper(typename[strlen(mod->name)]);
+
+ return g_type_from_name(typename);
}
int u_object_module_exit(void);
/*
- * Get a class handle from the UObject module system. This will load the
- * appropriate shared object if necessary. The resulting handle can then be
- * used to create instances of the class with g_object_new.
+ * Get a class handle from the UObject module system, where class is an
+ * object reference for the class within the provided package. This will load
+ * the appropriate shared object if necessary. The resulting handle can then
+ * be used to create instances of the class with g_object_new.
*
* Returns 0 on failure.
*/
-GType u_object_module_get_class(const char *package, const char *class);
+GType u_object_module_get_class(GTypeModule *pkg, long class);
#endif
{
g_return_val_if_fail(IS_U_PKG(pkg), NULL);
- const char *class, *package;
+ const struct upkg_export *export;
GObject *obj = NULL;
GType type;
- class = upkg_export_class(U_PKG(pkg)->pkg, idx, &package);
- if (!class)
+ export = upkg_get_export(U_PKG(pkg)->pkg, idx);
+ if (!export) {
+ u_err(pkg, "invalid package export: %lu", idx);
return NULL;
+ }
- type = u_object_module_get_class(package, class);
+ type = u_object_module_get_class(pkg, export->class);
if (type) {
obj = g_object_new(type, NULL);
if (u_object_deserialize(obj, pkg, idx) != 0) {