Initial import
[project/ufp.git] / src / uht.h
1 #ifndef __UHT_H
2 #define __UHT_H
3
4 #include <stdbool.h>
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <libubox/avl.h>
8 #include <libubox/utils.h>
9
10 #define UHT_TYPE_MASK 0xf
11 #define UHT_TYPE_BITS 4
12 #define UHT_ALIGN_BITS 2
13
14 #define UHT_ALIGN_MASK ((1 << UHT_ALIGN_BITS) - 1)
15
16 enum uht_type {
17 UHT_NULL, /* can also be used as value */
18 UHT_STRING,
19 UHT_INT,
20 UHT_DOUBLE,
21 UHT_BOOL,
22 UHT_HASHTBL,
23 UHT_OBJECT,
24 UHT_ARRAY,
25 };
26
27 struct uht_writer {
28 struct avl_tree data;
29 void *buf;
30 size_t buf_ofs;
31 size_t buf_len;
32 };
33
34 uint32_t uht_writer_hashtbl_alloc(struct uht_writer *wr, size_t n_members);
35 void uht_writer_hashtbl_add_element(struct uht_writer *wr, uint32_t hashtbl,
36 const char *key, uint32_t val);
37 void uht_writer_hashtbl_done(struct uht_writer *wr, uint32_t hashtbl);
38
39 uint32_t uht_writer_add_array(struct uht_writer *wr, uint32_t *members, size_t n);
40 uint32_t uht_writer_add_object(struct uht_writer *wr, uint32_t *keys,
41 uint32_t *values, size_t n);
42 uint32_t uht_writer_add_string(struct uht_writer *wr, const char *val);
43 uint32_t uht_writer_add_double(struct uht_writer *wr, double val);
44
45 static inline uint32_t
46 uht_writer_add_bool(struct uht_writer *wr, bool val)
47 {
48 return (((uint32_t)val) << UHT_TYPE_BITS) | UHT_BOOL;
49 }
50
51 uint32_t uht_writer_add_int(struct uht_writer *wr, int64_t val);
52
53 void uht_writer_init(struct uht_writer *wr);
54 int uht_writer_save(struct uht_writer *wr, FILE *out, uint32_t val);
55 void uht_writer_free(struct uht_writer *wr);
56
57 static inline uint32_t
58 uht_entry_offset(uint32_t entry)
59 {
60 return ((entry & ~UHT_TYPE_MASK) >> (UHT_TYPE_BITS - UHT_ALIGN_BITS));
61 }
62
63 static inline void *
64 uht_entry_ptr(void *buf, uint32_t entry)
65 {
66 return buf + uht_entry_offset(entry);
67 }
68
69 static inline enum uht_type
70 uht_entry_type(uint32_t attr)
71 {
72 return attr & UHT_TYPE_MASK;
73 }
74
75 static inline bool
76 uht_entry_valid(size_t len, uint32_t attr)
77 {
78 return uht_entry_offset(attr) + 4 <= len;
79 }
80
81 struct uht_reader {
82 void *data;
83 size_t len;
84 uint32_t val;
85 int fd;
86 };
87
88 struct uht_reader_iter {
89 uint32_t *__data;
90 uint8_t type;
91
92 uint32_t index, size;
93 const char *key;
94 uint32_t val;
95 };
96
97 int uht_reader_open(struct uht_reader *r, const char *file);
98 void uht_reader_close(struct uht_reader *r);
99
100 static inline const char *
101 uht_reader_get_string(struct uht_reader *r, uint32_t attr)
102 {
103 return uht_entry_ptr(r->data, attr);
104 }
105
106 static inline int64_t
107 uht_reader_get_int(struct uht_reader *r, uint32_t attr)
108 {
109 return le64_to_cpu(*(int64_t *)uht_entry_ptr(r->data, attr));
110 }
111
112 static inline bool
113 uht_reader_get_bool(struct uht_reader *r, uint32_t attr)
114 {
115 return !!(attr >> UHT_TYPE_BITS);
116 }
117
118 static inline double
119 uht_reader_get_double(struct uht_reader *r, uint32_t attr)
120 {
121 union {
122 double d;
123 uint64_t u64;
124 } v = {
125 .u64 = le64_to_cpu(*(uint64_t *)uht_entry_ptr(r->data, attr))
126 };
127 return v.d;
128 }
129
130 void __uht_object_iter_next(struct uht_reader *r, struct uht_reader_iter *iter);
131 struct uht_reader_iter __uht_object_iter_init(struct uht_reader *r, uint32_t attr);
132 uint32_t uht_reader_hashtbl_lookup(struct uht_reader *r, uint32_t hashtbl,
133 const char *key);
134
135 #define uht_for_each(r, iter, attr) \
136 for (struct uht_reader_iter iter = __uht_object_iter_init(r, attr); \
137 iter.index < iter.size; __uht_object_iter_next(r, &iter), iter.index++)
138
139 #endif