-
Notifications
You must be signed in to change notification settings - Fork 2
/
object.c
211 lines (170 loc) · 4.97 KB
/
object.c
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "jzon.h"
void jzon_free(struct jzon *value);
void set_error(enum jzon_error_type *error, enum jzon_error_type error_type);
void *jzon_calloc(size_t count, size_t size, enum jzon_error_type *error);
char *jzon_strdup(const char *s1, enum jzon_error_type *error);
static int max(int lhs, int rhs)
{
return lhs > rhs ? lhs : rhs;
}
static int height(struct jzon_object *object)
{
if (!object) {
return 0;
}
return object->height;
}
static int balance(struct jzon_object *object)
{
if (!object) {
return 0;
}
return height(object->left) - height(object->right);
}
static struct jzon_object *rotate_left(struct jzon_object *object)
{
struct jzon_object *right = object->right;
struct jzon_object *left = right->left;
right->left = object;
object->right = left;
object->height = max(height(object->left), height(object->right)) + 1;
right->height = max(height(right->left), height(right->right)) + 1;
return right;
}
static struct jzon_object *rotate_right(struct jzon_object *object)
{
struct jzon_object *left = object->left;
struct jzon_object *right = left->right;
left->right = object;
object->left = right;
object->height = max(height(object->left), height(object->right)) + 1;
left->height = max(height(left->left), height(left->right)) + 1;
return left;
}
static struct jzon_object *object_create(const char *key, struct jzon *value,
enum jzon_error_type *error)
{
if (!key) {
set_error(error, JZONE_INVALID_INPUT);
return NULL;
}
if (!value) {
set_error(error, JZONE_INVALID_INPUT);
return NULL;
}
enum jzon_error_type calloc_error;
struct jzon_object *object = jzon_calloc(1, sizeof(struct jzon_object),
&calloc_error);
if (calloc_error != JZONE_NONE) {
set_error(error, calloc_error);
return NULL;
}
enum jzon_error_type strdup_error;
object->key = jzon_strdup(key, &strdup_error);
if (strdup_error != JZONE_NONE) {
free(object);
set_error(error, strdup_error);
return NULL;
}
object->value = value;
object->height = 1;
object->left = NULL;
object->right = NULL;
set_error(error, JZONE_NONE);
return object;
}
struct jzon_object *object_put(struct jzon_object *object, const char *key,
struct jzon *value, enum jzon_error_type *error)
{
if (!key) {
set_error(error, JZONE_INVALID_INPUT);
return NULL;
}
if (!value) {
set_error(error, JZONE_INVALID_INPUT);
return NULL;
}
if (!object) {
return object_create(key, value, error);
}
enum jzon_error_type object_put_error = JZONE_NONE;
int cmp = strcmp(key, object->key);
if (cmp == 0) {
jzon_free(object->value);
object->value = value;
return object;
} else if (cmp < 0) {
object->left = object_put(object->left, key, value, &object_put_error);
} else {
object->right = object_put(object->right, key, value, &object_put_error);
}
if (object_put_error != JZONE_NONE) {
set_error(error, object_put_error);
return NULL;
}
object->height = max(height(object->left), height(object->right)) + 1;
int b = balance(object);
/* left left */
if (b > 1 && strcmp(key, object->left->key) < 0) {
return rotate_right(object);
}
/* left right */
if (b > 1 && strcmp(key, object->left->key) > 0) {
object->left = rotate_left(object->left);
return rotate_right(object);
}
/* right right */
if (b < -1 && strcmp(key, object->right->key) > 0) {
return rotate_left(object);
}
/* right left */
if (b < -1 && strcmp(key, object->right->key) < 0) {
object->right = rotate_right(object->right);
return rotate_left(object);
}
set_error(error, JZONE_NONE);
return object;
}
struct jzon *object_get(struct jzon_object *object, const char *key,
enum jzon_error_type *error)
{
if (!object) {
set_error(error, JZONE_INVALID_INPUT);
return NULL;
}
if (!key) {
set_error(error, JZONE_INVALID_INPUT);
return NULL;
}
struct jzon_object *temp = object;
while (temp) {
int cmp = strcmp(key, temp->key);
if (cmp == 0) {
set_error(error, JZONE_NONE);
return temp->value;
} else if (cmp < 0) {
temp = temp->left;
} else {
temp = temp->right;
}
}
set_error(error, JZONE_NO_ENTRY);
return NULL;
}
void object_free(struct jzon_object *object)
{
if (object) {
if (object->left) {
object_free(object->left);
}
if (object->right) {
object_free(object->right);
}
free(object->key);
jzon_free(object->value);
free(object);
}
}