src/core/serialize.c (view raw)
1/* Copyright (c) 2013-2016 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "serialize.h"
7
8#include "util/vfs.h"
9
10struct mStateExtdataHeader {
11 uint32_t tag;
12 int32_t size;
13 int64_t offset;
14};
15
16bool mStateExtdataInit(struct mStateExtdata* extdata) {
17 memset(extdata->data, 0, sizeof(extdata->data));
18 return true;
19}
20
21void mStateExtdataDeinit(struct mStateExtdata* extdata) {
22 size_t i;
23 for (i = 1; i < EXTDATA_MAX; ++i) {
24 if (extdata->data[i].data && extdata->data[i].clean) {
25 extdata->data[i].clean(extdata->data[i].data);
26 }
27 }
28}
29
30void mStateExtdataPut(struct mStateExtdata* extdata, enum mStateExtdataTag tag, struct mStateExtdataItem* item) {
31 if (tag == EXTDATA_NONE || tag >= EXTDATA_MAX) {
32 return;
33 }
34
35 if (extdata->data[tag].data && extdata->data[tag].clean) {
36 extdata->data[tag].clean(extdata->data[tag].data);
37 }
38 extdata->data[tag] = *item;
39}
40
41bool mStateExtdataGet(struct mStateExtdata* extdata, enum mStateExtdataTag tag, struct mStateExtdataItem* item) {
42 if (tag == EXTDATA_NONE || tag >= EXTDATA_MAX) {
43 return false;
44 }
45
46 *item = extdata->data[tag];
47 return true;
48}
49
50bool mStateExtdataSerialize(struct mStateExtdata* extdata, struct VFile* vf) {
51 ssize_t position = vf->seek(vf, 0, SEEK_CUR);
52 ssize_t size = sizeof(struct mStateExtdataHeader);
53 size_t i = 0;
54 for (i = 1; i < EXTDATA_MAX; ++i) {
55 if (extdata->data[i].data) {
56 size += sizeof(struct mStateExtdataHeader);
57 }
58 }
59 if (size == sizeof(struct mStateExtdataHeader)) {
60 return true;
61 }
62 struct mStateExtdataHeader* header = malloc(size);
63 position += size;
64
65 size_t j;
66 for (i = 1, j = 0; i < EXTDATA_MAX; ++i) {
67 if (extdata->data[i].data) {
68 STORE_32LE(i, offsetof(struct mStateExtdataHeader, tag), &header[j]);
69 STORE_32LE(extdata->data[i].size, offsetof(struct mStateExtdataHeader, size), &header[j]);
70 STORE_64LE(position, offsetof(struct mStateExtdataHeader, offset), &header[j]);
71 position += extdata->data[i].size;
72 ++j;
73 }
74 }
75 header[j].tag = 0;
76 header[j].size = 0;
77 header[j].offset = 0;
78
79 if (vf->write(vf, header, size) != size) {
80 free(header);
81 return false;
82 }
83 free(header);
84
85 for (i = 1; i < EXTDATA_MAX; ++i) {
86 if (extdata->data[i].data) {
87 if (vf->write(vf, extdata->data[i].data, extdata->data[i].size) != extdata->data[i].size) {
88 return false;
89 }
90 }
91 }
92 return true;
93}
94
95bool mStateExtdataDeserialize(struct mStateExtdata* extdata, struct VFile* vf) {
96 while (true) {
97 struct mStateExtdataHeader buffer, header;
98 if (vf->read(vf, &buffer, sizeof(buffer)) != sizeof(buffer)) {
99 return false;
100 }
101 LOAD_32LE(header.tag, 0, &buffer.tag);
102 LOAD_32LE(header.size, 0, &buffer.size);
103 LOAD_64LE(header.offset, 0, &buffer.offset);
104
105 if (header.tag == EXTDATA_NONE) {
106 break;
107 }
108 if (header.tag >= EXTDATA_MAX) {
109 continue;
110 }
111 ssize_t position = vf->seek(vf, 0, SEEK_CUR);
112 if (vf->seek(vf, header.offset, SEEK_SET) < 0) {
113 return false;
114 }
115 struct mStateExtdataItem item = {
116 .data = malloc(header.size),
117 .size = header.size,
118 .clean = free
119 };
120 if (!item.data) {
121 continue;
122 }
123 if (vf->read(vf, item.data, header.size) != header.size) {
124 free(item.data);
125 continue;
126 }
127 mStateExtdataPut(extdata, header.tag, &item);
128 vf->seek(vf, position, SEEK_SET);
129 };
130 return true;
131}