Clownfish-CFC
view release on metacpan or search on metacpan
src/CFCBindClass.c view on Meta::CPAN
#define CFC_NEED_BASE_STRUCT_DEF
#include <stdio.h>
#include <string.h>
#include "CFCBindClass.h"
#include "CFCBindFunction.h"
#include "CFCBindMethod.h"
#include "CFCBase.h"
#include "CFCClass.h"
#include "CFCFunction.h"
#include "CFCMethod.h"
#include "CFCParamList.h"
#include "CFCParcel.h"
#include "CFCType.h"
#include "CFCVariable.h"
#include "CFCUtil.h"
struct CFCBindClass {
CFCBase base;
CFCClass *client;
char *short_names_macro;
};
// Generate C header for an inert class.
static char*
S_to_c_header_inert(CFCBindClass *self);
// Generate C header for a dynamic class.
static char*
S_to_c_header_dynamic(CFCBindClass *self);
// Create the definition for the instantiable object struct.
static char*
S_struct_definition(CFCBindClass *self);
// Declare typedefs for fresh methods, to ease casting.
static char*
S_method_typedefs(CFCBindClass *self);
// If class inherits from something, include the parent class's header.
static char*
S_parent_include(CFCBindClass *self);
// Add a C function definition for each method and each function.
static char*
S_sub_declarations(CFCBindClass *self);
// Declare class (a.k.a. "inert") variables.
static char*
S_inert_var_declarations(CFCBindClass *self);
// Define type-safe wrappers for Obj functions.
static char*
S_wrapper_defs(CFCBindClass *self);
// Define method invocation inline functions.
static char*
S_method_defs(CFCBindClass *self);
// Declare override symbols for functions which wrap host callbacks.
static char*
S_override_decs(CFCBindClass *self);
// Define short names for all of the symbols associated with this class.
static char*
S_short_names(CFCBindClass *self);
static const CFCMeta CFCBINDCLASS_META = {
"Clownfish::CFC::Binding::Core::Class",
sizeof(CFCBindClass),
(CFCBase_destroy_t)CFCBindClass_destroy
};
CFCBindClass*
CFCBindClass_new(CFCClass *client) {
CFCBindClass *self = (CFCBindClass*)CFCBase_allocate(&CFCBINDCLASS_META);
return CFCBindClass_init(self, client);
}
CFCBindClass*
CFCBindClass_init(CFCBindClass *self, CFCClass *client) {
CFCUTIL_NULL_CHECK(client);
self->client = (CFCClass*)CFCBase_incref((CFCBase*)client);
const char *PREFIX = CFCClass_get_PREFIX(client);
self->short_names_macro = CFCUtil_sprintf("%sUSE_SHORT_NAMES", PREFIX);
return self;
}
void
CFCBindClass_destroy(CFCBindClass *self) {
FREEMEM(self->short_names_macro);
CFCBase_decref((CFCBase*)self->client);
CFCBase_destroy((CFCBase*)self);
}
char*
CFCBindClass_to_c_header(CFCBindClass *self) {
if (CFCClass_inert(self->client)) {
// Inert classes only output inert functions and vars.
return S_to_c_header_inert(self);
}
else {
return S_to_c_header_dynamic(self);
}
}
static char*
S_to_c_header_inert(CFCBindClass *self) {
char *inert_func_decs = S_sub_declarations(self);
char *inert_var_defs = S_inert_var_declarations(self);
char *short_names = S_short_names(self);
char pattern[] =
"/* Declare this class's inert variables.\n"
" */\n"
"\n"
"%s\n"
"\n"
src/CFCBindClass.c view on Meta::CPAN
short_struct, full_struct,
short_func, full_func);
return content;
}
static char*
S_to_c_header_dynamic(CFCBindClass *self) {
const char *privacy_symbol = CFCClass_privacy_symbol(self->client);
char *ivars = S_ivars_func(self);
char *struct_def = S_struct_definition(self);
char *parent_include = S_parent_include(self);
char *sub_declarations = S_sub_declarations(self);
char *inert_var_defs = S_inert_var_declarations(self);
char *method_typedefs = S_method_typedefs(self);
char *wrapper_defs = S_wrapper_defs(self);
char *method_defs = S_method_defs(self);
char *override_decs = S_override_decs(self);
char *short_names = S_short_names(self);
char pattern[] =
"/* Include the header for this class's parent. \n"
" */\n"
"\n"
"%s\n"
"\n"
"/* Define the struct layout for instances of this class.\n"
" */\n"
"\n"
"#ifdef %s\n"
"%s\n"
"%s\n"
"#endif /* %s */\n"
"\n"
"/* Declare this class's inert variables.\n"
" */\n"
"\n"
"%s\n"
"\n"
"/* Declare both this class's inert functions and the C functions which\n"
" * implement this class's dynamic methods.\n"
" */\n"
"\n"
"%s\n"
"\n"
"/* Define typedefs for each dynamic method, allowing us to cast generic\n"
" * pointers to the appropriate function pointer type more cleanly.\n"
" */\n"
"\n"
"%s\n"
"\n"
"/* Define type-safe wrappers for inert functions of Obj.\n"
" */\n"
"\n"
"%s\n"
"\n"
"/* Define the inline functions which implement this class's virtual methods.\n"
" */\n"
"\n"
"%s\n"
"\n"
"/* Declare callbacks for wrapping host overrides.\n"
" */\n"
"\n"
"%s\n"
"\n"
"/* Define \"short names\" for this class's symbols.\n"
" */\n"
"\n"
"%s\n"
"\n";
char *content
= CFCUtil_sprintf(pattern, parent_include, privacy_symbol, ivars,
struct_def, privacy_symbol, inert_var_defs,
sub_declarations, method_typedefs, wrapper_defs,
method_defs, override_decs, short_names);
FREEMEM(ivars);
FREEMEM(struct_def);
FREEMEM(parent_include);
FREEMEM(sub_declarations);
FREEMEM(inert_var_defs);
FREEMEM(method_typedefs);
FREEMEM(wrapper_defs);
FREEMEM(method_defs);
FREEMEM(override_decs);
FREEMEM(short_names);
return content;
}
char*
CFCBindClass_to_c_data(CFCBindClass *self) {
CFCClass *client = self->client;
if (CFCClass_inert(client)) {
return CFCUtil_strdup("");
}
const char *ivars_offset = CFCClass_full_ivars_offset(client);
const char *class_var = CFCClass_full_class_var(client);
CFCMethod **methods = CFCClass_methods(client);
char *offsets = CFCUtil_strdup("");
char *method_defs = CFCUtil_strdup("");
for (int meth_num = 0; methods[meth_num] != NULL; meth_num++) {
CFCMethod *method = methods[meth_num];
// Define method offset variable.
char *full_offset_sym = CFCMethod_full_offset_sym(method, client);
offsets = CFCUtil_cat(offsets, "uint32_t ", full_offset_sym, ";\n",
NULL);
FREEMEM(full_offset_sym);
int is_fresh = CFCMethod_is_fresh(method, client);
// Create a default implementation for abstract methods.
if (is_fresh && CFCMethod_abstract(method)) {
char *method_def = CFCBindMeth_abstract_method_def(method, client);
method_defs = CFCUtil_cat(method_defs, method_def, "\n", NULL);
FREEMEM(method_def);
( run in 0.618 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )