summaryrefslogtreecommitdiffhomepage
path: root/dev/kernel/NeKit/Json.h
blob: 2b2c9c043a113e04f0df6861689b46d16a01405a (plain)
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

/* -------------------------------------------

  Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.

------------------------------------------- */

#pragma once

// last-rev: 02/04/25

#include <CompilerKit/CompilerKit.h>
#include <NeKit/Defines.h>
#include <NeKit/KString.h>
#include <NeKit/Stream.h>
#include <NeKit/Utils.h>

#define kJSONMaxLen (8196)
#define kJSONLen (256)
#define kJSONNullArr "[]"
#define kJSONNullObj "{}"

namespace Kernel {
/// @brief JavaScript object class
class Json final {
 public:
  explicit Json() {
    auto    len = kJSONMaxLen;
    KString key = KString(len);
    key += kJSONNullObj;

    this->AsKey()   = key;
    this->AsValue() = key;
  }

  explicit Json(SizeT lhsLen, SizeT rhsLen) : fKey(lhsLen), fValue(rhsLen) {}

  ~Json() = default;

  NE_COPY_DEFAULT(Json)

  Bool& IsUndefined() { return fUndefined; }

 private:
  Bool    fUndefined;  // is this instance undefined?
  KString fKey;
  KString fValue;

 public:
  /// @brief returns the key of the json
  /// @return the key as string view.
  KString& AsKey() { return fKey; }

  /// @brief returns the value of the json.
  /// @return the key as string view.
  KString& AsValue() { return fValue; }

  static Json kNull;
};

/// @brief Json stream reader helper.
struct JsonStreamReader final {
  STATIC Json In(const Char* full_array) {
    auto    start_val   = '{';
    auto    end_val     = '}';
    Boolean probe_value = false;

    if (full_array[0] != start_val) {
      if (full_array[0] != '[') return Json::kNull;

      start_val = '[';
      end_val   = ']';

      probe_value = true;
    }

    SizeT len = rt_string_len(full_array);

    SizeT key_len   = 0;
    SizeT value_len = 0;

    Json type(kJSONMaxLen, kJSONMaxLen);

    for (SizeT i = 1; i < len; ++i) {
      if (full_array[i] == '\r' || full_array[i] == '\n') continue;

      if (probe_value) {
        if (full_array[i] == end_val || full_array[i] == ',') {
          probe_value = false;

          ++value_len;
        } else {
          if (full_array[i] == '\'') {
            type.AsValue().Data()[value_len] = 0;
            break;
          }

          type.AsValue().Data()[value_len] = full_array[i];

          ++value_len;
        }
      } else {
        if (start_val == '[') continue;

        if (full_array[i] == ':') {
          type.AsKey().Data()[key_len] = 0;
          ++key_len;

          ++i;

          while (full_array[i] == ' ' || full_array[i] == '\t') ++i;

          probe_value = true;
        } else {
          type.AsKey().Data()[key_len] = full_array[i];

          ++key_len;
        }
      }
    }

    type.AsValue().Data()[value_len] = 0;

    return type;
  }
};

using JsonStream = Stream<JsonStreamReader, Json>;
}  // namespace Kernel