diff options
| -rw-r--r-- | README.md | 10 | ||||
| -rw-r--r-- | python/example.py | 37 | ||||
| -rw-r--r-- | python/nissy_module.c | 258 | ||||
| -rw-r--r-- | src/nissy.c | 13 | ||||
| -rw-r--r-- | src/solvers/tables.h | 3 |
5 files changed, 304 insertions, 17 deletions
| @@ -182,8 +182,14 @@ From here you can call the library functions directly, for example: | |||
| 182 | 'ASTUGFBH=DACXEZGBLIKF' | 182 | 'ASTUGFBH=DACXEZGBLIKF' |
| 183 | ``` | 183 | ``` |
| 184 | 184 | ||
| 185 | Please note: as this is work in progress, not all functions are currently | 185 | Some methods have a different signature in the Pythn module than in |
| 186 | available from the Python module. | 186 | libnissy: for example `solve()` returns the solutions as a list of |
| 187 | strings instead of writing them to a return parameter buffer. | ||
| 188 | You can access the documentation for the Python module from within | ||
| 189 | a Python interpreter with `help(nissy)`. Cross-check this documentation | ||
| 190 | with the comments in nissy.h for more details. | ||
| 191 | |||
| 192 | Please note: the support for the Python module is still rudimentary. | ||
| 187 | 193 | ||
| 188 | ## Cube formats | 194 | ## Cube formats |
| 189 | 195 | ||
diff --git a/python/example.py b/python/example.py new file mode 100644 index 0000000..fdea2d4 --- /dev/null +++ b/python/example.py | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | # Small example of nissy_python_module usage | ||
| 2 | |||
| 3 | # Compile the python module with "make python", then run this from the main | ||
| 4 | # folder containing nissy_python_module.so | ||
| 5 | |||
| 6 | # Append the main folder to the python path so we can load the module | ||
| 7 | from sys import path | ||
| 8 | path.append("./") | ||
| 9 | |||
| 10 | # Import with a nicer name | ||
| 11 | import nissy_python_module as nissy | ||
| 12 | |||
| 13 | # Choose the solver you prefer | ||
| 14 | solver = "h48h0k4" | ||
| 15 | |||
| 16 | # Load the pruning table from file | ||
| 17 | data = bytearray(open("tables/" + solver, "rb").read()) | ||
| 18 | |||
| 19 | # If you have not generated the table yet, you can do so: | ||
| 20 | # data = nissy.gendata("h48h0k4") | ||
| 21 | |||
| 22 | # Get a scrambled cube | ||
| 23 | cube = nissy.applymoves(nissy.solved_cube, "U F R2"); | ||
| 24 | |||
| 25 | # Solve! | ||
| 26 | solutions = nissy.solve(cube, solver, nissy.nissflag_normal, 0, 9, 3, -1, data) | ||
| 27 | |||
| 28 | # Print the solutions, one per line | ||
| 29 | print("Found ", len(solutions), " solutions:") | ||
| 30 | for s in solutions: | ||
| 31 | print(s) | ||
| 32 | |||
| 33 | # You can use help(nissy) for more info about the available methods: | ||
| 34 | # help(nissy) | ||
| 35 | |||
| 36 | # Or help(nissy.methodname) if you want to know more about a specific method: | ||
| 37 | # help(nissy.solve) | ||
diff --git a/python/nissy_module.c b/python/nissy_module.c index d02d9fc..2357b90 100644 --- a/python/nissy_module.c +++ b/python/nissy_module.c | |||
| @@ -5,12 +5,17 @@ | |||
| 5 | #include "../src/nissy.h" | 5 | #include "../src/nissy.h" |
| 6 | 6 | ||
| 7 | #define MAX_CUBE_STR_LEN 1024 /* Update when adding formats */ | 7 | #define MAX_CUBE_STR_LEN 1024 /* Update when adding formats */ |
| 8 | #define MAX_SOLUTIONS_SIZE 250000 | ||
| 8 | 9 | ||
| 9 | static bool | 10 | static bool |
| 10 | check_error(long long err) | 11 | check_error(long long err) |
| 11 | { | 12 | { |
| 12 | char err_string[255]; | 13 | char err_string[255]; |
| 13 | 14 | ||
| 15 | /* A positive value always denotes a success */ | ||
| 16 | if (err > 0) | ||
| 17 | return true; | ||
| 18 | |||
| 14 | switch (err) { | 19 | switch (err) { |
| 15 | case NISSY_OK: /* Fallthrough */ | 20 | case NISSY_OK: /* Fallthrough */ |
| 16 | case NISSY_WARNING_UNSOLVABLE: | 21 | case NISSY_WARNING_UNSOLVABLE: |
| @@ -58,6 +63,18 @@ long_result(long long result) | |||
| 58 | return PyLong_FromLong(result); | 63 | return PyLong_FromLong(result); |
| 59 | } | 64 | } |
| 60 | 65 | ||
| 66 | |||
| 67 | PyDoc_STRVAR(compose_doc, | ||
| 68 | "compose(cube, permutation)\n" | ||
| 69 | "--\n\n" | ||
| 70 | "Apply 'permutation' on 'cube'.\n" | ||
| 71 | "\n" | ||
| 72 | "Parameters:\n" | ||
| 73 | " - cube: a cube in B32 format\n" | ||
| 74 | " - permutation: another cube in B32 format\n" | ||
| 75 | "\n" | ||
| 76 | "Returns: the resulting cube string in B32 format\n" | ||
| 77 | ); | ||
| 61 | static PyObject * | 78 | static PyObject * |
| 62 | compose(PyObject *self, PyObject *args) | 79 | compose(PyObject *self, PyObject *args) |
| 63 | { | 80 | { |
| @@ -72,6 +89,16 @@ compose(PyObject *self, PyObject *args) | |||
| 72 | return string_result(err, result); | 89 | return string_result(err, result); |
| 73 | } | 90 | } |
| 74 | 91 | ||
| 92 | PyDoc_STRVAR(inverse_doc, | ||
| 93 | "inverse(cube)\n" | ||
| 94 | "--\n\n" | ||
| 95 | "Invert 'cube'.\n" | ||
| 96 | "\n" | ||
| 97 | "Parameters:\n" | ||
| 98 | " - cube: a cube in B32 format\n" | ||
| 99 | "\n" | ||
| 100 | "Returns: the inverse cube in B32 format\n" | ||
| 101 | ); | ||
| 75 | static PyObject * | 102 | static PyObject * |
| 76 | inverse(PyObject *self, PyObject *args) | 103 | inverse(PyObject *self, PyObject *args) |
| 77 | { | 104 | { |
| @@ -86,6 +113,17 @@ inverse(PyObject *self, PyObject *args) | |||
| 86 | return string_result(err, result); | 113 | return string_result(err, result); |
| 87 | } | 114 | } |
| 88 | 115 | ||
| 116 | PyDoc_STRVAR(applymoves_doc, | ||
| 117 | "applymoves(cube, moves)\n" | ||
| 118 | "--\n\n" | ||
| 119 | "Apply 'moves' to 'cube'.\n" | ||
| 120 | "\n" | ||
| 121 | "Parameters:\n" | ||
| 122 | " - cube: a cube in B32 format\n" | ||
| 123 | " - moves: the moves to apply on the cube\n" | ||
| 124 | "\n" | ||
| 125 | "Returns: the resulting cube in B32 format\n" | ||
| 126 | ); | ||
| 89 | static PyObject * | 127 | static PyObject * |
| 90 | applymoves(PyObject *self, PyObject *args) | 128 | applymoves(PyObject *self, PyObject *args) |
| 91 | { | 129 | { |
| @@ -100,6 +138,19 @@ applymoves(PyObject *self, PyObject *args) | |||
| 100 | return string_result(err, result); | 138 | return string_result(err, result); |
| 101 | } | 139 | } |
| 102 | 140 | ||
| 141 | PyDoc_STRVAR(applytrans_doc, | ||
| 142 | "applytrans(cube, transformation)\n" | ||
| 143 | "--\n\n" | ||
| 144 | "Apply 'transformation' to 'cube'.\n" | ||
| 145 | "\n" | ||
| 146 | "Parameters:\n" | ||
| 147 | " - cube: a cube in B32 format\n" | ||
| 148 | " - transformation: the transformation to apply on the cube, formatted as\n" | ||
| 149 | " (rotation|mirrored) (2 letters)\n" | ||
| 150 | " for example 'mirrored ur' or 'rotation lf'\n" | ||
| 151 | "\n" | ||
| 152 | "Returns: the resulting cube in B32 format\n" | ||
| 153 | ); | ||
| 103 | static PyObject * | 154 | static PyObject * |
| 104 | applytrans(PyObject *self, PyObject *args) | 155 | applytrans(PyObject *self, PyObject *args) |
| 105 | { | 156 | { |
| @@ -114,6 +165,18 @@ applytrans(PyObject *self, PyObject *args) | |||
| 114 | return string_result(err, result); | 165 | return string_result(err, result); |
| 115 | } | 166 | } |
| 116 | 167 | ||
| 168 | PyDoc_STRVAR(convert_doc, | ||
| 169 | "convert(fin, fout, cube)\n" | ||
| 170 | "--\n\n" | ||
| 171 | "Convert 'cube' from format 'fin' to format 'fout'.\n" | ||
| 172 | "\n" | ||
| 173 | "Parameters:\n" | ||
| 174 | " - fin: the format in which 'cube' is given\n" | ||
| 175 | " - fout: the format to which 'cube' has to be converted\n" | ||
| 176 | " - cube: a cube in B32 format\n" | ||
| 177 | "\n" | ||
| 178 | "Returns: 'cube' in 'fout' format\n" | ||
| 179 | ); | ||
| 117 | static PyObject * | 180 | static PyObject * |
| 118 | convert(PyObject *self, PyObject *args) | 181 | convert(PyObject *self, PyObject *args) |
| 119 | { | 182 | { |
| @@ -128,6 +191,20 @@ convert(PyObject *self, PyObject *args) | |||
| 128 | return string_result(err, result); | 191 | return string_result(err, result); |
| 129 | } | 192 | } |
| 130 | 193 | ||
| 194 | PyDoc_STRVAR(getcube_doc, | ||
| 195 | "getcube(ep, eo, cp, co, options)\n" | ||
| 196 | "--\n\n" | ||
| 197 | "Constructs the cube from the given coordinates and options\n" | ||
| 198 | "\n" | ||
| 199 | "Parameters:\n" | ||
| 200 | " - ep: the edge permutation coordinate\n" | ||
| 201 | " - eo: the edge orientation coordinate\n" | ||
| 202 | " - cp: the corner permutation coordinate\n" | ||
| 203 | " - co: the corner orientation coordinate\n" | ||
| 204 | " - options: a string, for example \"fix\"\n" | ||
| 205 | "\n" | ||
| 206 | "Returns: the cube constructed from the given coordinates\n" | ||
| 207 | ); | ||
| 131 | static PyObject * | 208 | static PyObject * |
| 132 | getcube(PyObject *self, PyObject *args) | 209 | getcube(PyObject *self, PyObject *args) |
| 133 | { | 210 | { |
| @@ -142,6 +219,16 @@ getcube(PyObject *self, PyObject *args) | |||
| 142 | return string_result(err, result); | 219 | return string_result(err, result); |
| 143 | } | 220 | } |
| 144 | 221 | ||
| 222 | PyDoc_STRVAR(datasize_doc, | ||
| 223 | "datasize(solver)\n" | ||
| 224 | "--\n\n" | ||
| 225 | "Returns the size of the data (pruning table) for the given solver\n" | ||
| 226 | "\n" | ||
| 227 | "Parameters:\n" | ||
| 228 | " - solver: the name of the solver\n" | ||
| 229 | "\n" | ||
| 230 | "Returns: the size of the data for the solver, in bytes\n" | ||
| 231 | ); | ||
| 145 | static PyObject * | 232 | static PyObject * |
| 146 | datasize(PyObject *self, PyObject *args) | 233 | datasize(PyObject *self, PyObject *args) |
| 147 | { | 234 | { |
| @@ -155,23 +242,168 @@ datasize(PyObject *self, PyObject *args) | |||
| 155 | return long_result(result); | 242 | return long_result(result); |
| 156 | } | 243 | } |
| 157 | 244 | ||
| 158 | /* TODO: gendata, checkdata and solve and countmoves */ | 245 | PyDoc_STRVAR(gendata_doc, |
| 246 | "gendata(solver)\n" | ||
| 247 | "--\n\n" | ||
| 248 | "Generates the data (pruning table) for the given solver\n" | ||
| 249 | "\n" | ||
| 250 | "Parameters:\n" | ||
| 251 | " - solver: the name of the solver\n" | ||
| 252 | "\n" | ||
| 253 | "Returns: a bytearray containing the data for the solver\n" | ||
| 254 | ); | ||
| 255 | static PyObject * | ||
| 256 | gendata(PyObject *self, PyObject *args) | ||
| 257 | { | ||
| 258 | long long size, err; | ||
| 259 | const char *solver; | ||
| 260 | char *buf; | ||
| 261 | |||
| 262 | if (!PyArg_ParseTuple(args, "s", &solver)) | ||
| 263 | return NULL; | ||
| 264 | |||
| 265 | size = nissy_datasize(solver); | ||
| 266 | if (!check_error(size)) | ||
| 267 | return NULL; | ||
| 268 | |||
| 269 | buf = PyMem_Malloc(size); | ||
| 270 | |||
| 271 | Py_BEGIN_ALLOW_THREADS | ||
| 272 | err = nissy_gendata(solver, size, buf); | ||
| 273 | Py_END_ALLOW_THREADS | ||
| 274 | |||
| 275 | if (check_error(err)) | ||
| 276 | return PyByteArray_FromStringAndSize(buf, size); | ||
| 277 | else | ||
| 278 | return NULL; | ||
| 279 | } | ||
| 280 | |||
| 281 | PyDoc_STRVAR(checkdata_doc, | ||
| 282 | "checkdata(data)\n" | ||
| 283 | "--\n\n" | ||
| 284 | "Checks if the data (pruning table) given is valid or not\n" | ||
| 285 | "\n" | ||
| 286 | "Parameters:\n" | ||
| 287 | " - data: a bytearray containing the data for a solver" | ||
| 288 | "\n" | ||
| 289 | "Returns: true if the data is valid, false otherwise\n" | ||
| 290 | ); | ||
| 291 | PyObject * | ||
| 292 | checkdata(PyObject *self, PyObject *args) | ||
| 293 | { | ||
| 294 | long long result; | ||
| 295 | PyByteArrayObject *data; | ||
| 296 | |||
| 297 | if (!PyArg_ParseTuple(args, "Y", &data)) | ||
| 298 | return NULL; | ||
| 299 | |||
| 300 | result = nissy_checkdata(data->ob_alloc, data->ob_bytes); | ||
| 301 | |||
| 302 | if (check_error(result)) | ||
| 303 | return Py_True; | ||
| 304 | else | ||
| 305 | return Py_False; | ||
| 306 | } | ||
| 307 | |||
| 308 | PyDoc_STRVAR(solve_doc, | ||
| 309 | "solve(cube, solver, nissflag, minmoves, maxmoves, maxsolutions, optimal, data)\n" | ||
| 310 | "--\n\n" | ||
| 311 | "Solves the given 'cube' with the given 'solver' and other parameters." | ||
| 312 | "See the documentation for libnissy (in nissy.h) for details.\n" | ||
| 313 | "\n" | ||
| 314 | "Parameters:\n" | ||
| 315 | " - cube: a cube in B32 format\n" | ||
| 316 | " - solver: the solver to use\n" | ||
| 317 | " - minmoves: the minimum number of moves to use\n" | ||
| 318 | " - maxmoves: the maximum number of moves to use\n" | ||
| 319 | " - maxsolution: the maximum number of solutions to return\n" | ||
| 320 | " - optimal: the largest number of moves from the shortest solution" | ||
| 321 | "(set to -1 to ignore)\n" | ||
| 322 | " - data: a bytearray containing the data for the solver\n" | ||
| 323 | "\n" | ||
| 324 | "Returns: a list with the solutions found\n" | ||
| 325 | ); | ||
| 326 | PyObject * | ||
| 327 | solve(PyObject *self, PyObject *args) | ||
| 328 | { | ||
| 329 | long long result; | ||
| 330 | unsigned nissflag, minmoves, maxmoves, maxsolutions; | ||
| 331 | int optimal, i, j, k; | ||
| 332 | const char *cube, *solver; | ||
| 333 | char solutions[MAX_SOLUTIONS_SIZE]; | ||
| 334 | long long stats[NISSY_SIZE_SOLVE_STATS]; | ||
| 335 | PyByteArrayObject *data; | ||
| 336 | PyObject *list, *item; | ||
| 337 | |||
| 338 | if (!PyArg_ParseTuple(args, "ssIIIIiY", &cube, &solver, &nissflag, | ||
| 339 | &minmoves, &maxmoves, &maxsolutions, &optimal, &data)) | ||
| 340 | return NULL; | ||
| 341 | |||
| 342 | Py_BEGIN_ALLOW_THREADS | ||
| 343 | result = nissy_solve(cube, solver, nissflag, minmoves, maxmoves, | ||
| 344 | maxsolutions, optimal, data->ob_alloc, data->ob_bytes, | ||
| 345 | MAX_SOLUTIONS_SIZE, solutions, stats); | ||
| 346 | Py_END_ALLOW_THREADS | ||
| 347 | |||
| 348 | if(!check_error(result)) { | ||
| 349 | return NULL; | ||
| 350 | } else { | ||
| 351 | list = PyList_New(result); | ||
| 352 | for (i = 0, j = 0, k = 0; solutions[i] != 0; i++) { | ||
| 353 | if (solutions[i] != '\n') | ||
| 354 | continue; | ||
| 355 | solutions[i] = 0; | ||
| 356 | item = PyUnicode_FromString(&solutions[k]); | ||
| 357 | PyList_SetItem(list, j, item); | ||
| 358 | j++; | ||
| 359 | k = i+1; | ||
| 360 | } | ||
| 361 | return list; | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | PyDoc_STRVAR(countmoves_doc, | ||
| 366 | "countmoves(moves)\n" | ||
| 367 | "--\n\n" | ||
| 368 | "Count the moves\n" | ||
| 369 | "\n" | ||
| 370 | "Parameters:\n" | ||
| 371 | " - moves: the moves to be counted\n" | ||
| 372 | "\n" | ||
| 373 | "Returns: the number of moves in HTM metric\n" | ||
| 374 | ); | ||
| 375 | PyObject * | ||
| 376 | countmoves(PyObject *self, PyObject *args) | ||
| 377 | { | ||
| 378 | long long count; | ||
| 379 | const char *moves; | ||
| 380 | |||
| 381 | if (!PyArg_ParseTuple(args, "s", &moves)) | ||
| 382 | return NULL; | ||
| 383 | |||
| 384 | count = nissy_countmoves(moves); | ||
| 385 | return long_result(count); | ||
| 386 | } | ||
| 159 | 387 | ||
| 160 | static PyMethodDef nissy_methods[] = { | 388 | static PyMethodDef nissy_methods[] = { |
| 161 | { "compose", compose, METH_VARARGS, NULL }, | 389 | { "compose", compose, METH_VARARGS, compose_doc }, |
| 162 | { "inverse", inverse, METH_VARARGS, NULL }, | 390 | { "inverse", inverse, METH_VARARGS, inverse_doc }, |
| 163 | { "applymoves", applymoves, METH_VARARGS, NULL }, | 391 | { "applymoves", applymoves, METH_VARARGS, applymoves_doc }, |
| 164 | { "applytrans", applytrans, METH_VARARGS, NULL }, | 392 | { "applytrans", applytrans, METH_VARARGS, applytrans_doc }, |
| 165 | { "convert", convert, METH_VARARGS, NULL }, | 393 | { "convert", convert, METH_VARARGS, convert_doc }, |
| 166 | { "getcube", getcube, METH_VARARGS, NULL }, | 394 | { "getcube", getcube, METH_VARARGS, getcube_doc }, |
| 167 | { "datasize", datasize, METH_VARARGS, NULL }, | 395 | { "datasize", datasize, METH_VARARGS, datasize_doc }, |
| 396 | { "gendata", gendata, METH_VARARGS, gendata_doc }, | ||
| 397 | { "checkdata", checkdata, METH_VARARGS, checkdata_doc }, | ||
| 398 | { "solve", solve, METH_VARARGS, solve_doc }, | ||
| 399 | { "countmoves", countmoves, METH_VARARGS, countmoves_doc }, | ||
| 168 | { NULL, NULL, 0, NULL } | 400 | { NULL, NULL, 0, NULL } |
| 169 | }; | 401 | }; |
| 170 | 402 | ||
| 171 | static struct PyModuleDef nissy_python_module = { | 403 | static struct PyModuleDef nissy_python_module = { |
| 172 | .m_base = PyModuleDef_HEAD_INIT, | 404 | .m_base = PyModuleDef_HEAD_INIT, |
| 173 | .m_name = "nissy", | 405 | .m_name = "nissy", |
| 174 | .m_doc = NULL, | 406 | .m_doc = "python module for libnissy", |
| 175 | .m_size = -1, | 407 | .m_size = -1, |
| 176 | .m_methods = nissy_methods, | 408 | .m_methods = nissy_methods, |
| 177 | .m_slots = NULL, | 409 | .m_slots = NULL, |
| @@ -195,7 +427,13 @@ PyMODINIT_FUNC PyInit_nissy_python_module(void) { | |||
| 195 | 427 | ||
| 196 | nissy_setlogger(log_stdout); | 428 | nissy_setlogger(log_stdout); |
| 197 | module = PyModule_Create(&nissy_python_module); | 429 | module = PyModule_Create(&nissy_python_module); |
| 198 | PyModule_AddStringConstant(module, "solvedcube", NISSY_SOLVED_CUBE); | 430 | |
| 431 | PyModule_AddStringConstant(module, "solved_cube", NISSY_SOLVED_CUBE); | ||
| 432 | PyModule_AddIntConstant(module, "nissflag_normal", NISSY_NISSFLAG_NORMAL); | ||
| 433 | PyModule_AddIntConstant(module, "nissflag_inverse", NISSY_NISSFLAG_INVERSE); | ||
| 434 | PyModule_AddIntConstant(module, "nissflag_mixed", NISSY_NISSFLAG_MIXED); | ||
| 435 | PyModule_AddIntConstant(module, "nissflag_linear", NISSY_NISSFLAG_LINEAR); | ||
| 436 | PyModule_AddIntConstant(module, "nissflag_all", NISSY_NISSFLAG_ALL); | ||
| 199 | 437 | ||
| 200 | return module; | 438 | return module; |
| 201 | } | 439 | } |
diff --git a/src/nissy.c b/src/nissy.c index c5cf1d5..793d659 100644 --- a/src/nissy.c +++ b/src/nissy.c | |||
| @@ -71,7 +71,10 @@ checkdata(const char *buf, const tableinfo_t *info) | |||
| 71 | { | 71 | { |
| 72 | uint64_t distr[INFO_DISTRIBUTION_LEN]; | 72 | uint64_t distr[INFO_DISTRIBUTION_LEN]; |
| 73 | 73 | ||
| 74 | if (!strncmp(info->solver, "cocsep", 6)) { | 74 | if (info == NULL) { |
| 75 | LOG("checkdata: error reading table info\n"); | ||
| 76 | return false; | ||
| 77 | } else if (!strncmp(info->solver, "cocsep", 6)) { | ||
| 75 | getdistribution_cocsep( | 78 | getdistribution_cocsep( |
| 76 | (uint32_t *)((char *)buf + INFOSIZE), distr); | 79 | (uint32_t *)((char *)buf + INFOSIZE), distr); |
| 77 | } else if (!strncmp(info->solver, "h48", 3)) { | 80 | } else if (!strncmp(info->solver, "h48", 3)) { |
| @@ -442,21 +445,23 @@ nissy_checkdata( | |||
| 442 | { | 445 | { |
| 443 | char *buf; | 446 | char *buf; |
| 444 | tableinfo_t info; | 447 | tableinfo_t info; |
| 448 | int64_t err; | ||
| 445 | 449 | ||
| 446 | for (buf = (char *)data; | 450 | for (buf = (char *)data; |
| 447 | readtableinfo(data_size, buf, &info); | 451 | (err = readtableinfo(data_size, buf, &info)) == NISSY_OK; |
| 448 | buf += info.next, data_size -= info.next) | 452 | buf += info.next, data_size -= info.next) |
| 449 | { | 453 | { |
| 450 | if (!checkdata(buf, &info)) { | 454 | if (!checkdata(buf, &info)) { |
| 451 | LOG("Error: data for %s is inconsistent with info!\n", | 455 | LOG("Error: data for solver '%s' is corrupted!\n", |
| 452 | info.solver); | 456 | info.solver); |
| 453 | return NISSY_ERROR_DATA; | 457 | return NISSY_ERROR_DATA; |
| 454 | } | 458 | } |
| 459 | |||
| 455 | if (info.next == 0) | 460 | if (info.next == 0) |
| 456 | break; | 461 | break; |
| 457 | } | 462 | } |
| 458 | 463 | ||
| 459 | return NISSY_OK; | 464 | return err; |
| 460 | } | 465 | } |
| 461 | 466 | ||
| 462 | long long | 467 | long long |
diff --git a/src/solvers/tables.h b/src/solvers/tables.h index 060b018..3147416 100644 --- a/src/solvers/tables.h +++ b/src/solvers/tables.h | |||
| @@ -35,7 +35,8 @@ readtableinfo(uint64_t buf_size, const char *buf, tableinfo_t *info) | |||
| 35 | 35 | ||
| 36 | if (buf_size < INFOSIZE) { | 36 | if (buf_size < INFOSIZE) { |
| 37 | LOG("Error reading table: buffer size is too small " | 37 | LOG("Error reading table: buffer size is too small " |
| 38 | "(smaller than INFOSIZE = %" PRId64 ")\n", INFOSIZE); | 38 | "(given size %" PRIu64 " is smaller than INFOSIZE = %" |
| 39 | PRId64 ")\n", buf_size, INFOSIZE); | ||
| 39 | return NISSY_ERROR_BUFFER_SIZE; | 40 | return NISSY_ERROR_BUFFER_SIZE; |
| 40 | } | 41 | } |
| 41 | 42 | ||
