Line data Source code
1 : /*
2 : * libpino - pino.c
3 : *
4 : * This file is part of libpino.
5 : *
6 : * Author: Go Kudo <zeriyoshi@gmail.com>
7 : * SPDX-License-Identifier: MIT
8 : */
9 :
10 : #include <stdbool.h>
11 : #include <stddef.h>
12 : #include <stdint.h>
13 : #include <stdio.h>
14 :
15 : #include <pino.h>
16 : #include <pino/handler.h>
17 :
18 : #include "internal/common.h"
19 :
20 1007 : static inline pino_t *pino_create(pino_magic_safe_t magic, pino_handler_t *handler, size_t size)
21 : {
22 : pino_t *pino;
23 :
24 1007 : pino = pmalloc(sizeof(pino_t));
25 1007 : if (!pino) {
26 0 : return NULL;
27 : }
28 :
29 1007 : pmemcpy(pino->magic, magic, sizeof(pino_magic_t));
30 1007 : pino->magic[sizeof(pino_magic_t)] = '\0';
31 1007 : pino->static_fields_size = handler->static_fields_size;
32 1007 : pino->static_fields = pcalloc(1, pino->static_fields_size);
33 :
34 1007 : if (!pino->static_fields) {
35 0 : pfree(pino);
36 :
37 0 : return NULL;
38 : }
39 :
40 1007 : pino->handler = handler;
41 1007 : pino->this = handler->create(size, pino->static_fields);
42 1007 : if (!pino->this) {
43 1 : pfree(pino->static_fields);
44 1 : pfree(pino);
45 1 : return NULL;
46 : }
47 :
48 1006 : return pino;
49 : }
50 :
51 18 : extern bool pino_init(void)
52 : {
53 18 : return pino_handler_init(HANDLER_STEP);
54 : }
55 :
56 18 : extern void pino_free(void)
57 : {
58 18 : pino_handler_free();
59 18 : }
60 :
61 3 : extern size_t pino_serialize_size(const pino_t *pino)
62 : {
63 : size_t handler_size, total_size;
64 :
65 3 : if (!pino || !pino->handler || !pino->handler->serialize_size) {
66 1 : return 0;
67 : }
68 :
69 2 : handler_size = pino->handler->serialize_size(pino->this, pino->static_fields);
70 2 : if (handler_size > SIZE_MAX - sizeof(pino_magic_t) - sizeof(pino_static_fields_size_t) - pino->static_fields_size) {
71 0 : return 0;
72 : }
73 :
74 2 : total_size = handler_size + sizeof(pino_magic_t) + sizeof(pino_static_fields_size_t) + pino->static_fields_size;
75 :
76 2 : return total_size;
77 : }
78 :
79 3 : extern bool pino_serialize(const pino_t *pino, void *dest)
80 : {
81 3 : if (!pino || !dest || !pino->handler || !pino->handler->serialize) {
82 1 : return false;
83 : }
84 :
85 2 : pmemcpy(dest, pino->magic, sizeof(pino_magic_t));
86 2 : pmemcpy_n2l(((char *)dest) + sizeof(pino_magic_t), &pino->static_fields_size, sizeof(pino_static_fields_size_t));
87 :
88 : /* fields always use LE */
89 2 : pmemcpy(((char *)dest) + sizeof(pino_magic_t) + sizeof(pino_static_fields_size_t), pino->static_fields,
90 : pino->static_fields_size);
91 :
92 2 : return pino->handler->serialize(pino->this, pino->static_fields,
93 2 : ((char *)dest) + sizeof(pino_magic_t) + sizeof(pino_static_fields_size_t) +
94 2 : pino->handler->static_fields_size);
95 : }
96 :
97 9 : extern pino_t *pino_unserialize(const void *src, size_t size)
98 : {
99 : pino_t *pino;
100 : pino_handler_t *handler;
101 : pino_magic_safe_t magic;
102 : pino_static_fields_size_t fields_size;
103 :
104 9 : if (!src) {
105 1 : return NULL;
106 : }
107 :
108 8 : if (size < sizeof(pino_magic_t) + sizeof(pino_static_fields_size_t)) {
109 2 : return NULL;
110 : }
111 :
112 6 : pmemcpy(magic, src, sizeof(pino_magic_t));
113 6 : pmemcpy_l2n(&fields_size, ((char *)src) + sizeof(pino_magic_t), sizeof(pino_static_fields_size_t));
114 :
115 6 : if (size < sizeof(pino_magic_t) + sizeof(pino_static_fields_size_t) + fields_size) {
116 1 : return NULL;
117 : }
118 :
119 5 : handler = pino_handler_find(magic);
120 5 : if (!handler) {
121 2 : return NULL;
122 : }
123 :
124 3 : pino = pino_create(magic, handler, size - sizeof(pino_magic_t) - sizeof(pino_static_fields_size_t) - fields_size);
125 3 : if (!pino) {
126 0 : return NULL;
127 : }
128 :
129 : /* always LE */
130 3 : pmemcpy(pino->static_fields, ((char *)src) + sizeof(pino_magic_t) + sizeof(pino_static_fields_size_t), fields_size);
131 3 : if (!handler->unserialize(pino->this, pino->static_fields,
132 3 : ((char *)src) + sizeof(pino_magic_t) + sizeof(pino_static_fields_size_t) + fields_size,
133 : size)) {
134 1 : pino_destroy(pino);
135 1 : return NULL;
136 : }
137 :
138 2 : return pino;
139 : }
140 :
141 1008 : extern pino_t *pino_pack(pino_magic_safe_t magic, const void *src, size_t size)
142 : {
143 : pino_t *pino;
144 : pino_handler_t *handler;
145 :
146 1008 : handler = pino_handler_find(magic);
147 1008 : if (!handler) {
148 4 : return NULL;
149 : }
150 :
151 1004 : pino = pino_create(magic, handler, size);
152 1004 : if (!pino) {
153 1 : return NULL;
154 : }
155 :
156 1003 : if (!handler->pack(pino->this, pino->static_fields, src, size)) {
157 0 : pino_destroy(pino);
158 0 : return NULL;
159 : }
160 :
161 1003 : return pino;
162 : }
163 :
164 5 : extern size_t pino_unpack_size(const pino_t *pino)
165 : {
166 5 : if (!pino || !pino->handler || !pino->handler->unpack_size) {
167 0 : return 0;
168 : }
169 :
170 5 : return pino->handler->unpack_size(pino->this, pino->static_fields);
171 : }
172 :
173 4 : extern bool pino_unpack(const pino_t *pino, void *dest)
174 : {
175 4 : if (!pino || !dest || !pino->handler || !pino->handler->unpack) {
176 0 : return false;
177 : }
178 :
179 4 : return pino->handler->unpack(pino->this, pino->static_fields, dest);
180 : }
181 :
182 1007 : extern void pino_destroy(pino_t *pino)
183 : {
184 1007 : if (!pino) {
185 1 : return;
186 : }
187 :
188 1006 : if (pino->this) {
189 1006 : pino->handler->destroy(pino->this, pino->static_fields);
190 : }
191 :
192 1006 : if (pino->static_fields) {
193 1006 : pfree(pino->static_fields);
194 : }
195 :
196 1006 : pfree(pino);
197 : }
198 :
199 1 : extern uint32_t pino_version_id()
200 : {
201 1 : return (uint32_t)PINO_VERSION_ID;
202 : }
203 :
204 1 : extern pino_buildtime_t pino_buildtime()
205 : {
206 1 : return (pino_buildtime_t)PINO_BUILDTIME;
207 : }
|