commit c4f64cf2556c0f8597e1fbc19d7c664b8da94612
parent 4668156da5915c8d7a7b40edaf6617b004547bd7
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date: Fri, 11 Oct 2024 19:24:15 +0200
Added buffer sizes in API args
Diffstat:
9 files changed, 180 insertions(+), 93 deletions(-)
diff --git a/shell.c b/shell.c
@@ -9,9 +9,9 @@
#include "src/nissy.h"
-#define PRINTCUBE_BUFFER_SIZE 1024 /* Should be enough */
-#define SOLUTIONS_BUFFER_SIZE 500000 /* Should be enough */
-#define MAX_PATH_LENGTH 10000 /* Should be enough */
+#define PRINTCUBE_BUFFER_SIZE UINT64_C(1024)
+#define SOLUTIONS_BUFFER_SIZE UINT64_C(500000)
+#define MAX_PATH_LENGTH UINT64_C(10000)
#define FLAG_CUBE "-cube"
#define FLAG_PERM "-perm"
@@ -308,8 +308,8 @@ convert_exec(args_t *args)
char result[PRINTCUBE_BUFFER_SIZE];
int64_t ret;
- ret = nissy_convert(
- args->str_format_in, args->str_format_out, args->str_cube, result);
+ ret = nissy_convert(args->str_format_in, args->str_format_out,
+ args->str_cube, PRINTCUBE_BUFFER_SIZE, result);
if (ret == NISSY_OK || ret == NISSY_WARNING_UNSOLVABLE)
printf("%s\n", result);
@@ -382,7 +382,7 @@ gendata_exec(args_t *args)
buf = malloc(size);
- ret = nissy_gendata(args->str_solver, buf);
+ ret = nissy_gendata(args->str_solver, size, buf);
if (ret < 0) {
fprintf(stderr, "Unknown error in generating data\n");
fclose(file);
@@ -473,7 +473,8 @@ solve_exec(args_t *args)
ret = nissy_solve(
args->cube, args->str_solver, nissflag, args->minmoves,
- args->maxmoves, args->maxsolutions, args->optimal, buf, solutions);
+ args->maxmoves, args->maxsolutions, args->optimal,
+ size, buf, SOLUTIONS_BUFFER_SIZE, solutions);
free(buf);
diff --git a/src/nissy.c b/src/nissy.c
@@ -16,7 +16,7 @@ int parse_h48_solver(const char *, uint8_t [static 1], uint8_t [static 1]);
STATIC int64_t write_result(cube_t, char [static 22]);
STATIC bool distribution_equal(const uint64_t [static INFO_DISTRIBUTION_LEN],
const uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t);
-STATIC bool checkdata(const void *, const tableinfo_t *);
+STATIC bool checkdata(const char *, const tableinfo_t *);
#define GETCUBE_OPTIONS(S, F) { .option = S, .fix = F }
struct {
@@ -67,7 +67,7 @@ parse_h48_solver_error:
}
STATIC bool
-checkdata(const void *buf, const tableinfo_t *info)
+checkdata(const char *buf, const tableinfo_t *info)
{
uint64_t distr[INFO_DISTRIBUTION_LEN];
@@ -202,6 +202,12 @@ nissy_applymoves(
cube_t c, res;
int64_t err;
+ if (moves == NULL) {
+ LOG("Error: 'moves' argument is NULL\n");
+ err = NISSY_ERROR_NULL_POINTER;
+ goto nissy_applymoves_error;
+ }
+
c = readcube("B32", cube);
if (!isconsistent(c)) {
@@ -228,7 +234,7 @@ nissy_applymoves_error:
int64_t
nissy_applytrans(
const char cube[static 22],
- const char *transformation,
+ const char transformation[static 12],
char result[static 22]
)
{
@@ -267,6 +273,12 @@ nissy_frommoves(
cube_t res;
int64_t err;
+ if (moves == NULL) {
+ LOG("Error: 'moves' argument is NULL\n");
+ err = NISSY_ERROR_NULL_POINTER;
+ goto nissy_frommoves_error;
+ }
+
res = applymoves(SOLVED_CUBE, moves);
if (!isconsistent(res)) {
@@ -287,13 +299,32 @@ nissy_convert(
const char *format_in,
const char *format_out,
const char *cube_string,
- char *result
+ size_t result_size,
+ char result[result_size]
)
{
cube_t c;
int ret;
int64_t err;
+ if (format_in == NULL) {
+ LOG("Error: 'format_in' argument is NULL\n");
+ err = NISSY_ERROR_NULL_POINTER;
+ goto nissy_convert_error;
+ }
+
+ if (format_out == NULL) {
+ LOG("Error: 'format_out' argument is NULL\n");
+ err = NISSY_ERROR_NULL_POINTER;
+ goto nissy_convert_error;
+ }
+
+ if (cube_string == NULL) {
+ LOG("Error: 'cube_string' argument is NULL\n");
+ err = NISSY_ERROR_NULL_POINTER;
+ goto nissy_convert_error;
+ }
+
c = readcube(format_in, cube_string);
if (iserror(c)) {
@@ -334,6 +365,11 @@ nissy_getcube(
int i;
cube_t c;
+ if (options == NULL) {
+ LOG("Error: 'options' argument is NULL\n");
+ return NISSY_ERROR_NULL_POINTER;
+ }
+
for (i = 0; getcube_options[i].option != NULL; i++)
if (!strcmp(options, getcube_options[i].option))
getcube_options[i].fix(&ep, &eo, &cp, &co);
@@ -355,13 +391,19 @@ nissy_datasize(
const char *solver
)
{
+ if (solver == NULL) {
+ LOG("Error: 'solver' argument is NULL\n");
+ return NISSY_ERROR_NULL_POINTER;
+ }
+
/* gendata() handles a NULL *data as a "dryrun" request */
- return nissy_gendata(solver, NULL);
+ return nissy_gendata(solver, 0, NULL);
}
int64_t
nissy_datainfo(
- const void *data,
+ size_t data_size,
+ const char data[data_size],
void (*write)(const char *, ...)
)
{
@@ -396,7 +438,8 @@ nissy_datainfo(
}
if (info.next != 0)
- return nissy_datainfo((char *)data + info.next, write);
+ return nissy_datainfo(
+ data_size - info.next, (char *)data + info.next, write);
write("\n---------\n");
@@ -406,12 +449,18 @@ nissy_datainfo(
int64_t
nissy_gendata(
const char *solver,
- void *data
+ size_t data_size,
+ char data[data_size]
)
{
int p;
gendata_h48_arg_t arg;
+ if (solver == NULL) {
+ LOG("Error: 'solver' argument is NULL\n");
+ return NISSY_ERROR_NULL_POINTER;
+ }
+
arg.buf = data;
if (!strncmp(solver, "h48", 3)) {
p = parse_h48_solver(solver, &arg.h, &arg.k);
@@ -427,8 +476,8 @@ nissy_gendata(
int64_t
nissy_checkdata(
- const char *solver,
- const void *data
+ uint64_t data_size,
+ const char data[data_size]
)
{
char *buf;
@@ -454,16 +503,23 @@ nissy_solve(
uint8_t nissflag,
int8_t minmoves,
int8_t maxmoves,
- int64_t maxsolutions,
+ int64_t maxsols,
int8_t optimal,
- const void *data,
- char *solutions
+ size_t data_size,
+ const char data[data_size],
+ size_t sols_size,
+ char sols[sols_size]
)
{
cube_t c;
int p;
uint8_t h, k;
+ if (solver == NULL) {
+ LOG("Error: 'solver' argument is NULL\n");
+ return NISSY_ERROR_NULL_POINTER;
+ }
+
c = readcube_B32(cube);
if (!isconsistent(c)) {
@@ -486,24 +542,19 @@ nissy_solve(
maxmoves = 20;
}
- if (maxsolutions < 0) {
+ if (maxsols < 0) {
LOG("solve: 'maxsols' is negative, stopping\n");
return NISSY_ERROR_OPTIONS;
}
- if (maxsolutions == 0) {
+ if (maxsols == 0) {
LOG("solve: 'maxsols' is 0, returning no solution\n");
return 0;
}
- if (solutions == NULL) {
- LOG("solve: return parameter 'solutions' is NULL, stopping\n");
- return NISSY_ERROR_NULL_POINTER;
- }
-
if (!strncmp(solver, "h48", 3)) {
if (!strcmp(solver, "h48stats"))
- return solve_h48stats(c, maxmoves, data, solutions);
+ return solve_h48stats(c, maxmoves, data, sols);
p = parse_h48_solver(solver, &h, &k);
if (p != 0) {
@@ -512,13 +563,13 @@ nissy_solve(
} else {
return THREADS > 1 ?
solve_h48_multithread(c, minmoves,
- maxmoves, maxsolutions, data, solutions) :
+ maxmoves, maxsols, data, sols) :
solve_h48(c, minmoves,
- maxmoves, maxsolutions, data, solutions);
+ maxmoves, maxsols, data, sols);
}
} else if (!strcmp(solver, "simple")) {
return solve_simple(
- c, minmoves, maxmoves, maxsolutions, optimal, solutions);
+ c, minmoves, maxmoves, maxsols, optimal, sols);
} else {
LOG("solve: unknown solver '%s'\n", solver);
return NISSY_ERROR_INVALID_SOLVER;
diff --git a/src/nissy.h b/src/nissy.h
@@ -98,7 +98,7 @@ Apply the given sequence of moves on the given cube.
Parameters:
cube - The cube to move, in B32 format.
- moves - The moves to apply to the cube.
+ moves - The moves to apply to the cube. Must be a NULL-terminated string.
result - The return parameter for the resulting cube, in B32 format.
Return values:
@@ -108,6 +108,7 @@ Return values:
or due to an unknown internal error.
NISSY_ERROR_INVALID_CUBE - The given cube is invalid.
NISSY_ERROR_INVALID_MOVES - The given moves are invalid.
+ NISSY_ERROR_NULL_POINTER - The 'moves' argument is NULL.
*/
int64_t nissy_applymoves(
const char cube[static 22],
@@ -132,7 +133,7 @@ Return values:
*/
int64_t nissy_applytrans(
const char cube[static 22],
- const char *transformation,
+ const char transformation[static 12],
char result[static 22]
);
@@ -140,7 +141,8 @@ int64_t nissy_applytrans(
Apply the given moves to the solved cube.
Parameters:
- moves - The moves to be applied to the solved cube.
+ moves - The moves to be applied to the solved cube. Must be a
+ NULL-terminated string.
result - Return parameter for the resulting cube, in B32 format.
Return values:
@@ -148,6 +150,7 @@ Return values:
NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is
probably due to an unknown internal error.
NISSY_ERROR_INVALID_MOVES - The given moves are invalid.
+ NISSY_ERROR_NULL_POINTER - The 'moves' argument is NULL.
*/
int64_t nissy_frommoves(
const char *moves,
@@ -158,23 +161,26 @@ int64_t nissy_frommoves(
Convert the given cube between the two given formats.
Parameters:
- format_in - The input format.
- format_out - The output format.
- string - The cube, in format_in format.
- result - Return parameter for the cube in format_out format. Must be
- large enough to contains the cube in this format.
+ format_in - The input format.
+ format_out - The output format.
+ cube_string - The cube, in format_in format.
+ retult_size - The allocated size of the result array.
+ result - Return parameter for the cube in format_out format.
Return values:
NISSY_OK - The conversion was performed succesfully.
NISSY_ERROR_INVALID_CUBE - The given cube is invalid.
NISSY_ERROR_INVALID_FORMAT - At least one of the given formats is invalid.
NISSY_ERROR_UNKNOWN - An unknown error occurred.
+ NISSY_ERROR_NULL_POINTER - At least one of 'format_in', 'format_out' or
+ 'cube_string' arguments is NULL.
*/
int64_t nissy_convert(
const char *format_in,
const char *format_out,
- const char *cube,
- char *result
+ const char *cube_string,
+ uint64_t result_size,
+ char result[result_size]
);
/*
@@ -214,6 +220,7 @@ Parameters:
Return values:
NISSY_ERROR_INVALID_SOLVER - The given solver is not known.
+ NISSY_ERROR_NULL_POINTER - The 'solver' argument is null.
NISSY_ERROR_UNKNOWN - An unknown error occurred.
Any value >= 0 - The size of the data, in bytes.
*/
@@ -225,55 +232,75 @@ int64_t nissy_datasize(
Compute the data for the given solver and store it in generated_data.
Parameters:
- solver - The name of the solver.
- data - The return parameter for the generated data. Must be large enoguh
- to contain the whole data. It is advised to use nissy_datasize to
- check how much memory is needed.
+ solver - The name of the solver.
+ data_size - The size of the data buffer. It is advised to use nissy_datasize
+ to check how much memory is needed.
+ data - The return parameter for the generated data.
Return values:
NISSY_ERROR_INVALID_SOLVER - The given solver is not known.
+ NISSY_ERROR_NULL_POINTER - The 'solver' argument is null.
NISSY_ERROR_UNKNOWN - An error occurred while generating the data.
Any value >= 0 - The size of the data, in bytes.
*/
int64_t nissy_gendata(
const char *solver,
- void *data
+ uint64_t data_size,
+ char data[data_size]
);
/*
Print information on a data table via the provided callback writer.
Parameters:
- data - The data
- write - A callback writer with the same signature as printf(3).
+ data_size - The size of the data buffer.
+ data - The data to be read.
+ write - A callback writer with the same signature as printf(3).
Return values:
NISSY_OK - The data is correct.
NISSY_ERROR_DATA - The data contains errors.
*/
int64_t nissy_datainfo(
- const void *data,
+ uint64_t data_size,
+ const char data[data_size],
void (*write)(const char *, ...)
);
/*
+Check that the data is a valid data table for a solver.
+
+Parameters:
+ data_size - The size of the data buffer.
+ data - The data for the solver. Can be computed with gendata.
+
+Return values:
+ NISSY_OK - The data is valid.
+ NISSY_ERROR_DATA - The data is invalid.
+*/
+int64_t nissy_checkdata(
+ uint64_t data_size,
+ const char data[data_size]
+);
+
+/*
Solve the given cube using the given solver and options.
Parameters:
- cube - The cube to solver, in B32 format.
- solver - The name of the solver.
- nissflag - The flags for NISS (linear, inverse, mixed, or combinations).
- minmoves - The minimum number of moves for a solution.
- maxmoves - The maximum number of moves for a solution.
- maxsolutions - The maximum number of solutions.
- optimal - If set to a non-negative value, the maximum number of moves
- above the optimal solution length.
- data - The data for the solver. Can be computed with gendata.
- solutions - The return parameter for the solutions. Must be large enough
- to store all found solutions. The solutions are separated by
- a '\n' (newline) and a '\0' (NULL character) terminates the
- list.
- TODO: replace with callback writer.
+ cube - The cube to solver, in B32 format.
+ solver - The name of the solver.
+ nissflag - The flags for NISS (linear, inverse, mixed, or combinations).
+ minmoves - The minimum number of moves for a solution.
+ maxmoves - The maximum number of moves for a solution.
+ maxsols - The maximum number of solutions.
+ optimal - If set to a non-negative value, the maximum number of moves
+ above the optimal solution length.
+ data_size - The size of the data buffer.
+ data - The data for the solver. Can be computed with gendata.
+ sols_size - The size of the solutions buffer.
+ sols - The return parameter for the solutions. The solutions are
+ separated by a '\n' (newline) and a '\0' (NULL character)
+ terminates the list.
Return values:
NISSY_OK - Cube solved succesfully.
@@ -281,8 +308,8 @@ Return values:
NISSY_ERROR_UNSOLVABLE_CUBE - The given cube is valid, but not solvable with
the given solver.
NISSY_ERROR_OPTIONS - One or more of the given options are invalid.
- NISSY_ERROR_NULL_POINTER - One of the provided pointers is null.
NISSY_ERROR_INVALID_SOLVER - The given solver is not known.
+ NISSY_ERROR_NULL_POINTER - The 'solver' argument is null.
Any value >= 0 - The number of solutions found.
*/
int64_t nissy_solve(
@@ -293,8 +320,10 @@ int64_t nissy_solve(
int8_t maxmoves,
int64_t maxsolutions,
int8_t optimal,
- const void *data,
- char *solutions
+ uint64_t data_size,
+ const char data[data_size],
+ uint64_t sols_size,
+ char sols[sols_size]
);
/*
diff --git a/tools/000_gendata/gendata.c b/tools/000_gendata/gendata.c
@@ -17,8 +17,8 @@ run(void) {
case -2:
goto gendata_run_finish;
default:
- nissy_datainfo(buf, write_stdout);
- consistent = nissy_checkdata(solver, buf) == 0;
+ nissy_datainfo(size, buf, write_stdout);
+ consistent = nissy_checkdata(size, buf) == 0;
expected = check_distribution(solver, buf);
if (consistent && expected) {
printf("\n");
@@ -42,7 +42,7 @@ int main(int argc, char **argv) {
uint8_t h, k;
if (argc < 2) {
- fprintf(stderr, "Error: not enough arguments. "
+ printf("Error: not enough arguments. "
"A solver must be given.\n");
return 1;
}
diff --git a/tools/001_derive_h48/derive_h48.c b/tools/001_derive_h48/derive_h48.c
@@ -19,8 +19,7 @@ void run(void) {
int main(int argc, char **argv) {
if (argc < 5) {
- fprintf(stderr,
- "Error: not enough arguments. Required:\n"
+ printf("Error: not enough arguments. Required:\n"
"1. Solver name for large table\n"
"2. Solver name for derived table\n"
"3. Filename containing large table\n"
diff --git a/tools/100_checkdata/checkdata.c b/tools/100_checkdata/checkdata.c
@@ -12,19 +12,19 @@ run(void) {
size = nissy_datasize(solver);
if (size <= 0) {
- fprintf(stderr, "Error in datasize\n");
+ printf("Error in datasize\n");
return;
}
if ((f = fopen(filename, "rb")) == NULL) {
- fprintf(stderr, "Error reading file %s\n", filename);
+ printf("Error reading file %s\n", filename);
return;
}
buf = malloc(size);
fread(buf, size, 1, f);
fclose(f);
- result = nissy_checkdata(solver, buf);
+ result = nissy_checkdata(size, buf);
free(buf);
printf("checkdata %s\n", result == 0 ? "succeeded" : "failed");
@@ -34,7 +34,7 @@ run(void) {
int main(int argc, char **argv) {
if (argc < 3) {
- fprintf(stderr, "Error: not enough arguments. "
+ printf("Error: not enough arguments. "
"A solver and a file name must be given.\n");
return 1;
}
diff --git a/tools/200_stats_tables_h48/stats_tables_h48.c b/tools/200_stats_tables_h48/stats_tables_h48.c
@@ -6,6 +6,7 @@
#define LOG_EVERY (NCUBES_PER_THREAD / 10)
int NCUBES_PER_THREAD;
+int64_t size = 0;
const char *solver = "h48stats";
const char *filename = "tables/h48h0k4";
char *buf;
@@ -40,11 +41,12 @@ run_thread(void *arg)
cp = rand64();
co = rand64();
nissy_getcube(ep, eo, cp, co, "fix", cube);
- nissy_solve(cube, "h48stats", "", 0, MAXMOVES, 1, -1, buf, s);
+ nissy_solve(cube, "h48stats", NISSY_NISSFLAG_NORMAL,
+ 0, MAXMOVES, 1, -1, size, buf, 12, s);
for (j = 0; j < 12; j++)
a->v[j][(int)s[j]]++;
if ((i+1) % LOG_EVERY == 0)
- fprintf(stderr, "[thread %d] %d cubes solved...\n",
+ printf("[thread %d] %d cubes solved...\n",
a->thread_id, i+1);
}
@@ -57,6 +59,8 @@ void run(void) {
pthread_t thread[THREADS];
thread_arg_t arg[THREADS];
+ size = nissy_datasize(solver);
+
for (i = 0; i < THREADS; i++) {
arg[i] = (thread_arg_t) {
.thread_id = i,
@@ -88,7 +92,7 @@ int main(int argc, char **argv) {
nissy_setlogger(log_stderr);
if (argc < 2) {
- fprintf(stderr, "Error: not enough arguments. "
+ printf("Error: not enough arguments. "
"Number of cubes per thread must be provided.\n");
return 1;
}
@@ -96,7 +100,7 @@ int main(int argc, char **argv) {
NCUBES_PER_THREAD = atoi(argv[1]);
if (NCUBES_PER_THREAD < 1 || NCUBES_PER_THREAD > 1000000) {
- fprintf(stderr, "Invalid number of cubes: must be > 0 and "
+ printf("Invalid number of cubes: must be > 0 and "
"< 1000000, but %d was given.\n", NCUBES_PER_THREAD);
return 1;
}
diff --git a/tools/300_solve_small/solve_small.c b/tools/300_solve_small/solve_small.c
@@ -1,6 +1,9 @@
#include "../tool.h"
+#define SOL_BUFFER_LEN 1000
+
const char *solver = "h48h0k4";
+int64_t size = 0;
char *buf;
char *scrambles[] = {
@@ -14,25 +17,22 @@ char *scrambles[] = {
void run(void) {
int i;
int64_t n;
- char sol[100], cube[22];
+ char sol[SOL_BUFFER_LEN], cube[22];
printf("Solved the following scrambles:\n\n");
for (i = 0; scrambles[i] != NULL; i++) {
printf("%d. %s\n", i+1, scrambles[i]);
- fprintf(stderr, "Solving scramble %s\n", scrambles[i]);
+ printf("Solving scramble %s\n", scrambles[i]);
if (nissy_frommoves(scrambles[i], cube) == -1) {
- fprintf(stderr, "Invalid scramble\n");
- printf("Invalid\n");
+ printf("Invalid scramble\n");
continue;
}
- n = nissy_solve(
- cube, solver, "", 0, 20, 1, -1, buf, sol);
- if (n == 0) {
- printf("No solution\n");
- fprintf(stderr, "No solution found\n");
- } else {
+ n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL,
+ 0, 20, 1, -1, size, buf, SOL_BUFFER_LEN, sol);
+ if (n == 0)
+ printf("No solution found\n");
+ else
printf("Solutions:\n%s\n", sol);
- }
}
}
@@ -46,6 +46,8 @@ int main(void) {
if (getdata(solver, &buf, filename) != 0)
return 1;
+ size = nissy_datasize(solver);
+
timerun(run);
free(buf);
diff --git a/tools/tool.h b/tools/tool.h
@@ -96,7 +96,7 @@ generatetable(const char *solver, char **buf)
}
*buf = malloc(size);
- gensize = nissy_gendata(solver, *buf);
+ gensize = nissy_gendata(solver, size, *buf);
if (gensize != size) {
printf("Error generating table");
@@ -212,7 +212,7 @@ gendata_run(
case -2:
goto gendata_run_finish;
default:
- nissy_datainfo(buf, write_stdout);
+ nissy_datainfo(size, buf, write_stdout);
printf("\n");
printf("Succesfully generated %" PRId64 " bytes. "
"See above for details on the tables.\n", size);
@@ -237,6 +237,7 @@ derivedata_run(
int64_t size;
char *buf;
+ buf = NULL;
size = derivetable(solver_large, solver_small, filename_large, &buf);
switch (size) {
case -1:
@@ -244,7 +245,7 @@ derivedata_run(
case -2:
goto derivedata_run_finish;
default:
- nissy_datainfo(buf, write_stdout);
+ nissy_datainfo(size, buf, write_stdout);
printf("\n");
printf("Succesfully generated %" PRId64 " bytes. "
"See above for details on the tables.\n", size);