summary refs log tree commit diff stats
path: root/generator/godot_variant.cpp
blob: dd1ad33030bc0b7c11e0b4c02e51ff0d92e1d956 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "godot_variant.h"

#include <stdexcept>

bool GodotVariant::operator<(const GodotVariant& rhs) const {
  if (value.index() != rhs.value.index()) {
    return value.index() < rhs.value.index();
  }

  if (const int32_t* pval = std::get_if<int32_t>(&value)) {
    return *pval < std::get<int32_t>(rhs.value);
  } else if (const std::string* pval = std::get_if<std::string>(&value)) {
    return *pval < std::get<std::string>(rhs.value);
  } else if (const std::map<GodotVariant, GodotVariant>* pval =
                 std::get_if<std::map<GodotVariant, GodotVariant>>(&value)) {
    return *pval < std::get<std::map<GodotVariant, GodotVariant>>(rhs.value);
  } else if (const std::vector<GodotVariant>* pval =
                 std::get_if<std::vector<GodotVariant>>(&value)) {
    return *pval < std::get<std::vector<GodotVariant>>(rhs.value);
  }

  throw std::invalid_argument("Incomparable variants.");
}

void GodotVariant::Serialize(std::basic_ostream<char>& output) const {
  if (const int32_t* pval = std::get_if<int32_t>(&value)) {
    uint32_t typebits = 2;
    output.write(reinterpret_cast<char*>(&typebits), 4);
    output.write(reinterpret_cast<const char*>(pval), 4);
  } else if (const std::string* pval = std::get_if<std::string>(&value)) {
    uint32_t typebits = 4;
    output.write(reinterpret_cast<char*>(&typebits), 4);

    uint32_t lengthbits = pval->length();
    output.write(reinterpret_cast<char*>(&lengthbits), 4);

    output.write(pval->data(), pval->length());

    if (pval->length() % 4 != 0) {
      int padding = 4 - (pval->length() % 4);
      for (int i = 0; i < padding; i++) {
        output.put(0);
      }
    }
  } else if (const std::map<GodotVariant, GodotVariant>* pval =
                 std::get_if<std::map<GodotVariant, GodotVariant>>(&value)) {
    uint32_t typebits = 18;
    output.write(reinterpret_cast<char*>(&typebits), 4);

    uint32_t lengthbits = pval->size() & 0x7fffffff;
    output.write(reinterpret_cast<char*>(&lengthbits), 4);

    for (const auto& mapping : *pval) {
      mapping.first.Serialize(output);
      mapping.second.Serialize(output);
    }
  } else if (const std::vector<GodotVariant>* pval =
                 std::get_if<std::vector<GodotVariant>>(&value)) {
    uint32_t typebits = 19;
    output.write(reinterpret_cast<char*>(&typebits), 4);

    uint32_t lengthbits = pval->size() & 0x7fffffff;
    output.write(reinterpret_cast<char*>(&lengthbits), 4);

    for (const auto& entry : *pval) {
      entry.Serialize(output);
    }
  }
}