Skip to content

Commit 44b0fee

Browse files
committed
cppjson::JsonObject primitive, tagged union
Signed-off-by: TymianekPL <tymi@tymi.org>
1 parent a84f4af commit 44b0fee

File tree

3 files changed

+156
-2
lines changed

3 files changed

+156
-2
lines changed

Test/Test.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1-
#include <cppjson/cppjson.hpp>
1+
#include <cppjson/object.hpp>
2+
#include <print>
23

3-
int main() { cppjson::hello_world(); }
4+
int main()
5+
{
6+
cppjson::JsonObject object{};
7+
object.As<std::string>() = "Purr world!";
8+
std::println("{}", object.As<std::string>());
9+
}

cppjson/include/cppjson/object.hpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <cstddef>
5+
#include <algorithm>
6+
#include <string>
7+
#include <cstddef>
8+
9+
namespace cppjson
10+
{
11+
enum struct JsonType
12+
{
13+
Null,
14+
String,
15+
Object,
16+
Number,
17+
Bool,
18+
// TODO: Array
19+
};
20+
21+
class JsonObject
22+
{
23+
public:
24+
explicit JsonObject();
25+
~JsonObject();
26+
27+
template <typename T>
28+
T& As() noexcept(false);
29+
30+
template <typename T>
31+
const T& As() const noexcept(false);
32+
private:
33+
JsonType _dataType{};
34+
std::byte* _dataStorage{};
35+
36+
void Destroy();
37+
template <typename T>
38+
T& DangerousAs() noexcept { return *std::launder(reinterpret_cast<T*>(this->_dataStorage)); }
39+
template <typename T>
40+
const T& DangerousAs() const noexcept { return *std::launder(reinterpret_cast<T*>(this->_dataStorage)); }
41+
};
42+
}

cppjson/src/object.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#include "cppjson/object.hpp"
2+
#include <new>
3+
#include <stdexcept>
4+
5+
constexpr std::size_t DataStorageSize = std::max({ sizeof(std::string), sizeof(cppjson::JsonObject), sizeof(double), sizeof(bool) });
6+
7+
cppjson::JsonObject::JsonObject()
8+
: _dataStorage(static_cast<std::byte*>(::operator new(DataStorageSize)))
9+
{
10+
}
11+
12+
cppjson::JsonObject::~JsonObject()
13+
{
14+
this->Destroy();
15+
::operator delete(this->_dataStorage);
16+
}
17+
18+
void cppjson::JsonObject::Destroy(void)
19+
{
20+
using std::string;
21+
22+
switch (std::exchange(this->_dataType, JsonType::Null))
23+
{
24+
case JsonType::Null:
25+
case JsonType::Number:
26+
case JsonType::Bool: break;
27+
case JsonType::String: DangerousAs<std::string>().~string();
28+
}
29+
}
30+
31+
template<>
32+
std::string& cppjson::JsonObject::As<std::string>() noexcept(false)
33+
{
34+
if (this->_dataType == JsonType::Null)
35+
{
36+
this->_dataType = JsonType::String;
37+
return *new(this->_dataStorage) std::string{};
38+
}
39+
40+
if (this->_dataType != JsonType::String) throw std::logic_error("Cannot convert this object to a string");
41+
return DangerousAs<std::string>();
42+
}
43+
44+
template<>
45+
double& cppjson::JsonObject::As<double>() noexcept(false)
46+
{
47+
if (this->_dataType == JsonType::Null)
48+
{
49+
this->_dataType = JsonType::Number;
50+
return *new(this->_dataStorage) double{};
51+
}
52+
53+
if (this->_dataType != JsonType::Number) throw std::logic_error("Cannot convert this object to a double");
54+
return DangerousAs<double>();
55+
}
56+
57+
template<>
58+
bool& cppjson::JsonObject::As<bool>() noexcept(false)
59+
{
60+
if (this->_dataType == JsonType::Null)
61+
{
62+
this->_dataType = JsonType::Bool;
63+
return *new(this->_dataStorage) bool{};
64+
}
65+
66+
if (this->_dataType != JsonType::Bool) throw std::logic_error("Cannot convert this object to a bool");
67+
return DangerousAs<bool>();
68+
}
69+
70+
template<>
71+
std::nullptr_t& cppjson::JsonObject::As<std::nullptr_t>() noexcept(false)
72+
{
73+
if (std::exchange(this->_dataType, JsonType::Null) == JsonType::Null)
74+
return DangerousAs<std::nullptr_t>();
75+
76+
return *new(this->_dataStorage) std::nullptr_t{};
77+
}
78+
79+
80+
template<>
81+
const std::string& cppjson::JsonObject::As<std::string>() const noexcept(false)
82+
{
83+
if (this->_dataType != JsonType::String) throw std::logic_error("Cannot convert this object to a string");
84+
return DangerousAs<std::string>();
85+
}
86+
87+
template<>
88+
const double& cppjson::JsonObject::As<double>() const noexcept(false)
89+
{
90+
if (this->_dataType != JsonType::Number) throw std::logic_error("Cannot convert this object to a double");
91+
return DangerousAs<double>();
92+
}
93+
94+
template<>
95+
const bool& cppjson::JsonObject::As<bool>() const noexcept(false)
96+
{
97+
if (this->_dataType != JsonType::Bool) throw std::logic_error("Cannot convert this object to a bool");
98+
return DangerousAs<bool>();
99+
}
100+
101+
template<>
102+
const std::nullptr_t& cppjson::JsonObject::As<std::nullptr_t>() const noexcept(false)
103+
{
104+
if (this->_dataType != JsonType::Null) throw std::logic_error("Cannot convert this object to a null");
105+
return DangerousAs<std::nullptr_t>();
106+
}

0 commit comments

Comments
 (0)