summaryrefslogtreecommitdiffhomepage
path: root/dev/kernel/NeKit/Json.h
blob: 1cfa5a8a2f86b97184972f9826c2b7eb71ef3193 (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, licensed under the Apache 2.0 license.

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

#pragma once

/// @brief Kernel JSON API.

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

#define kNeJsonMaxLen (8196)
#define kNeJsonLen (256)
#define kNeJsonNullArr "[]"
#define kNeJsonNullObj "{}"

namespace Kernel {
/// @brief JavaScript object class
class JsonObject final {
 public:
  explicit JsonObject() {
    auto           len = kNeJsonMaxLen;
    KBasicString<> key = KString(len);
    key += kNeJsonNullObj;

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

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

  ~JsonObject() = default;

  NE_COPY_DEFAULT(JsonObject)

  Bool& IsUndefined() { return fUndefined; }

 private:
  Bool           fUndefined;  // is this instance undefined?
  KBasicString<> fKey;
  KBasicString<> fValue;

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

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

  static JsonObject kNull;
};

/// @brief JsonObject stream reader helper.
struct JsonStreamReader final {
  STATIC JsonObject 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 JsonObject::kNull;

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

      probe_value = true;
    }

    SizeT len = rt_string_len(full_array);

    SizeT key_len   = 0;
    SizeT value_len = 0;

    JsonObject type(kNeJsonMaxLen, kNeJsonMaxLen);

    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, JsonObject>;
}  // namespace Kernel