LCOV - code coverage report
Current view: top level - utils - base_encoding.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 169 188 89.9 %
Date: 2021-04-29 23:48:07 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / common tools sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/base_coding.h>
      27             : #include <gpac/constants.h>
      28             : 
      29             : #ifndef GPAC_DISABLE_CORE_TOOLS
      30             : 
      31             : static const char base_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      32             : 
      33             : GF_EXPORT
      34         125 : u32 gf_base64_encode(const u8 *_in, u32 inSize, u8 *_out, u32 outSize)
      35             : {
      36             :         s32 padding;
      37             :         u32 i = 0, j = 0;
      38             :         unsigned char *in = (unsigned char *)_in;
      39             :         unsigned char *out = (unsigned char *)_out;
      40             : 
      41         125 :         if (outSize < (inSize * 4 / 3)) return 0;
      42             : 
      43       47201 :         while (i < inSize) {
      44       47076 :                 padding = 3 - (inSize - i);
      45       47076 :                 if (padding == 2) {
      46          41 :                         out[j] = base_64[in[i]>>2];
      47          41 :                         out[j+1] = base_64[(in[i] & 0x03) << 4];
      48          41 :                         out[j+2] = '=';
      49          41 :                         out[j+3] = '=';
      50       47035 :                 } else if (padding == 1) {
      51          51 :                         out[j] = base_64[in[i]>>2];
      52          51 :                         out[j+1] = base_64[((in[i] & 0x03) << 4) | ((in[i+1] & 0xf0) >> 4)];
      53          51 :                         out[j+2] = base_64[(in[i+1] & 0x0f) << 2];
      54          51 :                         out[j+3] = '=';
      55             :                 } else {
      56       46984 :                         out[j] = base_64[in[i]>>2];
      57       46984 :                         out[j+1] = base_64[((in[i] & 0x03) << 4) | ((in[i+1] & 0xf0) >> 4)];
      58       46984 :                         out[j+2] = base_64[((in[i+1] & 0x0f) << 2) | ((in[i+2] & 0xc0) >> 6)];
      59       46984 :                         out[j+3] = base_64[in[i+2] & 0x3f];
      60             :                 }
      61       47076 :                 i += 3;
      62       47076 :                 j += 4;
      63             :         }
      64             :         return j;
      65             : }
      66             : 
      67             : static const unsigned char index_64[128] = {
      68             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      69             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      70             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,   62, 0xff, 0xff, 0xff,   63,
      71             :         52,   53,   54,   55,   56,   57,   58,   59,   60,   61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      72             :         0xff,    0,    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,
      73             :         15,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25, 0xff, 0xff, 0xff, 0xff, 0xff,
      74             :         0xff,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   40,
      75             :         41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51, 0xff, 0xff, 0xff, 0xff, 0xff
      76             : };
      77             : 
      78             : #define char64(c)  ((c > 127) ? (char) 0xff : index_64[(c)])
      79             : 
      80             : /*denoise input*/
      81         372 : u32 load_block(char *in, u32 size, u32 pos, char *out)
      82             : {
      83             :         u32 i, len;
      84             :         u8 c;
      85             :         len = i = 0;
      86        2328 :         while ((len<4) && ((pos+i)<size)) {
      87        1584 :                 c = in[pos+i];
      88        3168 :                 if ( ((c>='A') && (c<='Z'))
      89        1584 :                         || ((c>='a') && (c<='z'))
      90         356 :                         || ((c>='0') && (c<='9'))
      91         164 :                         || (c=='=') || (c=='+') || (c=='/')
      92             :                    ) {
      93        1480 :                         out[len] = c;
      94        1480 :                         len++;
      95             :                 }
      96        1584 :                 i++;
      97             :         }
      98         380 :         while (len<4) {
      99           8 :                 out[len] = (char) 0xFF;
     100           8 :                 len++;
     101             :         }
     102         372 :         return pos+i;
     103             : }
     104             : 
     105             : GF_EXPORT
     106          24 : u32 gf_base64_decode(u8 *in_buf, u32 inSize, u8 *out, u32 outSize)
     107             : {
     108             :         u32 i = 0, j = 0, padding;
     109             :         unsigned char c[4], in[4];
     110             : 
     111          24 :         if (outSize < (inSize * 3 / 4)) return 0;
     112             : 
     113         396 :         while ((i + 3) < inSize) {
     114             :                 padding = 0;
     115         372 :                 i = load_block(in_buf, inSize, i, (char*)in);
     116         372 :                 c[0] = char64(in[0]);
     117         372 :                 padding += (c[0] == 0xff);
     118         372 :                 c[1] = char64(in[1]);
     119         372 :                 padding += (c[1] == 0xff);
     120         372 :                 c[2] = char64(in[2]);
     121         372 :                 padding += (c[2] == 0xff);
     122         372 :                 c[3] = char64(in[3]);
     123         372 :                 padding += (c[3] == 0xff);
     124         372 :                 if (padding == 2) {
     125          12 :                         out[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
     126          12 :                         out[j]   = (c[1] & 0x0f) << 4;
     127         360 :                 } else if (padding == 1) {
     128           4 :                         out[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
     129           4 :                         out[j++] = ((c[1] & 0x0f) << 4) | ((c[2] & 0x3c) >> 2);
     130           4 :                         out[j]   = (c[2] & 0x03) << 6;
     131             :                 } else {
     132         356 :                         out[j++] = (c[0] << 2) | ((c[1] & 0x30) >> 4);
     133         356 :                         out[j++] = ((c[1] & 0x0f) << 4) | ((c[2] & 0x3c) >> 2);
     134         356 :                         out[j++] = ((c[2] & 0x03) << 6) | (c[3] & 0x3f);
     135             :                 }
     136             :                 //i += 4;
     137             :         }
     138             :         return j;
     139             : }
     140             : 
     141             : static const char base_16[] = "0123456789abcdef";
     142             : 
     143             : GF_EXPORT
     144           2 : u32 gf_base16_encode(u8 *_in, u32 inSize, u8 *_out, u32 outSize)
     145             : {
     146             :         u32 i = 0;
     147             :         unsigned char *in = (unsigned char *)_in;
     148             :         unsigned char *out = (unsigned char *)_out;
     149             : 
     150           2 :         if (outSize < (inSize * 2)+1) return 0;
     151             : 
     152         485 :         for (i=0; i<inSize; i++) {
     153         485 :                 out[2*i] = base_16[((in[i] & 0xf0) >> 4)];
     154         485 :                 out[2*i+1] = base_16[(in[i] & 0x0f)];
     155             :         }
     156           2 :         out[(inSize * 2)] = 0;
     157             : 
     158           2 :         return inSize * 2;
     159             : }
     160             : 
     161             : #define char16(nb) (((nb) < 97) ? ((nb)-48) : ((nb)-87))
     162             : 
     163             : GF_EXPORT
     164           2 : u32 gf_base16_decode(u8 *in, u32 inSize, u8 *out, u32 outSize)
     165             : {
     166             :         u32 j=0;
     167             :         u32 c[2] = {0,0};
     168             : 
     169           2 :         if (outSize < (inSize / 2)) return 0;
     170           2 :         if ((inSize % 2) != 0) return 0;
     171             : 
     172         485 :         for (j=0; j<inSize/2; j++) {
     173         485 :                 c[0] = char16(in[2*j]);
     174         485 :                 c[1] = char16(in[2*j+1]);
     175         485 :                 out[j] = ((c[0] << 4)&0xf0) | (c[1]&0x0f);
     176             :         }
     177           2 :         out[inSize/2] = 0;
     178             : 
     179           2 :         return j;
     180             : }
     181             : 
     182             : 
     183             : #ifndef GPAC_DISABLE_ZLIB
     184             : 
     185             : #include <zlib.h>
     186             : 
     187             : #define ZLIB_COMPRESS_SAFE      4
     188             : 
     189             : GF_EXPORT
     190          48 : GF_Err gf_gz_compress_payload_ex(u8 **data, u32 data_len, u32 *max_size, u8 data_offset, Bool skip_if_larger, u8 **out_comp_data)
     191             : {
     192             :         z_stream stream;
     193             :         int err;
     194          48 :         char *dest = (char *)gf_malloc(sizeof(char)*data_len*ZLIB_COMPRESS_SAFE);
     195          48 :         stream.next_in = (Bytef*)(*data) + data_offset;
     196          48 :         stream.avail_in = (uInt)data_len - data_offset;
     197          48 :         stream.next_out = ( Bytef*)dest;
     198          48 :         stream.avail_out = (uInt)data_len*ZLIB_COMPRESS_SAFE;
     199          48 :         stream.zalloc = (alloc_func)NULL;
     200          48 :         stream.zfree = (free_func)NULL;
     201          48 :         stream.opaque = (voidpf)NULL;
     202             : 
     203          48 :         err = deflateInit2(&stream, 9, Z_DEFLATED, 16+MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
     204             : 
     205          48 :         if (err != Z_OK) {
     206           0 :                 gf_free(dest);
     207           0 :                 return GF_IO_ERR;
     208             :         }
     209             : 
     210          48 :         err = deflate(&stream, Z_FINISH);
     211          48 :         if (err != Z_STREAM_END) {
     212           0 :                 deflateEnd(&stream);
     213           0 :                 gf_free(dest);
     214           0 :                 return GF_IO_ERR;
     215             :         }
     216          48 :         if (data_len-data_offset < stream.total_out) {
     217           2 :                 if (skip_if_larger) {
     218           0 :                         gf_free(dest);
     219           0 :                         deflateEnd(&stream);
     220           0 :                         *max_size = (u32) stream.total_out;
     221           0 :                         return GF_OK;
     222             :                 }
     223           2 :                 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[GZ] compressed data (%d) larger than input (%d)\n", (u32) stream.total_out, (u32) data_len ));
     224             :         }
     225             : 
     226          48 :         if (out_comp_data) {
     227             :                 data = out_comp_data;
     228             :         }
     229             : 
     230          48 :         if (*max_size < stream.total_out) {
     231           2 :                 *max_size = data_len*ZLIB_COMPRESS_SAFE;
     232           2 :                 *data = (char*)gf_realloc(*data, *max_size * sizeof(char));
     233             :         }
     234             : 
     235          48 :         memcpy((*data) , dest, sizeof(char)*stream.total_out);
     236          48 :         *max_size = (u32) stream.total_out;
     237          48 :         gf_free(dest);
     238             : 
     239          48 :         deflateEnd(&stream);
     240          48 :         return GF_OK;
     241             : }
     242             : 
     243             : GF_EXPORT
     244          30 : GF_Err gf_gz_compress_payload(u8 **data, u32 data_len, u32 *max_size)
     245             : {
     246          30 :         return gf_gz_compress_payload_ex(data, data_len, max_size, 0, GF_FALSE, NULL);
     247             : }
     248             : 
     249             : GF_EXPORT
     250          30 : GF_Err gf_gz_decompress_payload(u8 *data, u32 data_len, u8 **uncompressed_data, u32 *out_size)
     251             : {
     252             :         z_stream d_stream;
     253             :         GF_Err e = GF_OK;
     254             :         int err;
     255             :         Bool owns_buffer=GF_TRUE;
     256             :         u32 size = 4096;
     257             : 
     258          30 :         if (! *uncompressed_data) {
     259          15 :                 *uncompressed_data = (char*)gf_malloc(sizeof(char)*4096);
     260          15 :                 if (!*uncompressed_data) return GF_OUT_OF_MEM;
     261             :         } else {
     262             :                 owns_buffer = GF_FALSE;
     263          15 :                 size = *out_size;
     264             :         }
     265             : 
     266          30 :         d_stream.zalloc = (alloc_func)0;
     267          30 :         d_stream.zfree = (free_func)0;
     268          30 :         d_stream.opaque = (voidpf)0;
     269          30 :         d_stream.next_in  = (Bytef*)data;
     270          30 :         d_stream.avail_in = data_len;
     271          30 :         d_stream.next_out = (Bytef*) *uncompressed_data;
     272          30 :         d_stream.avail_out = size;
     273             : 
     274          30 :         err = inflateInit2(&d_stream, 16+MAX_WBITS);
     275             : 
     276          30 :         if (err == Z_OK) {
     277          30 :                 while (d_stream.total_in < data_len) {
     278          30 :                         err = inflate(&d_stream, Z_NO_FLUSH);
     279          30 :                         if (err < Z_OK) {
     280             :                                 e = GF_NON_COMPLIANT_BITSTREAM;
     281             :                                 break;
     282             :                         }
     283          30 :                         if (err==Z_STREAM_END) break;
     284             : 
     285           0 :                         size *= 2;
     286           0 :                         *uncompressed_data = (char*)gf_realloc(*uncompressed_data, sizeof(char)*size);
     287           0 :                         if (!*uncompressed_data) return GF_OUT_OF_MEM;
     288           0 :                         d_stream.avail_out = (u32) (size - d_stream.total_out);
     289           0 :                         d_stream.next_out = (Bytef*) ( *uncompressed_data + d_stream.total_out);
     290             :                 }
     291          30 :                 *out_size = (u32) d_stream.total_out;
     292          30 :                 inflateEnd(&d_stream);
     293          30 :                 return e;
     294             :         }
     295             :         if (e!=GF_OK) {
     296             :                 if (owns_buffer) {
     297             :                         gf_free(*uncompressed_data);
     298             :                         *uncompressed_data = NULL;
     299             :                 }
     300             :         }
     301             :         return e;
     302             : }
     303             : #else
     304             : GF_EXPORT
     305             : GF_Err gf_gz_decompress_payload(u8 *data, u32 data_len, u8 **uncompressed_data, u32 *out_size)
     306             : {
     307             :         *out_size = 0;
     308             :         return GF_NOT_SUPPORTED;
     309             : }
     310             : GF_EXPORT
     311             : GF_Err gf_gz_compress_payload(u8 **data, u32 data_len, u32 *max_size)
     312             : {
     313             :         *max_size = 0;
     314             :         return GF_NOT_SUPPORTED;
     315             : }
     316             : GF_Err gf_gz_compress_payload_ex(u8 **data, u32 data_len, u32 *max_size, u8 data_offset, Bool skip_if_larger, u8 **out_comp_data)
     317             : {
     318             :         *max_size = 0;
     319             :         return GF_NOT_SUPPORTED;
     320             : }
     321             : #endif /*GPAC_DISABLE_ZLIB*/
     322             : 
     323             : 
     324             : #ifdef GPAC_HAS_LZMA
     325             : 
     326             : #include <lzma.h>
     327             : 
     328             : #define LZMA_COMPRESS_SAFE      2
     329             : 
     330             : GF_EXPORT
     331           1 : GF_Err gf_lz_compress_payload(u8 **data, u32 data_len, u32 *max_size)
     332             : {
     333             :         u32 block_size, comp_size;
     334             :         lzma_options_lzma opt_lzma2;
     335           1 :         lzma_stream strm = LZMA_STREAM_INIT;
     336             : 
     337           1 :         lzma_lzma_preset(&opt_lzma2, LZMA_PRESET_DEFAULT);
     338           1 :         lzma_filter filters[] = {
     339             :                         { .id = LZMA_FILTER_X86, .options = NULL },
     340             :                         { .id = LZMA_FILTER_LZMA2, .options = &opt_lzma2 },
     341             :                         { .id = LZMA_VLI_UNKNOWN, .options = NULL },
     342             :         };
     343           1 :         lzma_ret ret = lzma_stream_encoder(&strm, filters, LZMA_CHECK_NONE);
     344           1 :         if (ret != LZMA_OK) return GF_IO_ERR;
     345             : 
     346           1 :         block_size = data_len*LZMA_COMPRESS_SAFE;
     347           1 :         if (block_size < 64) block_size = 64;
     348           1 :         char *dest = (char *)gf_malloc(sizeof(char)*block_size);
     349             : 
     350             : 
     351           1 :         strm.next_in = (const uint8_t *) (*data);
     352           1 :         strm.avail_in = data_len;
     353           1 :         strm.next_out = (uint8_t *) dest;
     354           1 :         strm.avail_out = block_size;
     355             : 
     356           1 :         ret = lzma_code(&strm, LZMA_FINISH);
     357           1 :         if ((ret != LZMA_OK) && (ret != LZMA_STREAM_END)) {
     358           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[LZMA] compressed data failure, code %d\n", ret ));
     359             :                 return GF_IO_ERR;
     360             :         }
     361           1 :         comp_size = block_size - strm.avail_out;
     362             : 
     363           1 :         if (data_len < comp_size) {
     364           1 :                 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[LZMA] compressed data (%d) larger than input (%d)\n", (u32) comp_size, (u32) data_len ));
     365             :         }
     366             : 
     367           1 :         if (*max_size < comp_size) {
     368           1 :                 *max_size = block_size;
     369           1 :                 *data = (char*)gf_realloc(*data, block_size * sizeof(char));
     370             :         }
     371             : 
     372           1 :         memcpy((*data) , dest, sizeof(char) * comp_size);
     373           1 :         *max_size = (u32) comp_size;
     374           1 :         gf_free(dest);
     375             : 
     376           1 :         lzma_end(&strm);
     377           1 :         return GF_OK;
     378             : }
     379             : 
     380             : GF_EXPORT
     381           1 : GF_Err gf_lz_decompress_payload(u8 *data, u32 data_len, u8 **uncompressed_data, u32 *out_size)
     382             : {
     383           1 :         lzma_stream strm = LZMA_STREAM_INIT;
     384           1 :         lzma_ret ret = lzma_stream_decoder(&strm, UINT64_MAX, 0);
     385           1 :         if (ret != LZMA_OK) return GF_IO_ERR;
     386             : 
     387             :         Bool owns_buffer=GF_TRUE;
     388             :         u32 block_size = 4096;
     389             :         u32 done = 0;
     390             :         u32 alloc_size = 0;
     391             :         u8 block[4096];
     392             :         u8 *dst_buffer = NULL;
     393             : 
     394           1 :         if (*uncompressed_data) {
     395             :                 owns_buffer = GF_FALSE;
     396             :                 dst_buffer = (u8 *) *uncompressed_data;
     397           0 :                 alloc_size = *out_size;
     398             :         } else {
     399           1 :                 *out_size = 0;
     400             :         }
     401             : 
     402           1 :         strm.next_in = (const uint8_t *) data;
     403           1 :         strm.avail_in = data_len;
     404           1 :         strm.next_out = (uint8_t *) block;
     405           1 :         strm.avail_out = block_size;
     406             : 
     407             :         while (1) {
     408           1 :                 ret = lzma_code(&strm, LZMA_FINISH);
     409             : 
     410           1 :                 if ((strm.avail_out == 0) || (ret == LZMA_STREAM_END)) {
     411           1 :                         u32 uncomp_size = block_size - strm.avail_out;
     412             : 
     413           1 :                         if (done + uncomp_size > alloc_size) {
     414             :                                 alloc_size = done + uncomp_size;
     415           1 :                                 dst_buffer = gf_realloc(dst_buffer, alloc_size);
     416           1 :                                 *out_size = alloc_size;
     417             :                         }
     418           1 :                         memcpy(dst_buffer + done, block, uncomp_size);
     419             :                         done += uncomp_size;
     420             : 
     421           1 :                         strm.next_out = (uint8_t *) block;
     422           1 :                         strm.avail_out = block_size;
     423             :                 }
     424           1 :                 if (ret == LZMA_STREAM_END) break;
     425           0 :                 if (ret != LZMA_OK) {
     426           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[LZMA] error decompressing data: %d\n", ret ));
     427           0 :                         if (owns_buffer) gf_free(dst_buffer);
     428             :                         return GF_IO_ERR;
     429             :                 }
     430             :         }
     431             : 
     432           1 :         *uncompressed_data = dst_buffer;
     433           1 :         *out_size = done;
     434           1 :         return GF_OK;
     435             : }
     436             : #else
     437             : GF_EXPORT
     438             : GF_Err gf_lz_decompress_payload(u8 *data, u32 data_len, u8 **uncompressed_data, u32 *out_size)
     439             : {
     440             :         *out_size = 0;
     441             :         return GF_NOT_SUPPORTED;
     442             : }
     443             : GF_EXPORT
     444             : GF_Err gf_lz_compress_payload(u8 **data, u32 data_len, u32 *max_size)
     445             : {
     446             :         *max_size = 0;
     447             :         return GF_NOT_SUPPORTED;
     448             : }
     449             : #endif /*GPAC_HAS_LZMA*/
     450             : 
     451             : #endif /* GPAC_DISABLE_CORE_TOOLS*/

Generated by: LCOV version 1.13