coco_problem_t *coco_problem_duplicate(coco_problem_t *other) { size_t i; coco_problem_t *problem; problem = coco_problem_allocate(other->number_of_variables, other->number_of_objectives, other->number_of_constraints); problem->evaluate_function = other->evaluate_function; problem->evaluate_constraint = other->evaluate_constraint; problem->recommend_solutions = other->recommend_solutions; problem->free_problem = NULL; for (i = 0; i < problem->number_of_variables; ++i) { problem->smallest_values_of_interest[i] = other->smallest_values_of_interest[i]; problem->largest_values_of_interest[i] = other->largest_values_of_interest[i]; if (other->best_parameter) problem->best_parameter[i] = other->best_parameter[i]; } if (other->best_value) for (i = 0; i < problem->number_of_objectives; ++i) { problem->best_value[i] = other->best_value[i]; } problem->problem_name = coco_strdup(other->problem_name); problem->problem_id = coco_strdup(other->problem_id); problem->suite_dep_index = other->suite_dep_index; problem->suite_dep_function_id = other->suite_dep_function_id; problem->suite_dep_instance_id = other->suite_dep_instance_id; return problem; }
/** * @brief Formatted string duplication, with va_list arguments. */ static char *coco_vstrdupf(const char *str, va_list args) { static char buf[COCO_VSTRDUPF_BUFLEN]; long written; /* apparently args can only be used once, therefore * len = vsnprintf(NULL, 0, str, args) to find out the * length does not work. Therefore we use a buffer * which limits the max length. Longer strings should * never appear anyway, so this is rather a non-issue. */ #if 0 written = vsnprintf(buf, COCO_VSTRDUPF_BUFLEN - 2, str, args); if (written < 0) coco_error("coco_vstrdupf(): vsnprintf failed on '%s'", str); #else /* less safe alternative, if vsnprintf is not available */ assert(strlen(str) < COCO_VSTRDUPF_BUFLEN / 2 - 2); if (strlen(str) >= COCO_VSTRDUPF_BUFLEN / 2 - 2) coco_error("coco_vstrdupf(): string is too long"); written = vsprintf(buf, str, args); if (written < 0) coco_error("coco_vstrdupf(): vsprintf failed on '%s'", str); #endif if (written > COCO_VSTRDUPF_BUFLEN - 3) coco_error("coco_vstrdupf(): A suspiciously long string is tried to being duplicated '%s'", buf); return coco_strdup(buf); }
/** * @brief Allocates a transformed problem that wraps the inner_problem. * * By default all methods will dispatch to the inner_problem. A prefix is prepended to the problem name * in order to reflect the transformation somewhere. */ static coco_problem_t *coco_problem_transformed_allocate(coco_problem_t *inner_problem, void *user_data, coco_data_free_function_t data_free_function, const char *name_prefix) { coco_problem_transformed_data_t *problem; coco_problem_t *inner_copy; char *old_name = coco_strdup(inner_problem->problem_name); problem = (coco_problem_transformed_data_t *) coco_allocate_memory(sizeof(*problem)); problem->inner_problem = inner_problem; problem->data = user_data; problem->data_free_function = data_free_function; inner_copy = coco_problem_duplicate(inner_problem); inner_copy->evaluate_function = coco_problem_transformed_evaluate_function; inner_copy->evaluate_constraint = coco_problem_transformed_evaluate_constraint; inner_copy->recommend_solution = coco_problem_transformed_recommend_solution; inner_copy->problem_free_function = coco_problem_transformed_free; inner_copy->data = problem; coco_problem_set_name(inner_copy, "%s(%s)", name_prefix, old_name); coco_free_memory(old_name); return inner_copy; }
/** * @brief Creates and returns a string with removed characters between from and to. * * If you wish to remove characters from the beginning of the string, set from to "". * If you wish to remove characters until the end of the string, set to to "". * * The caller is responsible for freeing the allocated memory using coco_free_memory(). */ static char *coco_remove_from_string(const char *string, const char *from, const char *to) { char *result, *start, *stop; result = coco_strdup(string); if (strcmp(from, "") == 0) { /* Remove from the start */ start = result; } else start = strstr(result, from); if (strcmp(to, "") == 0) { /* Remove until the end */ stop = result + strlen(result); } else stop = strstr(result, to); if ((start == NULL) || (stop == NULL) || (stop < start)) { coco_error("coco_remove_from_string(): failed to remove characters between %s and %s from string %s", from, to, string); return NULL; /* Never reached */ } memmove(start, stop, strlen(stop) + 1); return result; }
/** * @brief Creates a duplicate of the 'other' problem for all fields except for data, which points to NULL. */ static coco_problem_t *coco_problem_duplicate(const coco_problem_t *other) { size_t i; coco_problem_t *problem; problem = coco_problem_allocate(other->number_of_variables, other->number_of_objectives, other->number_of_constraints); problem->initial_solution = other->initial_solution; problem->evaluate_function = other->evaluate_function; problem->evaluate_constraint = other->evaluate_constraint; problem->recommend_solution = other->recommend_solution; problem->problem_free_function = other->problem_free_function; for (i = 0; i < problem->number_of_variables; ++i) { problem->smallest_values_of_interest[i] = other->smallest_values_of_interest[i]; problem->largest_values_of_interest[i] = other->largest_values_of_interest[i]; if (other->best_parameter) problem->best_parameter[i] = other->best_parameter[i]; } if (other->best_value) for (i = 0; i < problem->number_of_objectives; ++i) { problem->best_value[i] = other->best_value[i]; } if (other->nadir_value) for (i = 0; i < problem->number_of_objectives; ++i) { problem->nadir_value[i] = other->nadir_value[i]; } problem->problem_name = coco_strdup(other->problem_name); problem->problem_id = coco_strdup(other->problem_id); problem->problem_type = coco_strdup(other->problem_type); problem->evaluations = other->evaluations; problem->final_target_delta[0] = other->final_target_delta[0]; problem->best_observed_fvalue[0] = other->best_observed_fvalue[0]; problem->best_observed_evaluation[0] = other->best_observed_evaluation[0]; problem->suite = other->suite; problem->suite_dep_index = other->suite_dep_index; problem->suite_dep_function = other->suite_dep_function; problem->suite_dep_instance = other->suite_dep_instance; problem->data = NULL; return problem; }
static coco_problem_t *logger_bbob2009(coco_problem_t *inner_problem, const char *alg_name) { logger_bbob2009_t *data; coco_problem_t *self; data = coco_allocate_memory(sizeof(*data)); data->alg_name = coco_strdup(alg_name); if (bbob2009_logger_is_open) coco_error("The current bbob2009_logger (observer) must be closed before a new one is opened"); /* This is the name of the folder which happens to be the algName */ data->path = coco_strdup(alg_name); data->index_file = NULL; data->fdata_file = NULL; data->tdata_file = NULL; data->rdata_file = NULL; data->number_of_variables = inner_problem->number_of_variables; if (inner_problem->best_value == NULL) { /* coco_error("Optimal f value must be defined for each problem in order for the logger to work properly"); */ /* Setting the value to 0 results in the assertion y>=optimal_fvalue being susceptible to failure */ coco_warning("undefined optimal f value. Set to 0"); data->optimal_fvalue = 0; } else { data->optimal_fvalue = *(inner_problem->best_value); } bbob2009_raisedOptValWarning = 0; data->idx_f_trigger = INT_MAX; data->idx_t_trigger = 0; data->idx_tdim_trigger = 0; data->f_trigger = DBL_MAX; data->t_trigger = 0; data->number_of_evaluations = 0; data->best_solution = coco_allocate_vector(inner_problem->number_of_variables); /* TODO: the following inits are just to be in the safe side and * should eventually be removed. Some fields of the bbob2009_logger struct * might be useless */ data->function_id = coco_problem_get_suite_dep_function_id(inner_problem); data->instance_id = coco_problem_get_suite_dep_instance_id(inner_problem); data->written_last_eval = 1; data->last_fvalue = DBL_MAX; data->is_initialized = 0; self = coco_transformed_allocate(inner_problem, data, logger_bbob2009_free); self->evaluate_function = logger_bbob2009_evaluate; bbob2009_logger_is_open = 1; return self; }
/** * Allocates memory for a coco_observer_t instance. */ static coco_observer_t *coco_observer_allocate(const char *output_folder, const char *algorithm_name, const char *algorithm_info, const int precision_x, const int precision_f) { coco_observer_t *observer; observer = (coco_observer_t *) coco_allocate_memory(sizeof(*observer)); /* Initialize fields to sane/safe defaults */ observer->output_folder = coco_strdup(output_folder); observer->algorithm_name = coco_strdup(algorithm_name); observer->algorithm_info = coco_strdup(algorithm_info); observer->precision_x = precision_x; observer->precision_f = precision_f; observer->data = NULL; observer->data_free_function = NULL; observer->logger_initialize_function = NULL; observer->is_active = 1; return observer; }
/** * @brief Creates and returns the information on the solution in the form of a node's item in the AVL tree. */ static coco_archive_avl_item_t* coco_archive_node_item_create(const double f1, const double f2, const char *text) { /* Allocate memory to hold the data structure mo_preprocessing_avl_item_t */ coco_archive_avl_item_t *item = (coco_archive_avl_item_t*) coco_allocate_memory(sizeof(*item)); item->f1 = f1; item->f2 = f2; item->text = coco_strdup(text); return item; }
static coco_problem_t *log_nondominating(coco_problem_t *inner_problem, const size_t max_size_of_archive, const char *path) { _log_nondominating_t *data; coco_problem_t *self; data = coco_allocate_memory(sizeof(*data)); data->number_of_evaluations = 0; data->path = coco_strdup(path); data->logfile = NULL; /* Open lazily in lht_evaluate_function(). */ data->max_size_of_archive = max_size_of_archive; self = coco_allocate_transformed_problem(inner_problem, data, _lnd_free_data); self->evaluate_function = lnd_evaluate_function; return self; }
/** * Tests the function coco_set_log_level. */ static void test_coco_set_log_level(void **state) { char *previous_log_level; /* Check whether the default set to COCO_INFO */ assert(strcmp(coco_set_log_level(""), "info") == 0); /* Check whether the method works */ previous_log_level = coco_strdup(coco_set_log_level("error")); assert(strcmp(previous_log_level, "info") == 0); assert(strcmp(coco_set_log_level(""), "error") == 0); coco_free_memory(previous_log_level); previous_log_level = coco_strdup(coco_set_log_level("warning")); assert(strcmp(previous_log_level, "error") == 0); assert(strcmp(coco_set_log_level(""), "warning") == 0); coco_free_memory(previous_log_level); previous_log_level = coco_strdup(coco_set_log_level("debug")); assert(strcmp(previous_log_level, "warning") == 0); assert(strcmp(coco_set_log_level(""), "debug") == 0); coco_free_memory(previous_log_level); previous_log_level = coco_strdup(coco_set_log_level("info")); assert(strcmp(previous_log_level, "debug") == 0); assert(strcmp(coco_set_log_level(""), "info") == 0); coco_free_memory(previous_log_level); /* An invalid argument shouldn't change the current value */ previous_log_level = coco_strdup(coco_set_log_level("bla")); assert(strcmp(previous_log_level, "info") == 0); assert(strcmp(coco_set_log_level(""), "info") == 0); coco_free_memory(previous_log_level); (void)state; /* unused */ }
/** * @brief Creates and returns the information on the solution in the form of a node's item in the AVL tree. */ static coco_archive_avl_item_t* coco_archive_node_item_create(const double *y, const double *ideal, const double *nadir, const size_t num_obj, const char *text) { /* Allocate memory to hold the data structure coco_archive_avl_item_t */ coco_archive_avl_item_t *item = (coco_archive_avl_item_t*) coco_allocate_memory(sizeof(*item)); /* Compute the normalized y */ item->normalized_y = mo_normalize(y, ideal, nadir, num_obj); item->text = coco_strdup(text); return item; }
static coco_problem_t *f_schaffers(const size_t number_of_variables) { size_t i, problem_id_length; coco_problem_t *problem = coco_problem_allocate(number_of_variables, 1, 0); problem->problem_name = coco_strdup("schaffers function"); /* Construct a meaningful problem id */ problem_id_length = (size_t) snprintf(NULL, 0, "%s_%02lu", "schaffers", (long) number_of_variables); problem->problem_id = coco_allocate_memory(problem_id_length + 1); snprintf(problem->problem_id, problem_id_length + 1, "%s_%02lu", "schaffers", (long) number_of_variables); problem->number_of_variables = number_of_variables; problem->number_of_objectives = 1; problem->number_of_constraints = 0; problem->evaluate_function = f_schaffers_evaluate; for (i = 0; i < number_of_variables; ++i) { problem->smallest_values_of_interest[i] = -5.0; problem->largest_values_of_interest[i] = 5.0; problem->best_parameter[i] = 0.0; } /* Calculate best parameter value */ f_schaffers_evaluate(problem, problem->best_parameter, problem->best_value); return problem; }
static coco_problem_t *bent_cigar_problem(const size_t number_of_variables) { size_t i, problem_id_length; coco_problem_t *problem = coco_allocate_problem(number_of_variables, 1, 0); problem->problem_name = coco_strdup("bent cigar function"); /* Construct a meaningful problem id */ problem_id_length = snprintf(NULL, 0, "%s_%02i", "bent_cigar", (int)number_of_variables); problem->problem_id = coco_allocate_memory(problem_id_length + 1); snprintf(problem->problem_id, problem_id_length + 1, "%s_%02d", "bent_cigar", (int)number_of_variables); problem->number_of_variables = number_of_variables; problem->number_of_objectives = 1; problem->number_of_constraints = 0; problem->evaluate_function = _bent_cigar_evaluate; for (i = 0; i < number_of_variables; ++i) { problem->smallest_values_of_interest[i] = -5.0; problem->largest_values_of_interest[i] = 5.0; problem->best_parameter[i] = 0.0; } /* Calculate best parameter value */ _bent_cigar_evaluate(problem, problem->best_parameter, problem->best_value); return problem; }
/** * @brief Allocates a problem using scalar values for smallest_value_of_interest, largest_value_of_interest * and best_parameter. */ static coco_problem_t *coco_problem_allocate_from_scalars(const char *problem_name, coco_evaluate_function_t evaluate_function, coco_problem_free_function_t problem_free_function, const size_t number_of_variables, const double smallest_value_of_interest, const double largest_value_of_interest, const double best_parameter) { size_t i; coco_problem_t *problem = coco_problem_allocate(number_of_variables, 1, 0); problem->problem_name = coco_strdup(problem_name); problem->number_of_variables = number_of_variables; problem->number_of_objectives = 1; problem->number_of_constraints = 0; problem->evaluate_function = evaluate_function; problem->problem_free_function = problem_free_function; for (i = 0; i < number_of_variables; ++i) { problem->smallest_values_of_interest[i] = smallest_value_of_interest; problem->largest_values_of_interest[i] = largest_value_of_interest; problem->best_parameter[i] = best_parameter; } return problem; }
static coco_problem_t *weierstrass_problem(const size_t number_of_variables) { size_t i, problem_id_length; coco_problem_t *problem = coco_allocate_problem(number_of_variables, 1, 0); _wss_problem_t *data; data = coco_allocate_memory(sizeof(*data)); data->f0 = 0.0; for (i = 0; i < WEIERSTRASS_SUMMANDS; ++i) { data->ak[i] = pow(0.5, (double)i); data->bk[i] = pow(3., (double)i); data->f0 += data->ak[i] * cos(2 * coco_pi * data->bk[i] * 0.5); } problem->problem_name = coco_strdup("weierstrass function"); /* Construct a meaningful problem id */ problem_id_length = snprintf(NULL, 0, "%s_%02i", "weierstrass", (int)number_of_variables); problem->problem_id = coco_allocate_memory(problem_id_length + 1); snprintf(problem->problem_id, problem_id_length + 1, "%s_%02d", "weierstrass", (int)number_of_variables); problem->number_of_variables = number_of_variables; problem->number_of_objectives = 1; problem->number_of_constraints = 0; problem->evaluate_function = _weierstrass_evaluate; problem->data = data; for (i = 0; i < number_of_variables; ++i) { problem->smallest_values_of_interest[i] = -5.0; problem->largest_values_of_interest[i] = 5.0; problem->best_parameter[i] = 0.0; } /* Calculate best parameter value */ _weierstrass_evaluate(problem, problem->best_parameter, problem->best_value); return problem; }
/** * @brief Initializes the indicator with name indicator_name. * * Opens files for writing and resets counters. */ static logger_biobj_indicator_t *logger_biobj_indicator(const logger_biobj_data_t *logger, const coco_problem_t *problem, const char *indicator_name) { coco_observer_t *observer; observer_biobj_data_t *observer_biobj; logger_biobj_indicator_t *indicator; char *prefix, *file_name, *path_name; int info_file_exists = 0; indicator = (logger_biobj_indicator_t *) coco_allocate_memory(sizeof(*indicator)); observer = logger->observer; observer_biobj = (observer_biobj_data_t *) observer->data; indicator->name = coco_strdup(indicator_name); indicator->best_value = suite_biobj_get_best_value(indicator->name, problem->problem_id); indicator->next_target_id = 0; indicator->target_hit = 0; indicator->current_value = 0; indicator->additional_penalty = 0; indicator->overall_value = 0; /* Prepare the info file */ path_name = coco_allocate_string(COCO_PATH_MAX); memcpy(path_name, observer->result_folder, strlen(observer->result_folder) + 1); coco_create_directory(path_name); file_name = coco_strdupf("%s_%s.info", problem->problem_type, indicator_name); coco_join_path(path_name, COCO_PATH_MAX, file_name, NULL); info_file_exists = coco_file_exists(path_name); indicator->info_file = fopen(path_name, "a"); if (indicator->info_file == NULL) { coco_error("logger_biobj_indicator() failed to open file '%s'.", path_name); return NULL; /* Never reached */ } coco_free_memory(file_name); coco_free_memory(path_name); /* Prepare the tdat file */ path_name = coco_allocate_string(COCO_PATH_MAX); memcpy(path_name, observer->result_folder, strlen(observer->result_folder) + 1); coco_join_path(path_name, COCO_PATH_MAX, problem->problem_type, NULL); coco_create_directory(path_name); prefix = coco_remove_from_string(problem->problem_id, "_i", "_d"); file_name = coco_strdupf("%s_%s.tdat", prefix, indicator_name); coco_join_path(path_name, COCO_PATH_MAX, file_name, NULL); indicator->tdat_file = fopen(path_name, "a"); if (indicator->tdat_file == NULL) { coco_error("logger_biobj_indicator() failed to open file '%s'.", path_name); return NULL; /* Never reached */ } coco_free_memory(file_name); coco_free_memory(path_name); /* Prepare the dat file */ path_name = coco_allocate_string(COCO_PATH_MAX); memcpy(path_name, observer->result_folder, strlen(observer->result_folder) + 1); coco_join_path(path_name, COCO_PATH_MAX, problem->problem_type, NULL); coco_create_directory(path_name); file_name = coco_strdupf("%s_%s.dat", prefix, indicator_name); coco_join_path(path_name, COCO_PATH_MAX, file_name, NULL); indicator->dat_file = fopen(path_name, "a"); if (indicator->dat_file == NULL) { coco_error("logger_biobj_indicator() failed to open file '%s'.", path_name); return NULL; /* Never reached */ } /* Output header information to the info file */ if (!info_file_exists) { /* Output algorithm name */ fprintf(indicator->info_file, "algorithm = '%s', indicator = '%s', folder = '%s'\n%% %s", observer->algorithm_name, indicator_name, problem->problem_type, observer->algorithm_info); } if (observer_biobj->previous_function != problem->suite_dep_function) { fprintf(indicator->info_file, "\nfunction = %2lu, ", problem->suite_dep_function); fprintf(indicator->info_file, "dim = %2lu, ", problem->number_of_variables); fprintf(indicator->info_file, "%s", file_name); } coco_free_memory(prefix); coco_free_memory(file_name); coco_free_memory(path_name); /* Output header information to the dat file */ fprintf(indicator->dat_file, "%%\n%% index = %ld, name = %s\n", problem->suite_dep_index, problem->problem_name); fprintf(indicator->dat_file, "%% instance = %ld, reference value = %.*e\n", problem->suite_dep_instance, logger->precision_f, indicator->best_value); fprintf(indicator->dat_file, "%% function evaluation | indicator value | target hit\n"); /* Output header information to the tdat file */ fprintf(indicator->tdat_file, "%%\n%% index = %ld, name = %s\n", problem->suite_dep_index, problem->problem_name); fprintf(indicator->tdat_file, "%% instance = %ld, reference value = %.*e\n", problem->suite_dep_instance, logger->precision_f, indicator->best_value); fprintf(indicator->tdat_file, "%% function evaluation | indicator value\n"); return indicator; }
/** * @brief Returns the numbers defined by the ranges. * * Reads ranges from a string of positive ranges separated by commas. For example: "-3,5-6,8-". Returns the * numbers that are defined by the ranges if min and max are used as their extremes. If the ranges with open * beginning/end are not allowed, use 0 as min/max. The returned string has an appended 0 to mark its end. * A maximum of max_count values is returned. If there is a problem with one of the ranges, the parsing stops * and the current result is returned. The memory of the returned object needs to be freed by the caller. */ static size_t *coco_string_parse_ranges(const char *string, const size_t min, const size_t max, const char *name, const size_t max_count) { char *ptr, *dash = NULL; char **ranges, **numbers; size_t i, j, count; size_t num[2]; size_t *result; size_t i_result = 0; char *str = coco_strdup(string); /* Check for empty string */ if ((str == NULL) || (strlen(str) == 0)) { coco_warning("coco_string_parse_ranges(): cannot parse empty ranges"); coco_free_memory(str); return NULL; } ptr = str; /* Check for disallowed characters */ while (*ptr != '\0') { if ((*ptr != '-') && (*ptr != ',') && !isdigit((unsigned char )*ptr)) { coco_warning("coco_string_parse_ranges(): problem parsing '%s' - cannot parse ranges with '%c'", str, *ptr); coco_free_memory(str); return NULL; } else ptr++; } /* Check for incorrect boundaries */ if ((max > 0) && (min > max)) { coco_warning("coco_string_parse_ranges(): incorrect boundaries"); coco_free_memory(str); return NULL; } result = coco_allocate_vector_size_t(max_count + 1); /* Split string to ranges w.r.t commas */ ranges = coco_string_split(str, ','); coco_free_memory(str); if (ranges) { /* Go over the current range */ for (i = 0; *(ranges + i); i++) { ptr = *(ranges + i); /* Count the number of '-' */ count = 0; while (*ptr != '\0') { if (*ptr == '-') { if (count == 0) /* Remember the position of the first '-' */ dash = ptr; count++; } ptr++; } /* Point again to the start of the range */ ptr = *(ranges + i); /* Check for incorrect number of '-' */ if (count > 1) { coco_warning("coco_string_parse_ranges(): problem parsing '%s' - too many '-'s", string); /* Cleanup */ for (j = i; *(ranges + j); j++) coco_free_memory(*(ranges + j)); coco_free_memory(ranges); if (i_result == 0) { coco_free_memory(result); return NULL; } result[i_result] = 0; return result; } else if (count == 0) { /* Range is in the format: n (no range) */ num[0] = (size_t) strtol(ptr, NULL, 10); num[1] = num[0]; } else { /* Range is in one of the following formats: n-m / -n / n- / - */ /* Split current range to numbers w.r.t '-' */ numbers = coco_string_split(ptr, '-'); j = 0; if (numbers) { /* Read the numbers */ for (j = 0; *(numbers + j); j++) { assert(j < 2); num[j] = (size_t) strtol(*(numbers + j), NULL, 10); coco_free_memory(*(numbers + j)); } } coco_free_memory(numbers); if (j == 0) { /* Range is in the format - (open ends) */ if ((min == 0) || (max == 0)) { coco_warning("coco_string_parse_ranges(): '%s' ranges cannot have an open ends; some ranges ignored", name); /* Cleanup */ for (j = i; *(ranges + j); j++) coco_free_memory(*(ranges + j)); coco_free_memory(ranges); if (i_result == 0) { coco_free_memory(result); return NULL; } result[i_result] = 0; return result; } num[0] = min; num[1] = max; } else if (j == 1) { if (dash - *(ranges + i) == 0) { /* Range is in the format -n */ if (min == 0) { coco_warning("coco_string_parse_ranges(): '%s' ranges cannot have an open beginning; some ranges ignored", name); /* Cleanup */ for (j = i; *(ranges + j); j++) coco_free_memory(*(ranges + j)); coco_free_memory(ranges); if (i_result == 0) { coco_free_memory(result); return NULL; } result[i_result] = 0; return result; } num[1] = num[0]; num[0] = min; } else { /* Range is in the format n- */ if (max == 0) { coco_warning("coco_string_parse_ranges(): '%s' ranges cannot have an open end; some ranges ignored", name); /* Cleanup */ for (j = i; *(ranges + j); j++) coco_free_memory(*(ranges + j)); coco_free_memory(ranges); if (i_result == 0) { coco_free_memory(result); return NULL; } result[i_result] = 0; return result; } num[1] = max; } } /* if (j == 2), range is in the format n-m and there is nothing to do */ } /* Make sure the boundaries are taken into account */ if ((min > 0) && (num[0] < min)) { num[0] = min; coco_warning("coco_string_parse_ranges(): '%s' ranges adjusted to be >= %lu", name, (unsigned long) min); } if ((max > 0) && (num[1] > max)) { num[1] = max; coco_warning("coco_string_parse_ranges(): '%s' ranges adjusted to be <= %lu", name, (unsigned long) max); } if (num[0] > num[1]) { coco_warning("coco_string_parse_ranges(): '%s' ranges not within boundaries; some ranges ignored", name); /* Cleanup */ for (j = i; *(ranges + j); j++) coco_free_memory(*(ranges + j)); coco_free_memory(ranges); if (i_result == 0) { coco_free_memory(result); return NULL; } result[i_result] = 0; return result; } /* Write in result */ for (j = num[0]; j <= num[1]; j++) { if (i_result > max_count - 1) break; result[i_result++] = j; } coco_free_memory(*(ranges + i)); *(ranges + i) = NULL; } } coco_free_memory(ranges); if (i_result == 0) { coco_free_memory(result); return NULL; } result[i_result] = 0; return result; }