CFCType* CFCType_new_float(int flags, const char *specifier) { // Validate specifier. for (size_t i = 0; ; i++) { if (!float_specifiers[i]) { CFCUtil_die("Unknown float specifier: '%s'", specifier); } if (strcmp(float_specifiers[i], specifier) == 0) { break; } } // Cache the C representation of this type. char c_string[32]; if (flags & CFCTYPE_CONST) { sprintf(c_string, "const %s", specifier); } else { strcpy(c_string, specifier); } flags |= CFCTYPE_PRIMITIVE; flags |= CFCTYPE_FLOATING; S_check_flags(flags, CFCTYPE_CONST | CFCTYPE_PRIMITIVE | CFCTYPE_FLOATING, "Floating"); return CFCType_new(flags, NULL, specifier, 0, c_string); }
CFCType* CFCType_new_integer(int flags, const char *specifier) { // Validate specifier, find width. size_t width; if (!strcmp(specifier, "int8_t") || !strcmp(specifier, "uint8_t")) { width = 1; } else if (!strcmp(specifier, "int16_t") || !strcmp(specifier, "uint16_t")) { width = 2; } else if (!strcmp(specifier, "int32_t") || !strcmp(specifier, "uint32_t")) { width = 4; } else if (!strcmp(specifier, "int64_t") || !strcmp(specifier, "uint64_t")) { width = 8; } else if (!strcmp(specifier, "char") || !strcmp(specifier, "short") || !strcmp(specifier, "int") || !strcmp(specifier, "long") || !strcmp(specifier, "size_t") || !strcmp(specifier, "bool_t") // Charmonizer type. ) { width = 0; } else { CFCUtil_die("Unknown integer specifier: '%s'", specifier); } // Add Charmonizer prefix if necessary. char full_specifier[32]; if (strcmp(specifier, "bool_t") == 0) { strcpy(full_specifier, "chy_bool_t"); } else { strcpy(full_specifier, specifier); } // Cache the C representation of this type. char c_string[32]; if (flags & CFCTYPE_CONST) { sprintf(c_string, "const %s", full_specifier); } else { strcpy(c_string, full_specifier); } // Add flags. flags |= CFCTYPE_PRIMITIVE; flags |= CFCTYPE_INTEGER; S_check_flags(flags, CFCTYPE_CONST | CFCTYPE_PRIMITIVE | CFCTYPE_INTEGER, "Integer"); CFCType *self = CFCType_new(flags, NULL, full_specifier, 0, c_string); self->width = width; return self; }
CFCType* CFCType_new_object(int flags, CFCParcel *parcel, const char *specifier, int indirection) { // Validate params. if (indirection != 1) { CFCUtil_die("Parameter 'indirection' can only be 1"); } if (!specifier || !strlen(specifier)) { CFCUtil_die("Missing required param 'specifier'"); } if ((flags & CFCTYPE_INCREMENTED) && (flags & CFCTYPE_DECREMENTED)) { CFCUtil_die("Can't be both incremented and decremented"); } // Use default parcel if none supplied. if (!parcel) { parcel = CFCParcel_default_parcel(); } // Add flags. flags |= CFCTYPE_OBJECT; if (strstr(specifier, "String")) { // Determine whether this type is a string type. flags |= CFCTYPE_STRING_TYPE; } // Validate specifier. if (!isalpha(*specifier)) { CFCUtil_die("Invalid specifier: '%s'", specifier); } const char *small_specifier = specifier; while (!isupper(*small_specifier)) { if (!isalnum(*small_specifier) && *small_specifier != '_') { CFCUtil_die("Invalid specifier: '%s'", specifier); } small_specifier++; } if (!CFCSymbol_validate_class_name_component(small_specifier)) { CFCUtil_die("Invalid specifier: '%s'", specifier); } int acceptable_flags = CFCTYPE_OBJECT | CFCTYPE_STRING_TYPE | CFCTYPE_CONST | CFCTYPE_NULLABLE | CFCTYPE_INCREMENTED | CFCTYPE_DECREMENTED; S_check_flags(flags, acceptable_flags, "Object"); return CFCType_new(flags, parcel, specifier, 1); }
CFCType* CFCType_new_float(int flags, const char *specifier) { // Validate specifier. for (size_t i = 0; ; i++) { if (!float_specifiers[i]) { CFCUtil_die("Unknown float specifier: '%s'", specifier); } if (strcmp(float_specifiers[i], specifier) == 0) { break; } } flags |= CFCTYPE_PRIMITIVE; flags |= CFCTYPE_FLOATING; S_check_flags(flags, CFCTYPE_CONST | CFCTYPE_PRIMITIVE | CFCTYPE_FLOATING, "Floating"); return CFCType_new(flags, NULL, specifier, 0); }
CFCType* CFCType_new_composite(int flags, CFCType *child, int indirection, const char *array) { if (!child) { CFCUtil_die("Missing required param 'child'"); } flags |= CFCTYPE_COMPOSITE; S_check_flags(flags, CFCTYPE_COMPOSITE | CFCTYPE_NULLABLE, "Composite"); CFCType *self = CFCType_new(flags, NULL, CFCType_get_specifier(child), indirection); self->child = (CFCType*)CFCBase_incref((CFCBase*)child); // Record array spec. const char *array_spec = array ? array : ""; size_t array_spec_size = strlen(array_spec) + 1; self->array = (char*)MALLOCATE(array_spec_size); strcpy(self->array, array_spec); return self; }
CFCType* CFCType_new_integer(int flags, const char *specifier) { // Validate specifier, find width. size_t width; if (!strcmp(specifier, "int8_t") || !strcmp(specifier, "uint8_t")) { width = 1; } else if (!strcmp(specifier, "int16_t") || !strcmp(specifier, "uint16_t")) { width = 2; } else if (!strcmp(specifier, "int32_t") || !strcmp(specifier, "uint32_t")) { width = 4; } else if (!strcmp(specifier, "int64_t") || !strcmp(specifier, "uint64_t")) { width = 8; } else if (!strcmp(specifier, "char") || !strcmp(specifier, "short") || !strcmp(specifier, "int") || !strcmp(specifier, "long") || !strcmp(specifier, "size_t") || !strcmp(specifier, "bool") // Charmonizer type. ) { width = 0; } else { CFCUtil_die("Unknown integer specifier: '%s'", specifier); } // Add flags. flags |= CFCTYPE_PRIMITIVE; flags |= CFCTYPE_INTEGER; S_check_flags(flags, CFCTYPE_CONST | CFCTYPE_PRIMITIVE | CFCTYPE_INTEGER, "Integer"); CFCType *self = CFCType_new(flags, NULL, specifier, 0); self->width = width; return self; }
CFCType* CFCType_new_composite(int flags, CFCType *child, int indirection, const char *array) { if (!child) { CFCUtil_die("Missing required param 'child'"); } flags |= CFCTYPE_COMPOSITE; S_check_flags(flags, CFCTYPE_COMPOSITE | CFCTYPE_NULLABLE, "Composite"); // Cache C representation. // NOTE: Array postfixes are NOT included. const size_t MAX_LEN = 256; const char *child_c_string = CFCType_to_c(child); size_t child_c_len = strlen(child_c_string); size_t amount = child_c_len + indirection; if (amount > MAX_LEN) { CFCUtil_die("C representation too long"); } char c_string[MAX_LEN + 1]; strcpy(c_string, child_c_string); for (int i = 0; i < indirection; i++) { strncat(c_string, "*", 1); } CFCType *self = CFCType_new(flags, NULL, CFCType_get_specifier(child), indirection, c_string); self->child = (CFCType*)CFCBase_incref((CFCBase*)child); // Record array spec. const char *array_spec = array ? array : ""; size_t array_spec_size = strlen(array_spec) + 1; self->array = (char*)MALLOCATE(array_spec_size); strcpy(self->array, array_spec); return self; }
CFCType* CFCType_new_object(int flags, CFCParcel *parcel, const char *specifier, int indirection) { // Validate params. if (indirection != 1) { CFCUtil_die("Parameter 'indirection' can only be 1"); } if (!specifier || !strlen(specifier)) { CFCUtil_die("Missing required param 'specifier'"); } if ((flags & CFCTYPE_INCREMENTED) && (flags & CFCTYPE_DECREMENTED)) { CFCUtil_die("Can't be both incremented and decremented"); } // Use default parcel if none supplied. if (!parcel) { parcel = CFCParcel_default_parcel(); } // Add flags. flags |= CFCTYPE_OBJECT; if (strstr(specifier, "CharBuf")) { // Determine whether this type is a string type. flags |= CFCTYPE_STRING_TYPE; } const size_t MAX_SPECIFIER_LEN = 256; char full_specifier[MAX_SPECIFIER_LEN + 1]; char small_specifier[MAX_SPECIFIER_LEN + 1]; if (isupper(*specifier)) { const char *prefix = CFCParcel_get_prefix(parcel); if (strlen(prefix) + strlen(specifier) > MAX_SPECIFIER_LEN) { CFCUtil_die("Specifier and/or parcel prefix too long"); } sprintf(full_specifier, "%s%s", prefix, specifier); strcpy(small_specifier, specifier); } else if (!isalpha(*specifier)) { CFCUtil_die("Invalid specifier: '%s'", specifier); } else { if (strlen(specifier) > MAX_SPECIFIER_LEN) { CFCUtil_die("Specifier too long"); } const char *probe = specifier; while (*probe) { if (isupper(*probe)) { break; } else if (!isalnum(*probe) && *probe != '_') { CFCUtil_die("Invalid specifier: '%s'", specifier); } probe++; } strcpy(full_specifier, specifier); strcpy(small_specifier, probe); } if (!CFCSymbol_validate_class_name_component(small_specifier)) { CFCUtil_die("Invalid specifier: '%s'", specifier); } // Cache C representation. char c_string[MAX_SPECIFIER_LEN + 10]; if (flags & CFCTYPE_CONST) { sprintf(c_string, "const %s*", full_specifier); } else { sprintf(c_string, "%s*", full_specifier); } int acceptable_flags = CFCTYPE_OBJECT | CFCTYPE_STRING_TYPE | CFCTYPE_CONST | CFCTYPE_NULLABLE | CFCTYPE_INCREMENTED | CFCTYPE_DECREMENTED; S_check_flags(flags, acceptable_flags, "Object"); return CFCType_new(flags, parcel, full_specifier, 1, c_string); }