Merge pull request #5 from lioncash/fcc

hecl/FourCC: Remove undefined behavior and make rest of interface constexpr where applicable
This commit is contained in:
Phillip Stephens 2019-08-15 07:47:29 -07:00 committed by GitHub
commit 401ef19682
3 changed files with 44 additions and 36 deletions

View File

@ -18,28 +18,36 @@ class FourCC {
protected: protected:
union { union {
char fcc[4]; char fcc[4];
uint32_t num; uint32_t num = 0;
}; };
public: public:
constexpr FourCC() /* Sentinel FourCC */ // Sentinel FourCC
: num(0) {} constexpr FourCC() noexcept = default;
constexpr FourCC(const FourCC& other) : num(other.num) {} constexpr FourCC(const FourCC& other) noexcept = default;
constexpr FourCC(const char* name) : num(*(uint32_t*)name) {} constexpr FourCC(FourCC&& other) noexcept = default;
constexpr FourCC(uint32_t n) : num(n) {} constexpr FourCC(const char* name) noexcept : fcc{name[0], name[1], name[2], name[3]} {}
bool operator==(const FourCC& other) const { return num == other.num; } constexpr FourCC(uint32_t n) noexcept : num(n) {}
bool operator!=(const FourCC& other) const { return num != other.num; }
bool operator==(const char* other) const { return num == *(uint32_t*)other; } constexpr FourCC& operator=(const FourCC&) noexcept = default;
bool operator!=(const char* other) const { return num != *(uint32_t*)other; } constexpr FourCC& operator=(FourCC&&) noexcept = default;
bool operator==(int32_t other) const { return num == uint32_t(other); }
bool operator!=(int32_t other) const { return num != uint32_t(other); } constexpr bool operator==(const FourCC& other) const { return num == other.num; }
bool operator==(uint32_t other) const { return num == other; } constexpr bool operator!=(const FourCC& other) const { return !operator==(other); }
bool operator!=(uint32_t other) const { return num != other; } constexpr bool operator==(const char* other) const {
std::string toString() const { return std::string(fcc, 4); } return other[0] == fcc[0] && other[1] == fcc[1] && other[2] == fcc[2] && other[3] == fcc[3];
uint32_t toUint32() const { return num; } }
const char* getChars() const { return fcc; } constexpr bool operator!=(const char* other) const { return !operator==(other); }
char* getChars() { return fcc; } constexpr bool operator==(int32_t other) const { return num == uint32_t(other); }
bool IsValid() const { return num != 0; } constexpr bool operator!=(int32_t other) const { return !operator==(other); }
constexpr bool operator==(uint32_t other) const { return num == other; }
constexpr bool operator!=(uint32_t other) const { return !operator==(other); }
std::string toString() const { return std::string(std::begin(fcc), std::end(fcc)); }
constexpr uint32_t toUint32() const { return num; }
constexpr const char* getChars() const { return fcc; }
constexpr char* getChars() { return fcc; }
constexpr bool IsValid() const { return num != 0; }
}; };
#define FOURCC(chars) FourCC(SBIG(chars)) #define FOURCC(chars) FourCC(SBIG(chars))
@ -55,25 +63,25 @@ public:
AT_DECL_EXPLICIT_DNA_YAML AT_DECL_EXPLICIT_DNA_YAML
}; };
template <> template <>
inline void DNAFourCC::Enumerate<BigDNA::Read>(typename Read::StreamT& r) { inline void DNAFourCC::Enumerate<BigDNA::Read>(Read::StreamT& r) {
r.readUBytesToBuf(fcc, 4); r.readUBytesToBuf(fcc, std::size(fcc));
} }
template <> template <>
inline void DNAFourCC::Enumerate<BigDNA::Write>(typename Write::StreamT& w) { inline void DNAFourCC::Enumerate<BigDNA::Write>(Write::StreamT& w) {
w.writeUBytes((atUint8*)fcc, 4); w.writeBytes(fcc, std::size(fcc));
} }
template <> template <>
inline void DNAFourCC::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& r) { inline void DNAFourCC::Enumerate<BigDNA::ReadYaml>(ReadYaml::StreamT& r) {
std::string rs = r.readString(nullptr); const std::string rs = r.readString(nullptr);
strncpy(fcc, rs.c_str(), 4); rs.copy(fcc, std::size(fcc));
} }
template <> template <>
inline void DNAFourCC::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& w) { inline void DNAFourCC::Enumerate<BigDNA::WriteYaml>(WriteYaml::StreamT& w) {
w.writeString(nullptr, std::string(fcc, 4)); w.writeString(nullptr, std::string_view{fcc, std::size(fcc)});
} }
template <> template <>
inline void DNAFourCC::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) { inline void DNAFourCC::Enumerate<BigDNA::BinarySize>(BinarySize::StreamT& s) {
s += 4; s += std::size(fcc);
} }
} // namespace hecl } // namespace hecl
@ -85,7 +93,7 @@ struct hash<hecl::FourCC> {
}; };
} // namespace std } // namespace std
FMT_CUSTOM_FORMATTER(hecl::FourCC, "{:c}{:c}{:c}{:c}", FMT_CUSTOM_FORMATTER(hecl::FourCC, "{:c}{:c}{:c}{:c}", obj.getChars()[0], obj.getChars()[1], obj.getChars()[2],
obj.getChars()[0], obj.getChars()[1], obj.getChars()[2], obj.getChars()[3]) obj.getChars()[3])
FMT_CUSTOM_FORMATTER(hecl::DNAFourCC, "{:c}{:c}{:c}{:c}", FMT_CUSTOM_FORMATTER(hecl::DNAFourCC, "{:c}{:c}{:c}{:c}", obj.getChars()[0], obj.getChars()[1], obj.getChars()[2],
obj.getChars()[0], obj.getChars()[1], obj.getChars()[2], obj.getChars()[3]) obj.getChars()[3])

View File

@ -17,7 +17,7 @@
namespace hecl::Database { namespace hecl::Database {
logvisor::Module LogModule("hecl::Database"); logvisor::Module LogModule("hecl::Database");
static const hecl::FourCC HECLfcc("HECL"); constexpr hecl::FourCC HECLfcc("HECL");
/********************************************** /**********************************************
* Project::ConfigFile * Project::ConfigFile

View File

@ -264,7 +264,7 @@ ProjectRootPath SearchForProject(SystemStringView path) {
fclose(fp); fclose(fp);
if (readSize != 4) if (readSize != 4)
continue; continue;
static const hecl::FourCC hecl("HECL"); static constexpr hecl::FourCC hecl("HECL");
if (hecl::FourCC(magic) != hecl) if (hecl::FourCC(magic) != hecl)
continue; continue;
return ProjectRootPath(testPath); return ProjectRootPath(testPath);