in sources/cg_c.c [7148:7251]
static void cg_proc_result_set_type_based_getter(function_info *_Nonnull info)
{
charbuf *h = info->headers;
charbuf *d = info->defs;
charbuf *out = NULL;
Invariant(info->frag_type != FRAG_TYPE_EXTENSION);
CG_CHARBUF_OPEN_SYM_WITH_PREFIX(
col_getter_sym,
rt->symbol_prefix,
info->name,
"_get_",
info->col,
info->sym_suffix);
CHARBUF_OPEN(func_decl);
cg_var_decl(&func_decl, info->ret_type, col_getter_sym.ptr, CG_VAR_DECL_PROTO);
bprintf(&func_decl, "(%s _Nonnull result_set", info->result_set_ref_type);
// a procedure that uses OUT gives exactly one row, so no index in the API
if (!info->uses_out) {
bprintf(&func_decl, ", %s row", rt->cql_int32);
}
bprintf(&func_decl, ")");
CSTR row = info->uses_out ? "0" : "row";
// not set yet
Invariant(!out);
if (info->frag_type == FRAG_TYPE_ASSEMBLY || info->frag_type == FRAG_TYPE_BASE) {
// In the assembly or base fragment case we emit only the prototype into the header file
// The body goes into the main section. This is necessary because the extension fragments could be in other
// linkage units and they will try to call these getters. So the linkage has to allow the extension getters
// to have access to the authoritative getters. In the base case we're merely foreshadowing the actual
// definitions that will be created by the assembly but limited to the base columns.
// The body of the function will be emitted into the defs section (d).
bprintf(h, "\n%s%s;", rt->symbol_visibility, func_decl.ptr);
// in the base fragment case we only emit the prototype that the assembly will generate
// and no body... we're done at this point
if (info->frag_type == FRAG_TYPE_BASE) {
goto cleanup;
}
bprintf(d, "\n%s%s {\n", rt->symbol_visibility, func_decl.ptr);
out = d;
}
else {
// The inline body will all go into the header file in the normal case.
// Note it's ok for these to be static inline because they have a different name
// (they include the extension frag) so they don't conflict with the base/assembly frag names
// These guys just forward on to the assembly fragment
bprintf(h, "\nstatic inline %s {\n", func_decl.ptr);
out = h;
}
// definitely set now
Invariant(out);
bprintf(out, " return ");
if (is_ref_type(info->name_type) && is_nullable(info->ret_type)) {
bprintf(out,
"%s((cql_result_set_ref)result_set, %s, %d) ? NULL : ",
rt->cql_result_set_get_is_null,
row,
info->col_index);
}
switch (info->name_type) {
case SEM_TYPE_NULL:
bprintf(out, "%s", rt->cql_result_set_get_is_null);
break;
case SEM_TYPE_BOOL:
bprintf(out, "%s", rt->cql_result_set_get_bool);
break;
case SEM_TYPE_REAL:
bprintf(out, "%s", rt->cql_result_set_get_double);
break;
case SEM_TYPE_INTEGER:
bprintf(out, "%s", rt->cql_result_set_get_int32);
break;
case SEM_TYPE_LONG_INTEGER:
bprintf(out, "%s", rt->cql_result_set_get_int64);
break;
case SEM_TYPE_TEXT:
bprintf(out, "%s", rt->cql_result_set_get_string);
break;
case SEM_TYPE_BLOB:
bprintf(out, "%s", rt->cql_result_set_get_blob);
break;
case SEM_TYPE_OBJECT:
bprintf(out, "%s", rt->cql_result_set_get_object);
break;
}
bprintf(out, "((cql_result_set_ref)result_set, %s, %d);\n", row, info->col_index);
bprintf(out, "}\n");
cleanup:
CHARBUF_CLOSE(func_decl);
CHARBUF_CLOSE(col_getter_sym);
}