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