static void cg_proc_result_set_type_based_getter()

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);
}