1/**2* Copyright 2013, GitHub, Inc3* Copyright 2009-2013, Daniel Lemire, Cliff Moon,4* David McIntosh, Robert Becho, Google Inc. and Veronika Zenz5*6* This program is free software; you can redistribute it and/or7* modify it under the terms of the GNU General Public License8* as published by the Free Software Foundation; either version 29* 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 of13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14* GNU General Public License for more details.15*16* You should have received a copy of the GNU General Public License17* along with this program; if not, write to the Free Software18* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.19*/20#include "git-compat-util.h"21#include "ewok.h"2223int ewah_serialize_native(struct ewah_bitmap *self, int fd)24{25uint32_t write32;26size_t to_write = self->buffer_size * 8;2728/* 32 bit -- bit size for the map */29write32 = (uint32_t)self->bit_size;30if (write(fd, &write32, 4) != 4)31return -1;3233/** 32 bit -- number of compressed 64-bit words */34write32 = (uint32_t)self->buffer_size;35if (write(fd, &write32, 4) != 4)36return -1;3738if (write(fd, self->buffer, to_write) != to_write)39return -1;4041/** 32 bit -- position for the RLW */42write32 = self->rlw - self->buffer;43if (write(fd, &write32, 4) != 4)44return -1;4546return (3 * 4) + to_write;47}4849int ewah_serialize_to(struct ewah_bitmap *self,50int (*write_fun)(void *, const void *, size_t),51void *data)52{53size_t i;54eword_t dump[2048];55const size_t words_per_dump = sizeof(dump) / sizeof(eword_t);56uint32_t bitsize, word_count, rlw_pos;5758const eword_t *buffer;59size_t words_left;6061/* 32 bit -- bit size for the map */62bitsize = htonl((uint32_t)self->bit_size);63if (write_fun(data, &bitsize, 4) != 4)64return -1;6566/** 32 bit -- number of compressed 64-bit words */67word_count = htonl((uint32_t)self->buffer_size);68if (write_fun(data, &word_count, 4) != 4)69return -1;7071/** 64 bit x N -- compressed words */72buffer = self->buffer;73words_left = self->buffer_size;7475while (words_left >= words_per_dump) {76for (i = 0; i < words_per_dump; ++i, ++buffer)77dump[i] = htonll(*buffer);7879if (write_fun(data, dump, sizeof(dump)) != sizeof(dump))80return -1;8182words_left -= words_per_dump;83}8485if (words_left) {86for (i = 0; i < words_left; ++i, ++buffer)87dump[i] = htonll(*buffer);8889if (write_fun(data, dump, words_left * 8) != words_left * 8)90return -1;91}9293/** 32 bit -- position for the RLW */94rlw_pos = (uint8_t*)self->rlw - (uint8_t *)self->buffer;95rlw_pos = htonl(rlw_pos / sizeof(eword_t));9697if (write_fun(data, &rlw_pos, 4) != 4)98return -1;99100return (3 * 4) + (self->buffer_size * 8);101}102103static int write_helper(void *fd, const void *buf, size_t len)104{105return write((intptr_t)fd, buf, len);106}107108int ewah_serialize(struct ewah_bitmap *self, int fd)109{110return ewah_serialize_to(self, write_helper, (void *)(intptr_t)fd);111}112113int ewah_read_mmap(struct ewah_bitmap *self, void *map, size_t len)114{115uint8_t *ptr = map;116size_t i;117118self->bit_size = get_be32(ptr);119ptr += sizeof(uint32_t);120121self->buffer_size = self->alloc_size = get_be32(ptr);122ptr += sizeof(uint32_t);123124self->buffer = ewah_realloc(self->buffer,125self->alloc_size * sizeof(eword_t));126127if (!self->buffer)128return -1;129130/*131* Copy the raw data for the bitmap as a whole chunk;132* if we're in a little-endian platform, we'll perform133* the endianness conversion in a separate pass to ensure134* we're loading 8-byte aligned words.135*/136memcpy(self->buffer, ptr, self->buffer_size * sizeof(uint64_t));137ptr += self->buffer_size * sizeof(uint64_t);138139for (i = 0; i < self->buffer_size; ++i)140self->buffer[i] = ntohll(self->buffer[i]);141142self->rlw = self->buffer + get_be32(ptr);143144return (3 * 4) + (self->buffer_size * 8);145}146147int ewah_deserialize(struct ewah_bitmap *self, int fd)148{149size_t i;150eword_t dump[2048];151const size_t words_per_dump = sizeof(dump) / sizeof(eword_t);152uint32_t bitsize, word_count, rlw_pos;153154eword_t *buffer = NULL;155size_t words_left;156157ewah_clear(self);158159/* 32 bit -- bit size for the map */160if (read(fd, &bitsize, 4) != 4)161return -1;162163self->bit_size = (size_t)ntohl(bitsize);164165/** 32 bit -- number of compressed 64-bit words */166if (read(fd, &word_count, 4) != 4)167return -1;168169self->buffer_size = self->alloc_size = (size_t)ntohl(word_count);170self->buffer = ewah_realloc(self->buffer,171self->alloc_size * sizeof(eword_t));172173if (!self->buffer)174return -1;175176/** 64 bit x N -- compressed words */177buffer = self->buffer;178words_left = self->buffer_size;179180while (words_left >= words_per_dump) {181if (read(fd, dump, sizeof(dump)) != sizeof(dump))182return -1;183184for (i = 0; i < words_per_dump; ++i, ++buffer)185*buffer = ntohll(dump[i]);186187words_left -= words_per_dump;188}189190if (words_left) {191if (read(fd, dump, words_left * 8) != words_left * 8)192return -1;193194for (i = 0; i < words_left; ++i, ++buffer)195*buffer = ntohll(dump[i]);196}197198/** 32 bit -- position for the RLW */199if (read(fd, &rlw_pos, 4) != 4)200return -1;201202self->rlw = self->buffer + ntohl(rlw_pos);203return 0;204}