]>
Commit | Line | Data |
---|---|---|
e1273106 VM |
1 | /** |
2 | * Copyright 2013, GitHub, Inc | |
3 | * Copyright 2009-2013, Daniel Lemire, Cliff Moon, | |
4 | * David McIntosh, Robert Becho, Google Inc. and Veronika Zenz | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version 2 | |
9 | * of the License, or (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
48425792 | 17 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
e1273106 VM |
18 | */ |
19 | #include "git-compat-util.h" | |
20 | #include "ewok.h" | |
be0d9d53 | 21 | #include "strbuf.h" |
e1273106 | 22 | |
e1273106 VM |
23 | int ewah_serialize_to(struct ewah_bitmap *self, |
24 | int (*write_fun)(void *, const void *, size_t), | |
25 | void *data) | |
26 | { | |
27 | size_t i; | |
28 | eword_t dump[2048]; | |
29 | const size_t words_per_dump = sizeof(dump) / sizeof(eword_t); | |
30 | uint32_t bitsize, word_count, rlw_pos; | |
31 | ||
32 | const eword_t *buffer; | |
33 | size_t words_left; | |
34 | ||
35 | /* 32 bit -- bit size for the map */ | |
36 | bitsize = htonl((uint32_t)self->bit_size); | |
37 | if (write_fun(data, &bitsize, 4) != 4) | |
38 | return -1; | |
39 | ||
40 | /** 32 bit -- number of compressed 64-bit words */ | |
41 | word_count = htonl((uint32_t)self->buffer_size); | |
42 | if (write_fun(data, &word_count, 4) != 4) | |
43 | return -1; | |
44 | ||
45 | /** 64 bit x N -- compressed words */ | |
46 | buffer = self->buffer; | |
47 | words_left = self->buffer_size; | |
48 | ||
49 | while (words_left >= words_per_dump) { | |
50 | for (i = 0; i < words_per_dump; ++i, ++buffer) | |
51 | dump[i] = htonll(*buffer); | |
52 | ||
53 | if (write_fun(data, dump, sizeof(dump)) != sizeof(dump)) | |
54 | return -1; | |
55 | ||
56 | words_left -= words_per_dump; | |
57 | } | |
58 | ||
59 | if (words_left) { | |
60 | for (i = 0; i < words_left; ++i, ++buffer) | |
61 | dump[i] = htonll(*buffer); | |
62 | ||
63 | if (write_fun(data, dump, words_left * 8) != words_left * 8) | |
64 | return -1; | |
65 | } | |
66 | ||
67 | /** 32 bit -- position for the RLW */ | |
68 | rlw_pos = (uint8_t*)self->rlw - (uint8_t *)self->buffer; | |
69 | rlw_pos = htonl(rlw_pos / sizeof(eword_t)); | |
70 | ||
71 | if (write_fun(data, &rlw_pos, 4) != 4) | |
72 | return -1; | |
73 | ||
74 | return (3 * 4) + (self->buffer_size * 8); | |
75 | } | |
76 | ||
be0d9d53 NTND |
77 | static int write_strbuf(void *user_data, const void *data, size_t len) |
78 | { | |
79 | struct strbuf *sb = user_data; | |
80 | strbuf_add(sb, data, len); | |
81 | return len; | |
82 | } | |
83 | ||
84 | int ewah_serialize_strbuf(struct ewah_bitmap *self, struct strbuf *sb) | |
85 | { | |
86 | return ewah_serialize_to(self, write_strbuf, sb); | |
87 | } | |
88 | ||
9d2e330b | 89 | ssize_t ewah_read_mmap(struct ewah_bitmap *self, const void *map, size_t len) |
e1273106 | 90 | { |
a0a2f7d7 | 91 | const uint8_t *ptr = map; |
9d2e330b | 92 | size_t data_len; |
6b5b3a27 | 93 | size_t i; |
a201c20b | 94 | |
9d2e330b JK |
95 | if (len < sizeof(uint32_t)) |
96 | return error("corrupt ewah bitmap: eof before bit size"); | |
a201c20b VM |
97 | self->bit_size = get_be32(ptr); |
98 | ptr += sizeof(uint32_t); | |
9d2e330b | 99 | len -= sizeof(uint32_t); |
a201c20b | 100 | |
9d2e330b JK |
101 | if (len < sizeof(uint32_t)) |
102 | return error("corrupt ewah bitmap: eof before length"); | |
a201c20b VM |
103 | self->buffer_size = self->alloc_size = get_be32(ptr); |
104 | ptr += sizeof(uint32_t); | |
9d2e330b | 105 | len -= sizeof(uint32_t); |
e1273106 | 106 | |
08c95df8 | 107 | REALLOC_ARRAY(self->buffer, self->alloc_size); |
e1273106 | 108 | |
a201c20b VM |
109 | /* |
110 | * Copy the raw data for the bitmap as a whole chunk; | |
111 | * if we're in a little-endian platform, we'll perform | |
112 | * the endianness conversion in a separate pass to ensure | |
113 | * we're loading 8-byte aligned words. | |
114 | */ | |
9d2e330b JK |
115 | data_len = st_mult(self->buffer_size, sizeof(eword_t)); |
116 | if (len < data_len) | |
117 | return error("corrupt ewah bitmap: eof in data " | |
118 | "(%"PRIuMAX" bytes short)", | |
119 | (uintmax_t)(data_len - len)); | |
120 | memcpy(self->buffer, ptr, data_len); | |
121 | ptr += data_len; | |
122 | len -= data_len; | |
a201c20b | 123 | |
6b5b3a27 JK |
124 | for (i = 0; i < self->buffer_size; ++i) |
125 | self->buffer[i] = ntohll(self->buffer[i]); | |
e1273106 | 126 | |
9d2e330b JK |
127 | if (len < sizeof(uint32_t)) |
128 | return error("corrupt ewah bitmap: eof before rlw"); | |
a201c20b | 129 | self->rlw = self->buffer + get_be32(ptr); |
9d2e330b JK |
130 | ptr += sizeof(uint32_t); |
131 | len -= sizeof(uint32_t); | |
e1273106 | 132 | |
9d2e330b | 133 | return ptr - (const uint8_t *)map; |
e1273106 | 134 | } |