Clownfish-CFC
view release on metacpan or search on metacpan
src/CFCGoTypeMap.c view on Meta::CPAN
if (CFCType_cfish_obj(type)) {
return CFCUtil_strdup("interface{}");
}
else if (CFCType_cfish_string(type)) {
return CFCUtil_strdup("string");
}
else if (CFCType_cfish_blob(type)) {
return CFCUtil_strdup("[]byte");
}
else if (CFCType_cfish_vector(type)) {
return CFCUtil_strdup("[]interface{}");
}
else if (CFCType_cfish_hash(type)) {
return CFCUtil_strdup("map[string]interface{}");
}
else if (CFCType_is_object(type)) {
// Divide the specifier into prefix and struct name.
CFCClass *klass = CFCType_get_class(type);
const char *struct_sym = CFCClass_get_struct_sym(klass);
CFCParcel *parcel = CFCClass_get_parcel(klass);
if (!parcel) {
CFCUtil_die("Can't find parcel for type '%s'",
CFCType_get_specifier(type));
}
// If the type lives in this parcel, return only the struct sym
// without a go package prefix.
if (parcel == current_parcel) {
return CFCUtil_strdup(struct_sym);
}
// The type lives in another parcel, so prefix its Go package name.
// TODO: Stop downcasing once Clownfish parcel names are constrained
// to lower case.
const char *package_name = CFCParcel_get_name(parcel);
if (strrchr(package_name, '.')) {
package_name = strrchr(package_name, '.') + 1;
}
char *result = CFCUtil_sprintf("%s.%s", package_name, struct_sym);
for (int i = 0; result[i] != '.'; i++) {
result[i] = CFCUtil_tolower(result[i]);
}
return result;
}
else if (CFCType_is_primitive(type)) {
const char *specifier = CFCType_get_specifier(type);
for (int i = 0; i < num_conversions; i++) {
if (strcmp(specifier, conversions[i].c) == 0) {
return CFCUtil_strdup(conversions[i].go);
}
}
}
return NULL;
}
char*
CFCGoTypeMap_go_short_package(CFCParcel *parcel) {
// The Go short package name is the last component of the dot-separated
// Clownfish parcel name.
const char *parcel_frag = strrchr(CFCParcel_get_name(parcel), '.');
if (parcel_frag) {
parcel_frag += 1;
}
else {
parcel_frag = CFCParcel_get_name(parcel);
}
// TODO: Don't downcase package name once caps are forbidden in Clownfish
// parcel names.
char *go_short_package = CFCUtil_strdup(parcel_frag);
for (int i = 0; go_short_package[i] != '\0'; i++) {
go_short_package[i] = CFCUtil_tolower(go_short_package[i]);
}
return go_short_package;
}
void
CFCGoTypeMap_go_meth_receiever(const char *struct_name,
CFCParamList *param_list,
char *buf, size_t buf_len) {
size_t max_required = 2;
if (param_list != NULL && CFCParamList_num_vars(param_list) > 0) {
CFCVariable **vars = CFCParamList_get_variables(param_list);
const char *orig = CFCVariable_get_name(vars[0]);
max_required = strlen(orig) + 1;
}
if (buf_len < max_required) {
CFCUtil_die("Buffer length too short: %d", (int)buf_len);
}
// Find the first letter of the type and lowercase it.
for (size_t i = 0, max = strlen(struct_name); i < max; i++) {
if (CFCUtil_isupper(struct_name[i])) {
buf[0] = CFCUtil_tolower(struct_name[i]);
buf[1] = '\0';
break;
}
}
// Check for another argument with the same name.
if (param_list != NULL) {
CFCVariable **vars = CFCParamList_get_variables(param_list);
int num_vars = CFCParamList_num_vars(param_list);
for (int i = 1; i < num_vars; i++) {
const char *name = CFCVariable_get_name(vars[i]);
if (strcmp(name, buf) == 0) {
// Bah, a clash. Use the original name, even though it's
// probably "self" which isn't good Go style.
CFCGoTypeMap_go_arg_name(param_list, 0, buf, buf_len);
break;
}
}
}
}
void
CFCGoTypeMap_go_arg_name(CFCParamList *param_list, size_t tick, char *buf,
size_t buf_len) {
int num_vars = CFCParamList_num_vars(param_list);
if (tick >= (size_t)num_vars) {
CFCUtil_die("Index out of range: %d >= %d", (int)tick, num_vars);
}
CFCVariable **vars = CFCParamList_get_variables(param_list);
const char *orig = CFCVariable_get_name(vars[tick]);
size_t max_required = strlen(orig) + 2;
if (buf_len < max_required || buf_len < 5) {
CFCUtil_die("Buffer length too short: %d", (int)buf_len);
}
( run in 1.780 second using v1.01-cache-2.11-cpan-364913b4093 )