nissy.cpp (5523B)
1 /* 2 C++20 interface for nissy. 3 4 TODO: add more documentation (here and in README.md) 5 */ 6 7 #include "./nissy.h" 8 9 #include <fstream> 10 11 extern "C" { 12 long long nissy_inverse(const char *, char *); 13 long long nissy_applymoves(const char *, const char *, char *); 14 long long nissy_applytrans(const char *, const char *, char *); 15 long long nissy_getcube(long long, long long, long long, long long, 16 long long, const char *, char *); 17 long long nissy_solverinfo(const char *, char *); 18 long long nissy_gendata(const char *, unsigned long long, 19 unsigned char *); 20 long long nissy_checkdata(const char *, unsigned long long, 21 const unsigned char *); 22 long long nissy_solve(const char *, const char *, unsigned, unsigned, 23 unsigned, unsigned, unsigned, unsigned, unsigned long long, 24 const unsigned char *, unsigned, char *, long long *, 25 int (*)(void *), void *); 26 long long nissy_countmoves(const char *); 27 long long nissy_setlogger(void (*)(const char *, void *), void *); 28 } 29 30 namespace nissy { 31 32 /* Definition of constants with const qualifier */ 33 const nissflag nissflag::NORMAL{1}; 34 const nissflag nissflag::INVERSE{2}; 35 const nissflag nissflag::MIXED{4}; 36 const nissflag nissflag::LINEAR{3}; 37 const nissflag nissflag::ALL{7}; 38 39 const error error::OK{0}; 40 const error error::UNSOLVABLE_WARNING{-1}; 41 const error error::UNSOLVABLE_ERROR{-11}; 42 const error error::INVALID_CUBE{-10}; 43 const error error::INVALID_MOVES{-20}; 44 const error error::INVALID_TRANS{-30}; 45 const error error::INVALID_SOLVER{-50}; 46 const error error::NULL_POINTER{-60}; 47 const error error::BUFFER_SIZE{-61}; 48 const error error::DATA{-70}; 49 const error error::OPTIONS{-80}; 50 const error error::UNKNOWN{-999}; 51 52 const status status::RUN{0}; 53 const status status::STOP{1}; 54 const status status::PAUSE{2}; 55 56 namespace size { 57 constexpr size_t CUBE = 24; 58 constexpr size_t TRANSFORMATION = 12; 59 constexpr size_t SOLVE_STATS = 10; 60 constexpr size_t DATAID = 255; 61 } 62 63 bool error::ok() const { return value >= 0; } 64 65 cube::cube() {} 66 67 error cube::move(const std::string& moves) 68 { 69 char result[size::CUBE]; 70 long long err = nissy_applymoves( 71 m_str.c_str(), moves.c_str(), result); 72 if (err < 0) 73 return error{err}; 74 m_str = result; 75 return error::OK; 76 } 77 78 error cube::transform(const std::string& trans) 79 { 80 char result[size::CUBE]; 81 long long err = nissy_applytrans( 82 m_str.c_str(), trans.c_str(), result); 83 if (err < 0) 84 return error{err}; 85 m_str = result; 86 return error::OK; 87 } 88 89 void cube::invert() 90 { 91 char result[size::CUBE]; 92 nissy_inverse(m_str.c_str(), result); 93 m_str = result; 94 } 95 96 std::string cube::to_string() const { return m_str; } 97 98 std::variant<cube, error> 99 cube::from_string(const std::string& str) 100 { 101 /* Check that the cube is valid by making a single move */ 102 char result[size::CUBE]; 103 auto err = nissy_applymoves(str.c_str(), "U", result); 104 if (err < 0) 105 return error{err}; 106 107 cube c; 108 c.m_str = str; 109 return c; 110 } 111 112 std::variant<cube, error> 113 cube::get(long long ep, long long eo, 114 long long cp, long long co, long long orien) 115 { 116 return get(ep, eo, cp, co, orien, "fix"); 117 } 118 119 std::variant<cube, error> 120 cube::get(long long ep, long long eo, long long cp, long long co, 121 long long orient, const std::string& options) 122 { 123 char result[size::CUBE]; 124 cube c; 125 auto err = nissy_getcube(ep, eo, cp, co, orient, 126 options.c_str(), result); 127 if (err < 0) 128 return error{err}; 129 c.m_str = result; 130 return c; 131 } 132 133 error solver::generate_data() 134 { 135 data.resize(size); 136 auto err = nissy_gendata(name.c_str(), 137 size, reinterpret_cast<unsigned char *>(data.data())); 138 return error{err}; 139 } 140 141 void solver::read_data(std::ifstream& ifs) 142 { 143 data.resize(size); 144 ifs.read(reinterpret_cast<char *>(data.data()), size); 145 } 146 147 error solver::check_data() 148 { 149 auto err_value = nissy_checkdata(name.c_str(), data.size(), 150 reinterpret_cast<const unsigned char *>(data.data())); 151 error err{err_value}; 152 data_checked = err.ok(); 153 return err; 154 } 155 156 void solver::unload_data() 157 { 158 data.resize(0); 159 } 160 161 solver::solve_result 162 solver::solve(const cube& cube, nissflag niss, unsigned minmoves, 163 unsigned maxmoves, unsigned maxsols, unsigned optimal, 164 unsigned threads, int (*poll_status)(void *), 165 void *poll_status_data) const 166 { 167 long long stats[size::SOLVE_STATS]; 168 solver::solve_result result; 169 170 if (maxsols == 0) { 171 result.solutions = ""; 172 result.err = error::OK; 173 return result; 174 } 175 176 const size_t len = 3 * (maxmoves+1) * maxsols; 177 result.solutions.resize(len); 178 179 auto err = nissy_solve(cube.to_string().c_str(), 180 name.c_str(), niss.value, minmoves, maxmoves, maxsols, 181 optimal, threads, data.size(), 182 reinterpret_cast<const unsigned char *>(data.data()), len, 183 result.solutions.data(), stats, 184 poll_status, poll_status_data); 185 186 int size = result.solutions.find_first_of('\0'); 187 result.solutions.resize(size); 188 result.err = error{err}; 189 190 return result; 191 } 192 193 std::variant<solver, error> solver::get(const std::string& name) 194 { 195 char dataid[size::DATAID]; 196 auto err = nissy_solverinfo(name.c_str(), dataid); 197 if (err < 0) 198 return error{err}; 199 solver s(name); 200 s.size = (unsigned)err; 201 s.id = std::string{dataid}; 202 return s; 203 } 204 205 solver::solver(const std::string& str) : name{str} {} 206 207 error count_moves(const std::string& moves) 208 { 209 auto err = nissy_countmoves(moves.c_str()); 210 return error{err}; 211 } 212 213 void set_logger(void (*log)(const char *, void *), void *data) 214 { 215 nissy_setlogger(log, data); 216 } 217 }