Libpolycomp  1.0
A compression/decompression library that implements the polynomial compression and other simple compression schemes
rle.c
1 /* rle.c - Run-Length encoding
2  *
3  * Copyright (c) 2015 Maurizio Tomasi
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation
7  * files (the "Software"), to deal in the Software without
8  * restriction, including without limitation the rights to use, copy,
9  * modify, merge, publish, distribute, sublicense, and/or sell copies
10  * of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25 
71 #include "libpolycomp.h"
72 #include <stdlib.h>
73 
95 size_t pcomp_rle_bufsize(size_t input_size) { return 2 * input_size; }
96 
97 /***********************************************************************
98  * Run-length compression routines
99  */
100 
101 #define IMPLEMENT_RLE_COMPR_FN(name, datatype_t, max_value) \
102  int name(datatype_t* output_buf, size_t* output_size, \
103  const datatype_t* input_buf, size_t input_size) \
104  { \
105  size_t true_output_size = 0; \
106  size_t input_idx = 0; \
107  \
108  if (output_buf == NULL || output_size == NULL \
109  || input_buf == NULL) \
110  abort(); \
111  \
112  if (input_size == 0) { \
113  *output_size = 0; \
114  return PCOMP_STAT_SUCCESS; \
115  } \
116  \
117  if (*output_size < 2) { \
118  return PCOMP_STAT_INVALID_BUFFER; \
119  } \
120  \
121  while (input_idx < input_size) { \
122  datatype_t first_datum_in_the_run = input_buf[input_idx]; \
123  datatype_t count = 0; \
124  while (count < max_value && input_idx < input_size \
125  && input_buf[input_idx] \
126  == first_datum_in_the_run) { \
127  input_idx++; \
128  count++; \
129  } \
130  \
131  if (true_output_size >= *output_size - 2) { \
132  return PCOMP_STAT_INVALID_BUFFER; \
133  } \
134  \
135  output_buf[true_output_size++] = count; \
136  output_buf[true_output_size++] = first_datum_in_the_run; \
137  } \
138  \
139  *output_size = true_output_size; \
140  return PCOMP_STAT_SUCCESS; \
141  }
142 
143 IMPLEMENT_RLE_COMPR_FN(pcomp_compress_rle_int8, int8_t, INT8_MAX)
144 IMPLEMENT_RLE_COMPR_FN(pcomp_compress_rle_int16, int16_t, INT16_MAX)
145 IMPLEMENT_RLE_COMPR_FN(pcomp_compress_rle_int32, int32_t, INT32_MAX)
146 IMPLEMENT_RLE_COMPR_FN(pcomp_compress_rle_int64, int64_t, INT64_MAX)
147 
148 IMPLEMENT_RLE_COMPR_FN(pcomp_compress_rle_uint8, uint8_t, UINT8_MAX)
149 IMPLEMENT_RLE_COMPR_FN(pcomp_compress_rle_uint16, uint16_t, UINT16_MAX)
150 IMPLEMENT_RLE_COMPR_FN(pcomp_compress_rle_uint32, uint32_t, UINT32_MAX)
151 IMPLEMENT_RLE_COMPR_FN(pcomp_compress_rle_uint64, uint64_t, UINT64_MAX)
152 
298 /***********************************************************************
299  * Run-Length decompression routines
300  */
301 
302 #define IMPLEMENT_RLE_DECOMPR_FN(name, datatype_t) \
303  int name(datatype_t* output_buf, size_t output_size, \
304  const datatype_t* input_buf, size_t input_size) \
305  { \
306  size_t input_idx = 0; \
307  size_t output_idx = 0; \
308  \
309  if (output_buf == NULL || input_buf == NULL) \
310  abort(); \
311  \
312  if (input_size == 0) { \
313  return PCOMP_STAT_SUCCESS; \
314  } \
315  \
316  if (input_size % 2 != 0) { \
317  return PCOMP_STAT_INVALID_ENCODING; \
318  } \
319  \
320  while (output_idx < output_size \
321  && input_idx < input_size - 1) { \
322  datatype_t count = input_buf[input_idx]; \
323  datatype_t value = input_buf[input_idx + 1]; \
324  datatype_t idx; \
325  \
326  for (idx = 0; idx < count; ++idx) { \
327  output_buf[output_idx++] = value; \
328  } \
329  \
330  input_idx += 2; \
331  } \
332  \
333  return PCOMP_STAT_SUCCESS; \
334  }
335 
336 IMPLEMENT_RLE_DECOMPR_FN(pcomp_decompress_rle_int8, int8_t)
337 IMPLEMENT_RLE_DECOMPR_FN(pcomp_decompress_rle_int16, int16_t)
338 IMPLEMENT_RLE_DECOMPR_FN(pcomp_decompress_rle_int32, int32_t)
339 IMPLEMENT_RLE_DECOMPR_FN(pcomp_decompress_rle_int64, int64_t)
340 
341 IMPLEMENT_RLE_DECOMPR_FN(pcomp_decompress_rle_uint8, uint8_t)
342 IMPLEMENT_RLE_DECOMPR_FN(pcomp_decompress_rle_uint16, uint16_t)
343 IMPLEMENT_RLE_DECOMPR_FN(pcomp_decompress_rle_uint32, uint32_t)
344 IMPLEMENT_RLE_DECOMPR_FN(pcomp_decompress_rle_uint64, uint64_t)
int pcomp_compress_rle_int16(int16_t *output_buf, size_t *output_size, const int16_t *input_buf, size_t input_size)
Compress an array of int16_t values using the RLE compression.
int pcomp_compress_rle_int32(int32_t *output_buf, size_t *output_size, const int32_t *input_buf, size_t input_size)
Compress an array of int32_t values using the RLE compression.
size_t pcomp_rle_bufsize(size_t input_size)
Calculate an upper limit for the size of a buffer holding RLE-encoded streams.
Definition: rle.c:95
int pcomp_compress_rle_uint64(uint64_t *output_buf, size_t *output_size, const uint64_t *input_buf, size_t input_size)
Compress an array of uint64_t values using the RLE compression.
int pcomp_compress_rle_uint16(uint16_t *output_buf, size_t *output_size, const uint16_t *input_buf, size_t input_size)
Compress an array of uint16_t values using the RLE compression.
int pcomp_compress_rle_int64(int64_t *output_buf, size_t *output_size, const int64_t *input_buf, size_t input_size)
Compress an array of int64_t values using the RLE compression.
int pcomp_compress_rle_int8(int8_t *output_buf, size_t *output_size, const int8_t *input_buf, size_t input_size)
Compress an array of int8_t values using the RLE compression.
int pcomp_compress_rle_uint32(uint32_t *output_buf, size_t *output_size, const uint32_t *input_buf, size_t input_size)
Compress an array of uint32_t values using the RLE compression.
int pcomp_compress_rle_uint8(uint8_t *output_buf, size_t *output_size, const uint8_t *input_buf, size_t input_size)
Compress an array of uint8_t values using the RLE compression.
Header file for Libpolycomp.