Browse Source

feat: custom exception for codec

master
Dnomd343 2 years ago
parent
commit
0f96e74176
  1. 3
      src/klotski_core/common_code/common_code.cc
  2. 16
      src/klotski_core/common_code/common_code.h
  3. 7
      src/klotski_core/common_code/serialize.cc
  4. 3
      src/klotski_core/raw_code/convert.cc
  5. 3
      src/klotski_core/raw_code/raw_code.cc
  6. 11
      src/klotski_core/raw_code/raw_code.h
  7. 8
      src/klotski_core/short_code/serialize.cc
  8. 2
      src/klotski_core/short_code/short_code.cc
  9. 12
      src/klotski_core/short_code/short_code.h
  10. 3
      test/codec/common_code.cc
  11. 1
      test/codec/raw_code.cc
  12. 23
      test/codec/short_code.cc
  13. 22
      test/ffi/codec.cc

3
src/klotski_core/common_code/common_code.cc

@ -1,4 +1,3 @@
#include <stdexcept>
#include "common.h"
#include "common_code.h"
@ -48,7 +47,7 @@ namespace klotski {
CommonCode::CommonCode(uint64_t common_code) {
if (!CommonCode::check(common_code)) { // check input common code
throw std::invalid_argument("invalid common code");
throw klotski::CommonCodeException("common code invalid");
}
code = common_code;
}

16
src/klotski_core/common_code/common_code.h

@ -38,9 +38,9 @@
/// Eg1:
/// % # # % 2x2 -> head = 1
/// % # # % 2x1 2x1 2x1 1x2 2x1 1x1 1x1 1x1 space space 1x1 ... ... ... ... ...
/// @ $ $ @ 10 10 10 01 10 11 11 11 00 00 11 00 00 00 00 00
/// @ & * @ 1010 1001 1011 1111 0000 1100 0000 0000
/// * & A 9 B F 0 C 0 0
/// @ $ $ @ 10 10 10 01 10 11 11 11 00 00 11 00 00 00 00 00
/// @ & * @ 1010 1001 1011 1111 0000 1100 0000 0000
/// * & A 9 B F 0 C 0 0
/// CommonCode = 0x1A9BF0C00 -> "1A9BF0C"
/// Eg2:
@ -54,14 +54,22 @@
#include <string>
#include <cstdint>
#include <ostream>
#include <stdexcept>
#include "raw_code.h"
#include "short_code.h"
namespace klotski {
/// import for convert interface
// import for convert interface
class RawCode;
class ShortCode;
class CommonCodeException : public std::runtime_error {
public:
CommonCodeException() : std::runtime_error("invalid common code") {}
explicit CommonCodeException(const std::string &msg) : std::runtime_error(msg) {}
~CommonCodeException() noexcept override = default;
};
class CommonCode {
public:
bool valid() const;

7
src/klotski_core/common_code/serialize.cc

@ -1,6 +1,7 @@
#include "common_code.h"
using klotski::CommonCode;
using klotski::CommonCodeException;
inline uint8_t binary_count(uint32_t bin) { // get number of non-zero bits
bin -= (bin >> 1) & 0x55'55'55'55;
@ -37,7 +38,7 @@ std::string CommonCode::to_string(bool shorten) const { // convert uint64_t code
CommonCode::CommonCode(const std::string &common_code) { // convert from 1 ~ 9 bits string
/// check string length
if (common_code.length() > 9 || common_code.empty()) { // check string length
throw std::invalid_argument("common code format error");
throw CommonCodeException("common code should length 1 ~ 9");
}
/// check every characters
uint64_t result = 0;
@ -50,13 +51,13 @@ CommonCode::CommonCode(const std::string &common_code) { // convert from 1 ~ 9 b
} else if (bit >= 'a' && bit <= 'z') { // a ~ z
result |= (bit - 87);
} else {
throw std::invalid_argument("common code format error"); // unknown characters
throw CommonCodeException("common code with invalid character"); // unknown character
}
}
result <<= (9 - common_code.length()) * 4; // low-bits fill with zero
/// check whether common code is valid
if (!CommonCode::check(result)) { // check converted common code
throw std::invalid_argument("invalid common code");
throw CommonCodeException("common code invalid");
}
code = result;
}

3
src/klotski_core/raw_code/convert.cc

@ -4,11 +4,12 @@
using klotski::RawCode;
using klotski::CommonCode;
using klotski::RawCodeException;
/// RawCode to CommonCode
CommonCode RawCode::to_common_code() const {
if (!RawCode::check(code)) {
throw std::runtime_error("invalid raw code");
throw RawCodeException("raw code invalid");
}
/// pass raw code checker -> common code must valid
return CommonCode::unsafe_create(RawCode::compact(code));

3
src/klotski_core/raw_code/raw_code.cc

@ -1,4 +1,3 @@
#include <stdexcept>
#include "common.h"
#include "raw_code.h"
@ -56,7 +55,7 @@ namespace klotski {
RawCode::RawCode(uint64_t raw_code) {
if (!RawCode::check(raw_code)) { // check input raw code
throw std::invalid_argument("invalid raw code");
throw klotski::RawCodeException("raw code invalid");
}
code = raw_code;
}

11
src/klotski_core/raw_code/raw_code.h

@ -37,11 +37,18 @@
#include <string>
#include <cstdint>
#include <ostream>
#include <stdexcept>
#include "common_code.h"
namespace klotski {
/// import for convert interface
class CommonCode;
class CommonCode; // import for convert interface
class RawCodeException : public std::runtime_error {
public:
RawCodeException() : std::runtime_error("invalid raw code") {}
explicit RawCodeException(const std::string &msg) : std::runtime_error(msg) {}
~RawCodeException() noexcept override = default;
};
class RawCode {
public:

8
src/klotski_core/short_code/serialize.cc

@ -1,8 +1,8 @@
#include <stdexcept>
#include "short_code.h"
#include "serialize_chars.h"
using klotski::ShortCode;
using klotski::ShortCodeException;
ShortCode ShortCode::from_string(const std::string &short_code) {
return ShortCode(short_code); // convert from string
@ -21,7 +21,7 @@ std::string ShortCode::to_string() const { // encode as 5-bits string
ShortCode::ShortCode(const std::string &short_code) { // 5-bits string decode
if (short_code.length() != 5) { // check string length
throw std::invalid_argument("short code format error");
throw ShortCodeException("short code should length 5");
}
uint64_t result = 0;
for (auto bit : short_code) {
@ -32,12 +32,12 @@ ShortCode::ShortCode(const std::string &short_code) { // 5-bits string decode
if (bit >= '1' && bit <= 'Z') { // valid characters
result += (bit = SHORT_CODE_TABLE_REV[bit - 49]); // table convert
if (bit == -1) {
throw std::invalid_argument("short code format error"); // unknown characters
throw ShortCodeException("short code with invalid character"); // unknown character
}
}
}
if (!ShortCode::check(result)) { // check converted short code
throw std::invalid_argument("invalid short code");
throw ShortCodeException("short code invalid");
}
code = result; // apply convert result
}

2
src/klotski_core/short_code/short_code.cc

@ -45,7 +45,7 @@ namespace klotski {
ShortCode::ShortCode(uint32_t short_code) {
if (!ShortCode::check(short_code)) { // check input short code
throw std::invalid_argument("invalid short code");
throw klotski::ShortCodeException("short code invalid");
}
code = short_code;
}

12
src/klotski_core/short_code/short_code.h

@ -25,11 +25,19 @@
#include <string>
#include <cstdint>
#include <ostream>
#include <stdexcept>
#include <utility>
#include "common_code.h"
namespace klotski {
/// import for convert interface
class CommonCode;
class CommonCode; // import for convert interface
class ShortCodeException : public std::runtime_error {
public:
ShortCodeException() : std::runtime_error("invalid short code") {}
explicit ShortCodeException(const std::string &msg) : std::runtime_error(msg) {}
~ShortCodeException() noexcept override = default;
};
class ShortCode {
public:

3
test/codec/common_code.cc

@ -9,8 +9,9 @@ using klotski::AllCases;
using klotski::ShortCode;
using klotski::CommonCode;
const static uint64_t TEST_CODE = 0x1A9BF0C00;
const static uint64_t TEST_CODE = 0x1'A9BF'0C00;
const static std::string TEST_CODE_STR = "1A9BF0C00";
const static uint64_t TEST_ERR_CODE = 0x1'2190'2300;
// TODO: test some invalid cases

1
test/codec/raw_code.cc

@ -8,6 +8,7 @@ using klotski::AllCases;
using klotski::CommonCode;
const static uint64_t TEST_CODE = 0x0603'EDF5'CAFF'F5E2;
const static uint64_t TEST_ERR_CODE = 0x0A34'182B'3810'2D21;
// TODO: test some invalid cases

23
test/codec/short_code.cc

@ -9,10 +9,29 @@ using klotski::ShortCode;
using klotski::CommonCode;
using klotski::BasicRanges;
const static uint64_t TEST_CODE = 4091296;
const static uint32_t TEST_CODE = 4091296;
const static std::string TEST_CODE_STR = "4WVE1";
// TODO: test some invalid cases
inline void SHOULD_PANIC(const std::function<void(void)> &func) {
bool panic_flag = false;
try {
func();
} catch (klotski::ShortCodeException&) {
panic_flag = true;
}
EXPECT_EQ(panic_flag, true);
}
TEST(ShortCode, invalid) {
EXPECT_NE(ShortCode::check(29670987), true);
std::cout << ShortCode::from_string("R50EH") << std::endl;
SHOULD_PANIC([](){ ShortCode::from_string("R50EH"); }); // with invalid `0`
// SHOULD_PANIC([](){ ShortCode::from_string("123456"); }); // length != 5
// SHOULD_PANIC([](){ ShortCode::from_string("Z9EFV"); }); // out of short code range
}
TEST(ShortCode, speed_up) {
std::thread threads[4];

22
test/ffi/codec.cc

@ -1,12 +1,23 @@
#include "klotski.h"
#include "raw_code.h"
#include "all_cases.h"
#include "short_code.h"
#include "common_code.h"
#include "gtest/gtest.h"
using klotski::RawCode;
using klotski::AllCases;
using klotski::ShortCode;
using klotski::BasicRanges;
const static uint32_t TEST_SHORT_CODE_OK = 4091296;
const static uint64_t TEST_COMMON_CODE_OK = 0x1'A9BF'0C00;
const static uint64_t TEST_RAW_CODE_OK = 0x0603'EDF5'CAFF'F5E2;
const static uint32_t TEST_SHORT_CODE_ERR = 29670987;
const static uint64_t TEST_COMMON_CODE_ERR = 0x1'2190'2300;
const static uint64_t TEST_RAW_CODE_ERR = 0x0A34'182B'3810'2D21;
TEST(FFI, codec_warm_up) {
// short code normal mode check
EXPECT_EQ(is_short_code_available(), BasicRanges::status() == BasicRanges::AVAILABLE);
@ -20,3 +31,14 @@ TEST(FFI, codec_warm_up) {
EXPECT_EQ(is_short_code_available_fast(), true);
EXPECT_EQ(is_short_code_available_fast(), AllCases::status() == AllCases::AVAILABLE);
}
TEST(FFI, codec_checker) {
EXPECT_EQ(raw_code_check(TEST_RAW_CODE_OK), true);
EXPECT_NE(raw_code_check(TEST_RAW_CODE_ERR), true);
EXPECT_EQ(short_code_check(TEST_SHORT_CODE_OK), true);
EXPECT_NE(short_code_check(TEST_SHORT_CODE_ERR), true);
EXPECT_EQ(common_code_check(TEST_COMMON_CODE_OK), true);
EXPECT_NE(common_code_check(TEST_COMMON_CODE_ERR), true);
}

Loading…
Cancel
Save