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 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19#include"git-compat-util.h" 20#include"ewok.h" 21#include"strbuf.h" 22 23intewah_serialize_to(struct ewah_bitmap *self, 24int(*write_fun)(void*,const void*,size_t), 25void*data) 26{ 27size_t i; 28 eword_t dump[2048]; 29const size_t words_per_dump =sizeof(dump) /sizeof(eword_t); 30uint32_t bitsize, word_count, rlw_pos; 31 32const eword_t *buffer; 33size_t words_left; 34 35/* 32 bit -- bit size for the map */ 36 bitsize =htonl((uint32_t)self->bit_size); 37if(write_fun(data, &bitsize,4) !=4) 38return-1; 39 40/** 32 bit -- number of compressed 64-bit words */ 41 word_count =htonl((uint32_t)self->buffer_size); 42if(write_fun(data, &word_count,4) !=4) 43return-1; 44 45/** 64 bit x N -- compressed words */ 46 buffer = self->buffer; 47 words_left = self->buffer_size; 48 49while(words_left >= words_per_dump) { 50for(i =0; i < words_per_dump; ++i, ++buffer) 51 dump[i] =htonll(*buffer); 52 53if(write_fun(data, dump,sizeof(dump)) !=sizeof(dump)) 54return-1; 55 56 words_left -= words_per_dump; 57} 58 59if(words_left) { 60for(i =0; i < words_left; ++i, ++buffer) 61 dump[i] =htonll(*buffer); 62 63if(write_fun(data, dump, words_left *8) != words_left *8) 64return-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 71if(write_fun(data, &rlw_pos,4) !=4) 72return-1; 73 74return(3*4) + (self->buffer_size *8); 75} 76 77static intwrite_strbuf(void*user_data,const void*data,size_t len) 78{ 79struct strbuf *sb = user_data; 80strbuf_add(sb, data, len); 81return len; 82} 83 84intewah_serialize_strbuf(struct ewah_bitmap *self,struct strbuf *sb) 85{ 86returnewah_serialize_to(self, write_strbuf, sb); 87} 88 89ssize_t ewah_read_mmap(struct ewah_bitmap *self,const void*map,size_t len) 90{ 91const uint8_t*ptr = map; 92size_t data_len; 93size_t i; 94 95if(len <sizeof(uint32_t)) 96returnerror("corrupt ewah bitmap: eof before bit size"); 97 self->bit_size =get_be32(ptr); 98 ptr +=sizeof(uint32_t); 99 len -=sizeof(uint32_t); 100 101if(len <sizeof(uint32_t)) 102returnerror("corrupt ewah bitmap: eof before length"); 103 self->buffer_size = self->alloc_size =get_be32(ptr); 104 ptr +=sizeof(uint32_t); 105 len -=sizeof(uint32_t); 106 107REALLOC_ARRAY(self->buffer, self->alloc_size); 108 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 */ 115 data_len =st_mult(self->buffer_size,sizeof(eword_t)); 116if(len < data_len) 117returnerror("corrupt ewah bitmap: eof in data " 118"(%"PRIuMAX" bytes short)", 119(uintmax_t)(data_len - len)); 120memcpy(self->buffer, ptr, data_len); 121 ptr += data_len; 122 len -= data_len; 123 124for(i =0; i < self->buffer_size; ++i) 125 self->buffer[i] =ntohll(self->buffer[i]); 126 127if(len <sizeof(uint32_t)) 128returnerror("corrupt ewah bitmap: eof before rlw"); 129 self->rlw = self->buffer +get_be32(ptr); 130 ptr +=sizeof(uint32_t); 131 len -=sizeof(uint32_t); 132 133return ptr - (const uint8_t*)map; 134}