diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2024-10-11 12:04:02 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2024-10-11 12:04:02 +0200 |
| commit | 79c9c600f7a620e3e804ff7783511ad7da7d8f93 (patch) | |
| tree | c1cfd2320148f6a9d3af67f090e720cf6817eb91 /src | |
| parent | 5e291466fbbc45aed74f67a1b2e555d1f0c44d8f (diff) | |
| download | nissy-core-79c9c600f7a620e3e804ff7783511ad7da7d8f93.tar.gz nissy-core-79c9c600f7a620e3e804ff7783511ad7da7d8f93.zip | |
Error codes, documentation, change nisstype from string to flags
Diffstat (limited to '')
| -rw-r--r-- | src/nissy.c | 300 | ||||
| -rw-r--r-- | src/nissy.h | 229 |
2 files changed, 446 insertions, 83 deletions
diff --git a/src/nissy.c b/src/nissy.c index 1829d5c..d37256a 100644 --- a/src/nissy.c +++ b/src/nissy.c | |||
| @@ -109,20 +109,14 @@ distribution_equal( | |||
| 109 | STATIC int64_t | 109 | STATIC int64_t |
| 110 | write_result(cube_t cube, char result[static 22]) | 110 | write_result(cube_t cube, char result[static 22]) |
| 111 | { | 111 | { |
| 112 | if (!isconsistent(cube)) { | ||
| 113 | LOG("Error: resulting cube is invalid\n"); | ||
| 114 | writecube("B32", ZERO_CUBE, result); | ||
| 115 | return 8; | ||
| 116 | } | ||
| 117 | |||
| 118 | writecube("B32", cube, result); | 112 | writecube("B32", cube, result); |
| 119 | 113 | ||
| 120 | if (!issolvable(cube)) { | 114 | if (!issolvable(cube)) { |
| 121 | LOG("Warning: resulting cube is not solvable\n"); | 115 | LOG("Warning: resulting cube is not solvable\n"); |
| 122 | return 9; | 116 | return NISSY_WARNING_UNSOLVABLE; |
| 123 | } | 117 | } |
| 124 | 118 | ||
| 125 | return 0; | 119 | return NISSY_OK; |
| 126 | } | 120 | } |
| 127 | 121 | ||
| 128 | int64_t | 122 | int64_t |
| @@ -133,24 +127,37 @@ nissy_compose( | |||
| 133 | ) | 127 | ) |
| 134 | { | 128 | { |
| 135 | cube_t c, p, res; | 129 | cube_t c, p, res; |
| 130 | int64_t err; | ||
| 136 | 131 | ||
| 137 | c = readcube("B32", cube); | 132 | c = readcube("B32", cube); |
| 138 | 133 | ||
| 139 | if (!isconsistent(c)) { | 134 | if (!isconsistent(c)) { |
| 140 | LOG("Error in nissy_compose: given cube is invalid\n"); | 135 | LOG("Error in nissy_compose: given cube is invalid\n"); |
| 141 | return 1; | 136 | err = NISSY_ERROR_INVALID_CUBE; |
| 137 | goto nissy_compose_error; | ||
| 142 | } | 138 | } |
| 143 | 139 | ||
| 144 | p = readcube("B32", permutation); | 140 | p = readcube("B32", permutation); |
| 145 | 141 | ||
| 146 | if (!isconsistent(p)) { | 142 | if (!isconsistent(p)) { |
| 147 | LOG("Error in nissy_compose: given permutation is invalid\n"); | 143 | LOG("Error in nissy_compose: given permutation is invalid\n"); |
| 148 | return 2; | 144 | err = NISSY_ERROR_INVALID_CUBE; |
| 145 | goto nissy_compose_error; | ||
| 149 | } | 146 | } |
| 150 | 147 | ||
| 151 | res = compose(c, p); | 148 | res = compose(c, p); |
| 152 | 149 | ||
| 150 | if (!isconsistent(res)) { | ||
| 151 | LOG("Unknown error: resulting cube is invalid\n"); | ||
| 152 | err = NISSY_ERROR_UNKNOWN; | ||
| 153 | goto nissy_compose_error; | ||
| 154 | } | ||
| 155 | |||
| 153 | return write_result(res, result); | 156 | return write_result(res, result); |
| 157 | |||
| 158 | nissy_compose_error: | ||
| 159 | writecube("B32", ZERO_CUBE, result); | ||
| 160 | return err; | ||
| 154 | } | 161 | } |
| 155 | 162 | ||
| 156 | int64_t | 163 | int64_t |
| @@ -160,17 +167,29 @@ nissy_inverse( | |||
| 160 | ) | 167 | ) |
| 161 | { | 168 | { |
| 162 | cube_t c, res; | 169 | cube_t c, res; |
| 170 | int64_t err; | ||
| 163 | 171 | ||
| 164 | c = readcube("B32", cube); | 172 | c = readcube("B32", cube); |
| 165 | 173 | ||
| 166 | if (iserror(c)) { | 174 | if (iserror(c)) { |
| 167 | LOG("Error in nissy_inverse: given cube is invalid\n"); | 175 | LOG("Error in nissy_inverse: given cube is invalid\n"); |
| 168 | return 1; | 176 | err = NISSY_ERROR_INVALID_CUBE; |
| 177 | goto nissy_inverse_error; | ||
| 169 | } | 178 | } |
| 170 | 179 | ||
| 171 | res = inverse(c); | 180 | res = inverse(c); |
| 172 | 181 | ||
| 182 | if (!isconsistent(res)) { | ||
| 183 | LOG("Unknown error: inverted cube is invalid\n"); | ||
| 184 | err = NISSY_ERROR_UNKNOWN; | ||
| 185 | goto nissy_inverse_error; | ||
| 186 | } | ||
| 187 | |||
| 173 | return write_result(res, result); | 188 | return write_result(res, result); |
| 189 | |||
| 190 | nissy_inverse_error: | ||
| 191 | writecube("B32", ZERO_CUBE, result); | ||
| 192 | return err; | ||
| 174 | } | 193 | } |
| 175 | 194 | ||
| 176 | int64_t | 195 | int64_t |
| @@ -181,17 +200,29 @@ nissy_applymoves( | |||
| 181 | ) | 200 | ) |
| 182 | { | 201 | { |
| 183 | cube_t c, res; | 202 | cube_t c, res; |
| 203 | int64_t err; | ||
| 184 | 204 | ||
| 185 | c = readcube("B32", cube); | 205 | c = readcube("B32", cube); |
| 186 | 206 | ||
| 187 | if (!isconsistent(c)) { | 207 | if (!isconsistent(c)) { |
| 188 | LOG("Error in nissy_applymoves: given cube is invalid\n"); | 208 | LOG("Error in nissy_applymoves: given cube is invalid\n"); |
| 189 | return 1; | 209 | err = NISSY_ERROR_INVALID_CUBE; |
| 210 | goto nissy_applymoves_error; | ||
| 190 | } | 211 | } |
| 191 | 212 | ||
| 192 | res = applymoves(c, moves); | 213 | res = applymoves(c, moves); |
| 193 | 214 | ||
| 215 | if (!isconsistent(res)) { | ||
| 216 | /* Assume we got a reasonable error message from applymoves */ | ||
| 217 | err = NISSY_ERROR_INVALID_MOVES; | ||
| 218 | goto nissy_applymoves_error; | ||
| 219 | } | ||
| 220 | |||
| 194 | return write_result(res, result); | 221 | return write_result(res, result); |
| 222 | |||
| 223 | nissy_applymoves_error: | ||
| 224 | writecube("B32", ZERO_CUBE, result); | ||
| 225 | return err; | ||
| 195 | } | 226 | } |
| 196 | 227 | ||
| 197 | int64_t | 228 | int64_t |
| @@ -202,17 +233,29 @@ nissy_applytrans( | |||
| 202 | ) | 233 | ) |
| 203 | { | 234 | { |
| 204 | cube_t c, res; | 235 | cube_t c, res; |
| 236 | int64_t err; | ||
| 205 | 237 | ||
| 206 | c = readcube("B32", cube); | 238 | c = readcube("B32", cube); |
| 207 | 239 | ||
| 208 | if (!isconsistent(c)) { | 240 | if (!isconsistent(c)) { |
| 209 | LOG("Error in nissy_applytrans: given cube is invalid\n"); | 241 | LOG("Error in nissy_applytrans: given cube is invalid\n"); |
| 210 | return 1; | 242 | err = NISSY_ERROR_INVALID_CUBE; |
| 243 | goto nissy_applytrans_error; | ||
| 211 | } | 244 | } |
| 212 | 245 | ||
| 213 | res = applytrans(c, transformation); | 246 | res = applytrans(c, transformation); |
| 214 | 247 | ||
| 248 | if (!isconsistent(res)) { | ||
| 249 | /* Assume we got a reasonable error message from applytrans */ | ||
| 250 | err = NISSY_ERROR_INVALID_TRANS; | ||
| 251 | goto nissy_applytrans_error; | ||
| 252 | } | ||
| 253 | |||
| 215 | return write_result(res, result); | 254 | return write_result(res, result); |
| 255 | |||
| 256 | nissy_applytrans_error: | ||
| 257 | writecube("B32", ZERO_CUBE, result); | ||
| 258 | return err; | ||
| 216 | } | 259 | } |
| 217 | 260 | ||
| 218 | int64_t | 261 | int64_t |
| @@ -222,15 +265,21 @@ nissy_frommoves( | |||
| 222 | ) | 265 | ) |
| 223 | { | 266 | { |
| 224 | cube_t res; | 267 | cube_t res; |
| 268 | int64_t err; | ||
| 225 | 269 | ||
| 226 | res = applymoves(SOLVED_CUBE, moves); | 270 | res = applymoves(SOLVED_CUBE, moves); |
| 227 | 271 | ||
| 228 | if (!isconsistent(res)) { | 272 | if (!isconsistent(res)) { |
| 229 | /* Moves must be invalid */ | 273 | /* Assume we got a reasonable error message from applymoves */ |
| 230 | return 1; | 274 | err = NISSY_ERROR_INVALID_MOVES; |
| 275 | goto nissy_frommoves_error; | ||
| 231 | } | 276 | } |
| 232 | 277 | ||
| 233 | return write_result(res, result); | 278 | return write_result(res, result); |
| 279 | |||
| 280 | nissy_frommoves_error: | ||
| 281 | writecube("B32", ZERO_CUBE, result); | ||
| 282 | return err; | ||
| 234 | } | 283 | } |
| 235 | 284 | ||
| 236 | int64_t | 285 | int64_t |
| @@ -241,20 +290,35 @@ nissy_convert( | |||
| 241 | char *result | 290 | char *result |
| 242 | ) | 291 | ) |
| 243 | { | 292 | { |
| 244 | int ret; | ||
| 245 | cube_t c; | 293 | cube_t c; |
| 294 | int ret; | ||
| 295 | int64_t err; | ||
| 246 | 296 | ||
| 247 | c = readcube(format_in, cube_string); | 297 | c = readcube(format_in, cube_string); |
| 248 | 298 | ||
| 249 | if (iserror(c)) | 299 | if (iserror(c)) { |
| 250 | return 1; | 300 | err = NISSY_ERROR_INVALID_CUBE; |
| 301 | goto nissy_convert_error; | ||
| 302 | } | ||
| 251 | 303 | ||
| 252 | ret = writecube(format_out, c, result); | 304 | ret = writecube(format_out, c, result); |
| 253 | 305 | ||
| 254 | if (ret != 0) | 306 | if (ret != 0) { |
| 255 | return 2; | 307 | /* Assume the format was invalid */ |
| 308 | err = NISSY_ERROR_INVALID_FORMAT; | ||
| 309 | goto nissy_convert_error; | ||
| 310 | } | ||
| 311 | |||
| 312 | if (!isconsistent(c)) { | ||
| 313 | err = NISSY_ERROR_UNKNOWN; | ||
| 314 | goto nissy_convert_error; | ||
| 315 | } | ||
| 316 | |||
| 317 | return NISSY_OK; | ||
| 256 | 318 | ||
| 257 | return isconsistent(c) ? 0 : 3; | 319 | nissy_convert_error: |
| 320 | /* We don't write anything to result, we don't know the format */ | ||
| 321 | return err; | ||
| 258 | } | 322 | } |
| 259 | 323 | ||
| 260 | int64_t | 324 | int64_t |
| @@ -276,6 +340,13 @@ nissy_getcube( | |||
| 276 | 340 | ||
| 277 | c = getcube(ep, eo, cp, co); | 341 | c = getcube(ep, eo, cp, co); |
| 278 | 342 | ||
| 343 | if (!isconsistent(c)) { | ||
| 344 | LOG("Error: could not get cube with ep=%" PRId64 ", eo=%" | ||
| 345 | PRId64 ", cp=%" PRId64 ", co=%" PRId64 ".\n", | ||
| 346 | ep, eo, cp, co); | ||
| 347 | return NISSY_ERROR_OPTIONS; | ||
| 348 | } | ||
| 349 | |||
| 279 | return write_result(c, result); | 350 | return write_result(c, result); |
| 280 | } | 351 | } |
| 281 | 352 | ||
| @@ -290,14 +361,14 @@ nissy_datasize( | |||
| 290 | 361 | ||
| 291 | int64_t | 362 | int64_t |
| 292 | nissy_datainfo( | 363 | nissy_datainfo( |
| 293 | const void *table, | 364 | const void *data, |
| 294 | void (*write)(const char *, ...) | 365 | void (*write)(const char *, ...) |
| 295 | ) | 366 | ) |
| 296 | { | 367 | { |
| 297 | uint8_t i; | 368 | uint8_t i; |
| 298 | tableinfo_t info; | 369 | tableinfo_t info; |
| 299 | 370 | ||
| 300 | readtableinfo(table, &info); | 371 | readtableinfo(data, &info); |
| 301 | 372 | ||
| 302 | write("\n---------\n\n"); | 373 | write("\n---------\n\n"); |
| 303 | write("Table information for '%s'\n", info.solver); | 374 | write("Table information for '%s'\n", info.solver); |
| @@ -321,16 +392,15 @@ nissy_datainfo( | |||
| 321 | break; | 392 | break; |
| 322 | default: | 393 | default: |
| 323 | LOG("datainfo: unknown table type\n"); | 394 | LOG("datainfo: unknown table type\n"); |
| 324 | return 1; | 395 | return NISSY_ERROR_DATA; |
| 325 | } | 396 | } |
| 326 | 397 | ||
| 327 | if (info.next != 0) { | 398 | if (info.next != 0) |
| 328 | return nissy_datainfo((char *)table + info.next, write); | 399 | return nissy_datainfo((char *)data + info.next, write); |
| 329 | } | ||
| 330 | 400 | ||
| 331 | write("\n---------\n"); | 401 | write("\n---------\n"); |
| 332 | 402 | ||
| 333 | return 0; | 403 | return NISSY_OK; |
| 334 | } | 404 | } |
| 335 | 405 | ||
| 336 | int64_t | 406 | int64_t |
| @@ -340,20 +410,19 @@ nissy_gendata( | |||
| 340 | ) | 410 | ) |
| 341 | { | 411 | { |
| 342 | int p; | 412 | int p; |
| 343 | int64_t ret; | ||
| 344 | gendata_h48_arg_t arg; | 413 | gendata_h48_arg_t arg; |
| 345 | 414 | ||
| 346 | arg.buf = data; | 415 | arg.buf = data; |
| 347 | if (!strncmp(solver, "h48", 3)) { | 416 | if (!strncmp(solver, "h48", 3)) { |
| 348 | p = parse_h48_solver(solver, &arg.h, &arg.k); | 417 | p = parse_h48_solver(solver, &arg.h, &arg.k); |
| 349 | arg.maxdepth = 20; | 418 | arg.maxdepth = 20; |
| 350 | ret = p == 0 ? (int64_t)gendata_h48(&arg) : -1; | 419 | if (p != 0) |
| 420 | return NISSY_ERROR_UNKNOWN; | ||
| 421 | return (int64_t)gendata_h48(&arg); | ||
| 351 | } else { | 422 | } else { |
| 352 | LOG("gendata: unknown solver %s\n", solver); | 423 | LOG("gendata: unknown solver %s\n", solver); |
| 353 | ret = -1; | 424 | return NISSY_ERROR_INVALID_SOLVER; |
| 354 | } | 425 | } |
| 355 | |||
| 356 | return ret; | ||
| 357 | } | 426 | } |
| 358 | 427 | ||
| 359 | int64_t | 428 | int64_t |
| @@ -369,20 +438,20 @@ nissy_checkdata( | |||
| 369 | if (!checkdata(buf, &info)) { | 438 | if (!checkdata(buf, &info)) { |
| 370 | LOG("Error: data for %s is inconsistent with info!\n", | 439 | LOG("Error: data for %s is inconsistent with info!\n", |
| 371 | info.solver); | 440 | info.solver); |
| 372 | return 1; | 441 | return NISSY_ERROR_DATA; |
| 373 | } | 442 | } |
| 374 | if (info.next == 0) | 443 | if (info.next == 0) |
| 375 | break; | 444 | break; |
| 376 | } | 445 | } |
| 377 | 446 | ||
| 378 | return 0; | 447 | return NISSY_OK; |
| 379 | } | 448 | } |
| 380 | 449 | ||
| 381 | int64_t | 450 | int64_t |
| 382 | nissy_solve( | 451 | nissy_solve( |
| 383 | const char cube[static 22], | 452 | const char cube[static 22], |
| 384 | const char *solver, | 453 | const char *solver, |
| 385 | const char *nisstype, | 454 | uint8_t nissflag, |
| 386 | int8_t minmoves, | 455 | int8_t minmoves, |
| 387 | int8_t maxmoves, | 456 | int8_t maxmoves, |
| 388 | int64_t maxsolutions, | 457 | int64_t maxsolutions, |
| @@ -397,9 +466,14 @@ nissy_solve( | |||
| 397 | 466 | ||
| 398 | c = readcube_B32(cube); | 467 | c = readcube_B32(cube); |
| 399 | 468 | ||
| 469 | if (!isconsistent(c)) { | ||
| 470 | LOG("solve: cube is invalid\n"); | ||
| 471 | return NISSY_ERROR_INVALID_CUBE; | ||
| 472 | } | ||
| 473 | |||
| 400 | if (!issolvable(c)) { | 474 | if (!issolvable(c)) { |
| 401 | LOG("solve: cube is not solvable\n"); | 475 | LOG("solve: cube is not solvable\n"); |
| 402 | return -1; | 476 | return NISSY_ERROR_UNSOLVABLE_CUBE; |
| 403 | } | 477 | } |
| 404 | 478 | ||
| 405 | if (minmoves < 0) { | 479 | if (minmoves < 0) { |
| @@ -414,7 +488,7 @@ nissy_solve( | |||
| 414 | 488 | ||
| 415 | if (maxsolutions < 0) { | 489 | if (maxsolutions < 0) { |
| 416 | LOG("solve: 'maxsols' is negative, stopping\n"); | 490 | LOG("solve: 'maxsols' is negative, stopping\n"); |
| 417 | return -1; | 491 | return NISSY_ERROR_OPTIONS; |
| 418 | } | 492 | } |
| 419 | 493 | ||
| 420 | if (maxsolutions == 0) { | 494 | if (maxsolutions == 0) { |
| @@ -424,7 +498,7 @@ nissy_solve( | |||
| 424 | 498 | ||
| 425 | if (solutions == NULL) { | 499 | if (solutions == NULL) { |
| 426 | LOG("solve: return parameter 'solutions' is NULL, stopping\n"); | 500 | LOG("solve: return parameter 'solutions' is NULL, stopping\n"); |
| 427 | return -1; | 501 | return NISSY_ERROR_NULL_POINTER; |
| 428 | } | 502 | } |
| 429 | 503 | ||
| 430 | if (!strncmp(solver, "h48", 3)) { | 504 | if (!strncmp(solver, "h48", 3)) { |
| @@ -433,7 +507,8 @@ nissy_solve( | |||
| 433 | 507 | ||
| 434 | p = parse_h48_solver(solver, &h, &k); | 508 | p = parse_h48_solver(solver, &h, &k); |
| 435 | if (p != 0) { | 509 | if (p != 0) { |
| 436 | return -1; | 510 | LOG("solve: unknown solver %s\n", solver); |
| 511 | return NISSY_ERROR_INVALID_SOLVER; | ||
| 437 | } else { | 512 | } else { |
| 438 | return THREADS > 1 ? | 513 | return THREADS > 1 ? |
| 439 | solve_h48_multithread(c, minmoves, | 514 | solve_h48_multithread(c, minmoves, |
| @@ -446,12 +521,151 @@ nissy_solve( | |||
| 446 | c, minmoves, maxmoves, maxsolutions, optimal, solutions); | 521 | c, minmoves, maxmoves, maxsolutions, optimal, solutions); |
| 447 | } else { | 522 | } else { |
| 448 | LOG("solve: unknown solver '%s'\n", solver); | 523 | LOG("solve: unknown solver '%s'\n", solver); |
| 449 | return -1; | 524 | return NISSY_ERROR_INVALID_SOLVER; |
| 450 | } | 525 | } |
| 451 | } | 526 | } |
| 452 | 527 | ||
| 453 | void | 528 | int64_t |
| 454 | nissy_setlogger(void (*log)(const char *, ...)) | 529 | nissy_setlogger( |
| 530 | void (*log)(const char *, ...) | ||
| 531 | ) | ||
| 455 | { | 532 | { |
| 456 | nissy_log = log; | 533 | nissy_log = log; |
| 534 | |||
| 535 | if (log == NULL) | ||
| 536 | return NISSY_WARNING_NULL_CALLBACK; | ||
| 537 | |||
| 538 | return NISSY_OK; | ||
| 539 | } | ||
| 540 | |||
| 541 | int64_t | ||
| 542 | nissy_explainerror( | ||
| 543 | int64_t error_code, | ||
| 544 | void (*write)(const char *, ...) | ||
| 545 | ) | ||
| 546 | { | ||
| 547 | if (write == NULL) | ||
| 548 | return NISSY_WARNING_NULL_CALLBACK; | ||
| 549 | |||
| 550 | switch (error_code) { | ||
| 551 | case NISSY_OK: | ||
| 552 | write( | ||
| 553 | "The value %" PRId64 " denotes a success.\n" | ||
| 554 | "If returned by solve, it means that no solutions has " | ||
| 555 | "been found.\n", NISSY_OK | ||
| 556 | ); | ||
| 557 | return NISSY_OK; | ||
| 558 | case NISSY_WARNING_UNSOLVABLE: | ||
| 559 | write( | ||
| 560 | "The value %" PRId64 " is a warning. It means that the " | ||
| 561 | "operation was completed succesfully, but the resulting " | ||
| 562 | "cube is in an unsolvable state. This could be intended, " | ||
| 563 | "for example if the user has provided an unsolvable cube " | ||
| 564 | "as input.\n", NISSY_WARNING_UNSOLVABLE | ||
| 565 | ); | ||
| 566 | return NISSY_OK; | ||
| 567 | case NISSY_WARNING_NULL_CALLBACK: | ||
| 568 | write( | ||
| 569 | "The value %" PRId64 " is a warning. It means that the " | ||
| 570 | "provided pointer to a writer function is NULL.\n" | ||
| 571 | "If returned by nissy_setlogger, it means that any future " | ||
| 572 | "log messages will not be printed.\n", | ||
| 573 | NISSY_WARNING_NULL_CALLBACK | ||
| 574 | ); | ||
| 575 | return NISSY_OK; | ||
| 576 | case NISSY_ERROR_INVALID_CUBE: | ||
| 577 | write( | ||
| 578 | "The value %" PRId64 " means that the provided cube is " | ||
| 579 | "invalid. It could be written in an unknown format, or " | ||
| 580 | "in a format different from what specified, or simply " | ||
| 581 | "ill-formed.\n", NISSY_ERROR_INVALID_CUBE | ||
| 582 | ); | ||
| 583 | return NISSY_OK; | ||
| 584 | case NISSY_ERROR_UNSOLVABLE_CUBE: | ||
| 585 | write( | ||
| 586 | "The value %" PRId64 " means that the provided cube is " | ||
| 587 | "in an unsolvable state.\n", NISSY_ERROR_INVALID_CUBE | ||
| 588 | ); | ||
| 589 | return NISSY_OK; | ||
| 590 | case NISSY_ERROR_INVALID_MOVES: | ||
| 591 | write( | ||
| 592 | "The value %" PRId64 " means that the given moves are " | ||
| 593 | "invalid.\n", NISSY_ERROR_INVALID_MOVES | ||
| 594 | ); | ||
| 595 | return NISSY_OK; | ||
| 596 | case NISSY_ERROR_INVALID_TRANS: | ||
| 597 | write( | ||
| 598 | "The value %" PRId64 " means that the given transformation " | ||
| 599 | "is invalid.\n", NISSY_ERROR_INVALID_TRANS | ||
| 600 | ); | ||
| 601 | return NISSY_OK; | ||
| 602 | case NISSY_ERROR_INVALID_FORMAT: | ||
| 603 | write( | ||
| 604 | "The value %" PRId64 " means that the given format is not " | ||
| 605 | "known.\n", NISSY_ERROR_INVALID_FORMAT | ||
| 606 | ); | ||
| 607 | return NISSY_OK; | ||
| 608 | case NISSY_ERROR_INVALID_SOLVER: | ||
| 609 | write( | ||
| 610 | "The value %" PRId64 " means that the given solver is not " | ||
| 611 | "known.\n", NISSY_ERROR_INVALID_SOLVER | ||
| 612 | ); | ||
| 613 | return NISSY_OK; | ||
| 614 | case NISSY_ERROR_NULL_POINTER: | ||
| 615 | write( | ||
| 616 | "The value %" PRId64 " means that one of the provided " | ||
| 617 | "pointer arguments is NULL. For example, it may be " | ||
| 618 | "returned by solve when called with a solver that " | ||
| 619 | "requires some pre-computed data, but the provided data " | ||
| 620 | "is NULL.\n", NISSY_ERROR_NULL_POINTER | ||
| 621 | ); | ||
| 622 | return NISSY_OK; | ||
| 623 | case NISSY_ERROR_DATA: | ||
| 624 | write( | ||
| 625 | "The value %" PRId64 " means that the provided data is " | ||
| 626 | "invalid. For example, it may be returned by solve when " | ||
| 627 | "called with incompatible solver and data arguments.\n", | ||
| 628 | NISSY_ERROR_DATA | ||
| 629 | ); | ||
| 630 | return NISSY_OK; | ||
| 631 | case NISSY_ERROR_OPTIONS: | ||
| 632 | write( | ||
| 633 | "The value %" PRId64 " means that one or more of the " | ||
| 634 | "given options are invalid. For example, it may be " | ||
| 635 | "returned by solve when called with a negative maximum " | ||
| 636 | "number of solutions.\n", NISSY_ERROR_OPTIONS | ||
| 637 | ); | ||
| 638 | return NISSY_OK; | ||
| 639 | case NISSY_ERROR_INVALID_CODE: | ||
| 640 | write( | ||
| 641 | "The value %" PRId64 " means that the given error code " | ||
| 642 | "is not known. It may be returned by explainerror.\n", | ||
| 643 | NISSY_ERROR_INVALID_CODE | ||
| 644 | ); | ||
| 645 | return NISSY_OK; | ||
| 646 | case NISSY_ERROR_UNKNOWN: | ||
| 647 | write( | ||
| 648 | "The value %" PRId64 " denotes an unexpected error. It " | ||
| 649 | "probably means that there some bug in this library.\n" | ||
| 650 | "If you can, report any error of this kind to " | ||
| 651 | "sebastiano@tronto.net. Thanks!\n", NISSY_ERROR_UNKNOWN | ||
| 652 | ); | ||
| 653 | return NISSY_OK; | ||
| 654 | default: | ||
| 655 | break; | ||
| 656 | } | ||
| 657 | |||
| 658 | if (error_code > 0) { | ||
| 659 | write( | ||
| 660 | "A positive return values does not denote an error\n" | ||
| 661 | "If returned by gendata or datasize, it denotes the size " | ||
| 662 | "of the data, in bytes\n" | ||
| 663 | "If returned by solve, it denotes the number of solutions " | ||
| 664 | "found.\n" | ||
| 665 | ); | ||
| 666 | return NISSY_OK; | ||
| 667 | } else { | ||
| 668 | write("Unknown error code %" PRId64 "\n", error_code); | ||
| 669 | return NISSY_ERROR_INVALID_CODE; | ||
| 670 | } | ||
| 457 | } | 671 | } |
diff --git a/src/nissy.h b/src/nissy.h index c78fb50..c019998 100644 --- a/src/nissy.h +++ b/src/nissy.h | |||
| @@ -8,10 +8,9 @@ If you include this file, you should also use the following includes: | |||
| 8 | #include <stdbool> | 8 | #include <stdbool> |
| 9 | #include <string> | 9 | #include <string> |
| 10 | 10 | ||
| 11 | All the functions below return 0 in case of success and a positive number | 11 | All the functions return 0 or a positive integer in case of success and |
| 12 | in case of error, unless otherwise specified. Errors are checked in code | 12 | a negative integer in case of error, unless otherwise specified. |
| 13 | order: for example if error code 1 is returned then it could that also | 13 | You can see the list of error codes below, or use nissy_explainerror(). |
| 14 | an error with code 2 or higher occurred. | ||
| 15 | 14 | ||
| 16 | Arguments of type char [static 22] denote a cube in B32 format. | 15 | Arguments of type char [static 22] denote a cube in B32 format. |
| 17 | Other available formats are H48 and SRC. See README.md for more info on | 16 | Other available formats are H48 and SRC. See README.md for more info on |
| @@ -25,14 +24,48 @@ A transformation must be given in the format | |||
| 25 | for example 'rotation UF' or 'mirrored BL'. | 24 | for example 'rotation UF' or 'mirrored BL'. |
| 26 | */ | 25 | */ |
| 27 | 26 | ||
| 27 | /* Error codes */ | ||
| 28 | #define NISSY_OK INT64_C(0) | ||
| 29 | #define NISSY_WARNING_UNSOLVABLE INT64_C(-1) | ||
| 30 | #define NISSY_WARNING_NULL_CALLBACK INT64_C(-2) | ||
| 31 | #define NISSY_ERROR_INVALID_CUBE INT64_C(-10) | ||
| 32 | #define NISSY_ERROR_UNSOLVABLE_CUBE INT64_C(-11) | ||
| 33 | #define NISSY_ERROR_INVALID_MOVES INT64_C(-20) | ||
| 34 | #define NISSY_ERROR_INVALID_TRANS INT64_C(-30) | ||
| 35 | #define NISSY_ERROR_INVALID_FORMAT INT64_C(-40) | ||
| 36 | #define NISSY_ERROR_INVALID_SOLVER INT64_C(-50) | ||
| 37 | #define NISSY_ERROR_NULL_POINTER INT64_C(-60) | ||
| 38 | #define NISSY_ERROR_DATA INT64_C(-70) | ||
| 39 | #define NISSY_ERROR_OPTIONS INT64_C(-80) | ||
| 40 | #define NISSY_ERROR_INVALID_CODE INT64_C(-90) | ||
| 41 | #define NISSY_ERROR_UNKNOWN INT64_C(-999) | ||
| 42 | |||
| 43 | /* Flags for NISS options */ | ||
| 44 | #define NISSY_NISSFLAG_NORMAL UINT8_C(1) | ||
| 45 | #define NISSY_NISSFLAG_INVERSE UINT8_C(2) | ||
| 46 | #define NISSY_NISSFLAG_MIXED UINT8_C(4) | ||
| 47 | #define NISSY_NISSFLAG_LINEAR \ | ||
| 48 | (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE) | ||
| 49 | #define NISSY_NISSFLAG_ALL \ | ||
| 50 | (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED) | ||
| 51 | |||
| 28 | /* | 52 | /* |
| 29 | Apply the secod argument as a permutation on the first argument. | 53 | Apply the secod argument as a permutation on the first argument. |
| 30 | 54 | ||
| 55 | Parameters: | ||
| 56 | cube - The first cube, in B32 format. | ||
| 57 | permutation - The second cube, in B32 format. This cube is treated as a | ||
| 58 | permutation and "applied" to the first cube. | ||
| 59 | result - The return parameter for the resulting cube, in B32 format. | ||
| 60 | |||
| 31 | Return values: | 61 | Return values: |
| 32 | 0 Valid result | 62 | NISSY_OK - The cubes were composed succesfully. |
| 33 | 1 The given cube is invalid | 63 | NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is |
| 34 | 2 The given permutation is invalid | 64 | either because at least on of the given cubes |
| 35 | 9 The resulting cube is not solvable | 65 | was not solvable, or due to an unknown internal |
| 66 | error. | ||
| 67 | NISSY_ERROR_INVALID_CUBE - At least one of the given cubes is invalid. | ||
| 68 | NISSY_ERROR_UNKNOWN - An unknown error occurred. | ||
| 36 | */ | 69 | */ |
| 37 | int64_t nissy_compose( | 70 | int64_t nissy_compose( |
| 38 | const char cube[static 22], | 71 | const char cube[static 22], |
| @@ -43,10 +76,17 @@ int64_t nissy_compose( | |||
| 43 | /* | 76 | /* |
| 44 | Compute the inverse of the given cube. | 77 | Compute the inverse of the given cube. |
| 45 | 78 | ||
| 79 | Parameters: | ||
| 80 | cube - The cube to be inverted, in B32 format. | ||
| 81 | result - The return parameter for the resulting cube, in B32 format. | ||
| 82 | |||
| 46 | Return values: | 83 | Return values: |
| 47 | 0 Valid result | 84 | NISSY_OK - The cube was inverted succesfully. |
| 48 | 1 The given cube is invalid | 85 | NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is |
| 49 | 9 The resulting cube is not solvable | 86 | either because the given cube was not solvable, |
| 87 | or due to an unknown internal error. | ||
| 88 | NISSY_ERROR_INVALID_CUBE - The given cube is invalid. | ||
| 89 | NISSY_ERROR_UNKNOWN - An unknown error occurred. | ||
| 50 | */ | 90 | */ |
| 51 | int64_t nissy_inverse( | 91 | int64_t nissy_inverse( |
| 52 | const char cube[static 22], | 92 | const char cube[static 22], |
| @@ -56,11 +96,18 @@ int64_t nissy_inverse( | |||
| 56 | /* | 96 | /* |
| 57 | Apply the given sequence of moves on the given cube. | 97 | Apply the given sequence of moves on the given cube. |
| 58 | 98 | ||
| 99 | Parameters: | ||
| 100 | cube - The cube to move, in B32 format. | ||
| 101 | moves - The moves to apply to the cube. | ||
| 102 | result - The return parameter for the resulting cube, in B32 format. | ||
| 103 | |||
| 59 | Return values: | 104 | Return values: |
| 60 | 0 Valid result | 105 | NISSY_OK - The moves were applied succesfully. |
| 61 | 1 The given cube is invalid | 106 | NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is |
| 62 | 8 The given moves are invalid | 107 | either because the given cube was not solvable, |
| 63 | 9 The resulting cube is not solvable | 108 | or due to an unknown internal error. |
| 109 | NISSY_ERROR_INVALID_CUBE - The given cube is invalid. | ||
| 110 | NISSY_ERROR_INVALID_MOVES - The given moves are invalid. | ||
| 64 | */ | 111 | */ |
| 65 | int64_t nissy_applymoves( | 112 | int64_t nissy_applymoves( |
| 66 | const char cube[static 22], | 113 | const char cube[static 22], |
| @@ -71,11 +118,17 @@ int64_t nissy_applymoves( | |||
| 71 | /* | 118 | /* |
| 72 | Apply the single given transformation to the given cube. | 119 | Apply the single given transformation to the given cube. |
| 73 | 120 | ||
| 121 | Parameters: | ||
| 122 | cube - The cube to be transformed, in B32 format. | ||
| 123 | transformation - The transformation in (rotation|mirrored) xy format. | ||
| 124 | result - The return parameter for the resulting cube, in B32 format. | ||
| 125 | |||
| 74 | Return values: | 126 | Return values: |
| 75 | 0 Valid result | 127 | NISSY_OK - The transformation was performed succesfully. |
| 76 | 1 The given cube is invalid | 128 | NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is |
| 77 | 8 The given transformation is invalid | 129 | probably due to an unknown internal error. |
| 78 | 9 The resulting cube is not solvable | 130 | NISSY_ERROR_INVALID_CUBE - The given cube is invalid. |
| 131 | NISSY_ERROR_INVALID_TRANS - The given transformation is invalid. | ||
| 79 | */ | 132 | */ |
| 80 | int64_t nissy_applytrans( | 133 | int64_t nissy_applytrans( |
| 81 | const char cube[static 22], | 134 | const char cube[static 22], |
| @@ -86,9 +139,15 @@ int64_t nissy_applytrans( | |||
| 86 | /* | 139 | /* |
| 87 | Apply the given moves to the solved cube. | 140 | Apply the given moves to the solved cube. |
| 88 | 141 | ||
| 142 | Parameters: | ||
| 143 | moves - The moves to be applied to the solved cube. | ||
| 144 | result - Return parameter for the resulting cube, in B32 format. | ||
| 145 | |||
| 89 | Return values: | 146 | Return values: |
| 90 | 0 Valid result | 147 | NISSY_OK - The moves were performed succesfully. |
| 91 | 1 The given moves are invalid | 148 | NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is |
| 149 | probably due to an unknown internal error. | ||
| 150 | NISSY_ERROR_INVALID_MOVES - The given moves are invalid. | ||
| 92 | */ | 151 | */ |
| 93 | int64_t nissy_frommoves( | 152 | int64_t nissy_frommoves( |
| 94 | const char *moves, | 153 | const char *moves, |
| @@ -98,20 +157,45 @@ int64_t nissy_frommoves( | |||
| 98 | /* | 157 | /* |
| 99 | Convert the given cube between the two given formats. | 158 | Convert the given cube between the two given formats. |
| 100 | 159 | ||
| 160 | Parameters: | ||
| 161 | format_in - The input format. | ||
| 162 | format_out - The output format. | ||
| 163 | string - The cube, in format_in format. | ||
| 164 | result - Return parameter for the cube in format_out format. Must be | ||
| 165 | large enough to contains the cube in this format. | ||
| 166 | |||
| 101 | Return values: | 167 | Return values: |
| 102 | 0 Valid result | 168 | NISSY_OK - The conversion was performed succesfully. |
| 103 | 1 The given cube or format_in is invalid | 169 | NISSY_ERROR_INVALID_CUBE - The given cube is invalid. |
| 104 | 2 The resulting cube or format_out is invalid | 170 | NISSY_ERROR_INVALID_FORMAT - At least one of the given formats is invalid. |
| 105 | 3 The resulting cube is inconsistent | 171 | NISSY_ERROR_UNKNOWN - An unknown error occurred. |
| 106 | */ | 172 | */ |
| 107 | int64_t nissy_convert( | 173 | int64_t nissy_convert( |
| 108 | const char *format_in, | 174 | const char *format_in, |
| 109 | const char *format_out, | 175 | const char *format_out, |
| 110 | const char *cube_string, | 176 | const char *cube, |
| 111 | char *result | 177 | char *result |
| 112 | ); | 178 | ); |
| 113 | 179 | ||
| 114 | /* Get the cube with the given ep, eo, cp and co values. */ | 180 | /* |
| 181 | Get the cube with the given ep, eo, cp and co values. The values must be in the | ||
| 182 | ranges specified below, but if the option "fix" is given any values outside its | ||
| 183 | range will be adjusted before using it. The option "fix" also fixes parity and | ||
| 184 | orientation issues, resulting always in a solvable cube. | ||
| 185 | |||
| 186 | Parameters: | ||
| 187 | ep - The edge permutation, 0 <= ep <= 479001600 (12!) | ||
| 188 | eo - The edge orientation, 0 <= eo <= 2047 (2^11) | ||
| 189 | cp - The corner permutation, 0 <= cp <= 40320 (8!) | ||
| 190 | co - The corner orientation, 0 <= co <= 2187 (3^7) | ||
| 191 | options - Other options. | ||
| 192 | result - The return parameter for the resulting cube, in B32 format. | ||
| 193 | |||
| 194 | Return values: | ||
| 195 | NISSY_OK - The cube was generated succesfully. | ||
| 196 | NISSY_WARNING_UNSOLVABLE - The resulting cube is unsolvable. | ||
| 197 | NISSY_ERROR_OPTIONS - One or more of the given parameters is invalid. | ||
| 198 | */ | ||
| 115 | int64_t nissy_getcube( | 199 | int64_t nissy_getcube( |
| 116 | int64_t ep, | 200 | int64_t ep, |
| 117 | int64_t eo, | 201 | int64_t eo, |
| @@ -125,9 +209,13 @@ int64_t nissy_getcube( | |||
| 125 | Compute the size of the data generated by nissy_gendata, when called with | 209 | Compute the size of the data generated by nissy_gendata, when called with |
| 126 | the same parameters, or -1 in case of error. | 210 | the same parameters, or -1 in case of error. |
| 127 | 211 | ||
| 212 | Parameters: | ||
| 213 | solver - The name of the solver. | ||
| 214 | |||
| 128 | Return values: | 215 | Return values: |
| 129 | -1 Error | 216 | NISSY_ERROR_INVALID_SOLVER - The given solver is not known. |
| 130 | >=0 The size of the table, in bytes | 217 | NISSY_ERROR_UNKNOWN - An unknown error occurred. |
| 218 | Any value >= 0 - The size of the data, in bytes. | ||
| 131 | */ | 219 | */ |
| 132 | int64_t nissy_datasize( | 220 | int64_t nissy_datasize( |
| 133 | const char *solver | 221 | const char *solver |
| @@ -136,38 +224,71 @@ int64_t nissy_datasize( | |||
| 136 | /* | 224 | /* |
| 137 | Compute the data for the given solver and store it in generated_data. | 225 | Compute the data for the given solver and store it in generated_data. |
| 138 | 226 | ||
| 227 | Parameters: | ||
| 228 | solver - The name of the solver. | ||
| 229 | data - The return parameter for the generated data. Must be large enoguh | ||
| 230 | to contain the whole data. It is advised to use nissy_datasize to | ||
| 231 | check how much memory is needed. | ||
| 232 | |||
| 139 | Return values: | 233 | Return values: |
| 140 | -1 Error | 234 | NISSY_ERROR_INVALID_SOLVER - The given solver is not known. |
| 141 | >=0 The size of the table, in bytes | 235 | NISSY_ERROR_UNKNOWN - An error occurred while generating the data. |
| 236 | Any value >= 0 - The size of the data, in bytes. | ||
| 142 | */ | 237 | */ |
| 143 | int64_t nissy_gendata( | 238 | int64_t nissy_gendata( |
| 144 | const char *solver, | 239 | const char *solver, |
| 145 | void *generated_data | 240 | void *data |
| 146 | ); | 241 | ); |
| 147 | 242 | ||
| 148 | /* | 243 | /* |
| 149 | Print information on a data table via the provided callback writer. | 244 | Print information on a data table via the provided callback writer. |
| 150 | 245 | ||
| 246 | Parameters: | ||
| 247 | data - The data | ||
| 248 | write - A callback writer with the same signature as printf(3). | ||
| 249 | |||
| 151 | Return values: | 250 | Return values: |
| 152 | 0 No error | 251 | NISSY_OK - The data is correct. |
| 153 | 1 The given data could not be read correctly | 252 | NISSY_ERROR_DATA - The data contains errors. |
| 154 | */ | 253 | */ |
| 155 | int64_t nissy_datainfo( | 254 | int64_t nissy_datainfo( |
| 156 | const void *table, | 255 | const void *data, |
| 157 | void (*write)(const char *, ...) | 256 | void (*write)(const char *, ...) |
| 158 | ); | 257 | ); |
| 159 | 258 | ||
| 160 | /* | 259 | /* |
| 161 | Solve the given cube using the given solver and options | 260 | Solve the given cube using the given solver and options. |
| 261 | |||
| 262 | Parameters: | ||
| 263 | cube - The cube to solver, in B32 format. | ||
| 264 | solver - The name of the solver. | ||
| 265 | nissflag - The flags for NISS (linear, inverse, mixed, or combinations). | ||
| 266 | minmoves - The minimum number of moves for a solution. | ||
| 267 | maxmoves - The maximum number of moves for a solution. | ||
| 268 | maxsolutions - The maximum number of solutions. | ||
| 269 | optimal - If set to a non-negative value, the maximum number of moves | ||
| 270 | above the optimal solution length. | ||
| 271 | data - The data for the solver. Can be computed with gendata. | ||
| 272 | solutions - The return parameter for the solutions. Must be large enough | ||
| 273 | to store all found solutions. The solutions are separated by | ||
| 274 | a '\n' (newline) and a '\0' (NULL character) terminates the | ||
| 275 | list. | ||
| 276 | TODO: replace with callback writer. | ||
| 162 | 277 | ||
| 163 | Return values: | 278 | Return values: |
| 164 | -1 Error | 279 | NISSY_OK - Cube solved succesfully. |
| 165 | >=0 The number of solutions found | 280 | NISSY_ERROR_INVALID_CUBE - The given cube is invalid. |
| 281 | NISSY_ERROR_UNSOLVABLE_CUBE - The given cube is valid, but not solvable with | ||
| 282 | the given solver. | ||
| 283 | NISSY_ERROR_OPTIONS - One or more of the given options are invalid. | ||
| 284 | NISSY_ERROR_NULL_POINTER - One of the provided pointers is null. | ||
| 285 | NISSY_ERROR_INVALID_SOLVER - The given solver is not known. | ||
| 286 | Any value >= 0 - The number of solutions found. | ||
| 166 | */ | 287 | */ |
| 167 | int64_t nissy_solve( | 288 | int64_t nissy_solve( |
| 168 | const char cube[static 22], | 289 | const char cube[static 22], |
| 169 | const char *solver, | 290 | const char *solver, |
| 170 | const char *nisstype, /* TODO: remove, use flags */ | 291 | uint8_t nissflag, |
| 171 | int8_t minmoves, | 292 | int8_t minmoves, |
| 172 | int8_t maxmoves, | 293 | int8_t maxmoves, |
| 173 | int64_t maxsolutions, | 294 | int64_t maxsolutions, |
| @@ -178,5 +299,33 @@ int64_t nissy_solve( | |||
| 178 | 299 | ||
| 179 | /* | 300 | /* |
| 180 | Set a global logger function used by this library. | 301 | Set a global logger function used by this library. |
| 302 | |||
| 303 | Parameters: | ||
| 304 | write - A callback writer with the same signature as printf(3). | ||
| 305 | |||
| 306 | Return values: | ||
| 307 | NISSY_OK - Logger set succesfully. | ||
| 308 | NISSY_WARNING_NULL_CALLBACK - The provided callback writer is NULL. | ||
| 181 | */ | 309 | */ |
| 182 | void nissy_setlogger(void (*logger_function)(const char *, ...)); | 310 | int64_t nissy_setlogger( |
| 311 | void (*logger_function)(const char *, ...) | ||
| 312 | ); | ||
| 313 | |||
| 314 | /* | ||
| 315 | Print an explanation of the given error code via the provided callback writer. | ||
| 316 | |||
| 317 | Parameters: | ||
| 318 | error_code - The error code to be explained. It can be any value returned | ||
| 319 | by a function in this library, not necessarily an error. | ||
| 320 | write - A callback writer with the same signature as printf(3). | ||
| 321 | Must be non-NULL. | ||
| 322 | |||
| 323 | Return values: | ||
| 324 | NISSY_OK - The error code is known. | ||
| 325 | NISSY_WARNING_NULL_CALLBACK - The provided callback writer is NULL. | ||
| 326 | NISSY_ERROR_INVALID_CODE - The error code is unknown. | ||
| 327 | */ | ||
| 328 | int64_t nissy_explainerror( | ||
| 329 | int64_t error_code, | ||
| 330 | void (*write)(const char *, ...) | ||
| 331 | ); | ||
