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