github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-varint.c (about) 1 /* 2 * jit-varint.c - Variable length integer encoding. 3 * 4 * Copyright (C) 2011 Aleksey Demakov 5 * 6 * The libjit library is free software: you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public License 8 * as published by the Free Software Foundation, either version 2.1 of 9 * the License, or (at your option) any later version. 10 * 11 * The libjit library 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 GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with the libjit library. If not, see 18 * <http://www.gnu.org/licenses/>. 19 */ 20 21 #include <jit/jit.h> 22 #include "jit-varint.h" 23 24 /* 25 * Flush the current encode buffer. 26 */ 27 static int 28 flush_encoder(jit_varint_encoder_t *encoder) 29 { 30 jit_varint_data_t data; 31 32 /* Allocate a new jit_varint_data structure to hold the data */ 33 data = jit_malloc(sizeof(struct jit_varint_data) + encoder->len); 34 if(!data) 35 { 36 return 0; 37 } 38 39 /* Copy the temporary debug data into the new structure */ 40 jit_memcpy(data->data, encoder->buf, encoder->len); 41 42 /* Link the structure into the debug list */ 43 data->next = 0; 44 if(encoder->last) 45 { 46 encoder->last->next = data; 47 } 48 else 49 { 50 encoder->data = data; 51 } 52 encoder->last = data; 53 54 /* Reset the temporary debug buffer */ 55 encoder->len = 0; 56 return 1; 57 } 58 59 void 60 _jit_varint_init_encoder(jit_varint_encoder_t *encoder) 61 { 62 encoder->len = 0; 63 encoder->data = 0; 64 encoder->last = 0; 65 } 66 67 void 68 _jit_varint_init_decoder(jit_varint_decoder_t *decoder, jit_varint_data_t data) 69 { 70 decoder->len = 0; 71 decoder->data = data; 72 decoder->end = (data == 0); 73 } 74 75 int 76 _jit_varint_encode_end(jit_varint_encoder_t *encoder) 77 { 78 if(!encoder->len) 79 { 80 return 1; 81 } 82 83 /* Mark the end of the data */ 84 encoder->buf[encoder->len++] = 0xFF; 85 86 /* Flush the data that we have collected so far */ 87 return flush_encoder(encoder); 88 } 89 90 /* 91 * Compress a "long" value so that it takes up less bytes. 92 * This is used to store offsets within functions and 93 * debug line numbers, which are usually small integers. 94 */ 95 int 96 _jit_varint_encode_uint(jit_varint_encoder_t *encoder, jit_uint value) 97 { 98 if(encoder->len + 6 > sizeof(encoder->buf)) 99 { 100 /* Overflow occurred: end current buffer */ 101 if(!_jit_varint_encode_end(encoder)) 102 { 103 return 0; 104 } 105 } 106 107 /* Write the value to the temporary buffer */ 108 if(value < 0x80) 109 { 110 /* 0xxx xxxx */ 111 encoder->buf[encoder->len++] = (unsigned char) (value); 112 } 113 else if(value < 0x4000) 114 { 115 /* 10xx xxxx | xxxx xxxx */ 116 encoder->buf[encoder->len++] = (unsigned char) (value >> 8) | 0x80; 117 encoder->buf[encoder->len++] = (unsigned char) (value); 118 } 119 else if(value < 0x200000) 120 { 121 /* 110x xxxx | xxxx xxxx | xxxx xxxx */ 122 encoder->buf[encoder->len++] = (unsigned char) (value >> 16) | 0xC0; 123 encoder->buf[encoder->len++] = (unsigned char) (value >> 8); 124 encoder->buf[encoder->len++] = (unsigned char) (value); 125 } 126 else if(value < 0x10000000) 127 { 128 /* 1110 xxxx | xxxx xxxx | xxxx xxxx | xxxx xxxx */ 129 encoder->buf[encoder->len++] = (unsigned char) (value >> 24) | 0xE0; 130 encoder->buf[encoder->len++] = (unsigned char) (value >> 16); 131 encoder->buf[encoder->len++] = (unsigned char) (value >> 8); 132 encoder->buf[encoder->len++] = (unsigned char) (value); 133 } 134 else 135 { 136 /* 1111 0000 | xxxx xxxx | xxxx xxxx | xxxx xxxx | xxxx xxxx */ 137 encoder->buf[encoder->len++] = 0xF0; 138 encoder->buf[encoder->len++] = (unsigned char) (value >> 24); 139 encoder->buf[encoder->len++] = (unsigned char) (value >> 16); 140 encoder->buf[encoder->len++] = (unsigned char) (value >> 8); 141 encoder->buf[encoder->len++] = (unsigned char) (value); 142 } 143 144 return 1; 145 } 146 147 jit_varint_data_t 148 _jit_varint_get_data(jit_varint_encoder_t *encoder) 149 { 150 return encoder->data; 151 } 152 153 void 154 _jit_varint_free_data(jit_varint_data_t data) 155 { 156 while(data) 157 { 158 jit_varint_data_t next = data->next; 159 jit_free(data); 160 data = next; 161 } 162 } 163 164 int 165 _jit_varint_decode_end(jit_varint_decoder_t *decoder) 166 { 167 return decoder->end; 168 } 169 170 jit_uint 171 _jit_varint_decode_uint(jit_varint_decoder_t *decoder) 172 { 173 jit_uint value; 174 unsigned char c; 175 176 value = (jit_uint) (-1); 177 if(decoder->end) 178 { 179 return value; 180 } 181 if(decoder->len >= JIT_VARINT_BUFFER_SIZE) 182 { 183 /* Sanity check failed */ 184 decoder->end = 2; 185 return value; 186 } 187 188 again: 189 c = decoder->data->data[decoder->len++]; 190 if(!(c & 0x80)) 191 { 192 /* 0xxx xxxx */ 193 value = ((jit_uint) c); 194 } 195 else if(!(c & 0x40)) 196 { 197 /* 10xx xxxx | xxxx xxxx */ 198 value = ((jit_uint) c & 0x3F) << 8; 199 value |= ((jit_uint) decoder->data->data[decoder->len++]); 200 } 201 else if(!(c & 0x20)) 202 { 203 /* 110x xxxx | xxxx xxxx | xxxx xxxx */ 204 value = ((jit_uint) c & 0x1F) << 16; 205 value |= ((jit_uint) decoder->data->data[decoder->len++]) << 8; 206 value |= ((jit_uint) decoder->data->data[decoder->len++]); 207 } 208 else if(!(c & 0x10)) 209 { 210 /* 1110 xxxx | xxxx xxxx | xxxx xxxx | xxxx xxxx */ 211 value = ((jit_uint) c & 0x0F) << 24; 212 value |= ((jit_uint) decoder->data->data[decoder->len++]) << 16; 213 value |= ((jit_uint) decoder->data->data[decoder->len++]) << 8; 214 value |= ((jit_uint) decoder->data->data[decoder->len++]); 215 } 216 else if(!(c & 0x0f)) 217 { 218 /* 1111 0000 | xxxx xxxx | xxxx xxxx | xxxx xxxx | xxxx xxxx */ 219 value |= ((jit_uint) decoder->data->data[decoder->len++]) << 24; 220 value |= ((jit_uint) decoder->data->data[decoder->len++]) << 16; 221 value |= ((jit_uint) decoder->data->data[decoder->len++]) << 8; 222 value |= ((jit_uint) decoder->data->data[decoder->len++]); 223 } 224 else 225 { 226 /* Met data end mark */ 227 if(decoder->data->next) 228 { 229 /* There is another data block */ 230 decoder->data = decoder->data->next; 231 decoder->len = 0; 232 goto again; 233 } 234 235 /* This was the last data block */ 236 decoder->end = 1; 237 } 238 239 return value; 240 } 241 242 #if 0 243 244 void 245 _jit_varint_encode_int(jit_varint_encoder_t *encoder, jit_int value) 246 { 247 value = (value << 1) ^ (value >> (8 * sizeof(jit_uint) - 1));; 248 _jit_varint_encode_uint(encoder, (jit_uint) value); 249 } 250 251 jit_int 252 _jit_varint_decode_int(jit_varint_decoder_t *decoder) 253 { 254 jit_uint value = _jit_varint_decode_uint(decoder); 255 return (jit_int) ((value >> 1) ^ -(value & 1)); 256 } 257 258 #endif 259 260 #if defined(VARINT_TEST) 261 262 #include <stdio.h> 263 #include <stdlib.h> 264 #include <string.h> 265 266 void * 267 jit_malloc(unsigned int size) 268 { 269 return malloc(size); 270 } 271 272 void 273 jit_free(void *ptr) 274 { 275 if(ptr) 276 { 277 free(ptr); 278 } 279 } 280 281 void * 282 jit_memcpy(void *dest, const void *src, unsigned int len) 283 { 284 return memcpy(dest, src, len); 285 } 286 287 int 288 main() 289 { 290 jit_uint i, j, n, v; 291 292 for(n = 1; n != 0; n >>= 1) 293 { 294 jit_varint_encoder_t encoder; 295 _jit_varint_init_encoder(&encoder); 296 _jit_varint_encode_uint(&encoder, n); 297 _jit_varint_encode_uint(&encoder, n - 1); 298 _jit_varint_encode_uint(&encoder, n + 1); 299 _jit_varint_encode_end(&encoder); 300 301 jit_varint_data_t data = _jit_varint_get_data(&encoder); 302 303 jit_varint_decoder_t decoder; 304 _jit_varint_init_decoder(&decoder, data); 305 v = _jit_varint_decode_uint(&decoder); 306 if(v != n) 307 { 308 fprintf(stderr, "FAILED\n"); 309 } 310 v = _jit_varint_decode_uint(&decoder); 311 if(v != n - 1) 312 { 313 fprintf(stderr, "FAILED\n"); 314 } 315 v = _jit_varint_decode_uint(&decoder); 316 if(v != n + 1) 317 { 318 fprintf(stderr, "FAILED\n"); 319 } 320 _jit_varint_decode_uint(&decoder); 321 if(!_jit_varint_decode_end(&decoder)) 322 { 323 fprintf(stderr, "FAILED\n"); 324 } 325 326 _jit_varint_free_data(data); 327 } 328 329 } 330 331 #endif