loaders: unify duplicated b64 decoders.

- move the svg/lottie b64 decoders to tvgLzw.
- renames tvgLzw -> tvgCompressor
This commit is contained in:
Hermet Park 2023-08-17 16:37:46 +09:00 committed by Hermet Park
parent 846823bd7f
commit e7d29e166b
9 changed files with 81 additions and 105 deletions

View file

@ -21,6 +21,7 @@
*/ */
#include "tvgStr.h" #include "tvgStr.h"
#include "tvgCompressor.h"
#include "tvgLottieModel.h" #include "tvgLottieModel.h"
#include "tvgLottieParser.h" #include "tvgLottieParser.h"
@ -29,16 +30,6 @@
/* Internal Class Implementation */ /* Internal Class Implementation */
/************************************************************************/ /************************************************************************/
static constexpr const char B64_INDEX[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 0, 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
};
static char* _int2str(int num) static char* _int2str(int num)
@ -49,31 +40,6 @@ static char* _int2str(int num)
} }
static void _decodeB64(const uint8_t* input, const size_t len, Array<char>& output)
{
int pad = len > 0 && (len % 4 || input[len - 1] == '=');
const size_t L = ((len + 3) / 4 - pad) * 4;
output.reserve(L / 4 * 3 + pad + 1);
output.data[output.reserved - 1] = '\0';
for (size_t i = 0; i < L; i += 4) {
int n = B64_INDEX[input[i]] << 18 | B64_INDEX[input[i + 1]] << 12 | B64_INDEX[input[i + 2]] << 6 | B64_INDEX[input[i + 3]];
output.push(n >> 16);
output.push(n >> 8 & 0xFF);
output.push(n & 0xFF);
}
if (pad) {
int n = B64_INDEX[input[L]] << 18 | B64_INDEX[input[L + 1]] << 12;
output.last() = n >> 16;
if (len > L + 2 && input[L + 2] != '=') {
n |= B64_INDEX[input[L + 2]] << 6;
output.push(n >> 8 & 0xFF);
}
}
output.count = output.reserved;
}
static void _updateRoundedCorner(LottieGroup* parent, LottieRoundedCorner* roundedCorner) static void _updateRoundedCorner(LottieGroup* parent, LottieRoundedCorner* roundedCorner)
{ {
for (auto child = parent->children.data; child < parent->children.end(); ++child) { for (auto child = parent->children.data; child < parent->children.end(); ++child) {
@ -860,12 +826,7 @@ LottieImage* LottieParser::parseImage(const char* key)
//b64 data //b64 data
auto b64Data = strstr(data, ",") + 1; auto b64Data = strstr(data, ",") + 1;
size_t length = strlen(data) - (b64Data - data); size_t length = strlen(data) - (b64Data - data);
image->size = b64Decode(b64Data, length, &image->b64Data);
Array<char> decoded;
_decodeB64(reinterpret_cast<const uint8_t*>(b64Data), length, decoded);
image->b64Data = decoded.data;
image->size = decoded.count;
decoded.data = nullptr;
//external image resource //external image resource
} else { } else {
auto len = strlen(dirName) + strlen(subPath) + strlen(data) + 1; auto len = strlen(dirName) + strlen(subPath) + strlen(data) + 1;

View file

@ -23,6 +23,7 @@
#include "tvgMath.h" /* to include math.h before cstring */ #include "tvgMath.h" /* to include math.h before cstring */
#include <cstring> #include <cstring>
#include <string> #include <string>
#include "tvgCompressor.h"
#include "tvgSvgLoaderCommon.h" #include "tvgSvgLoaderCommon.h"
#include "tvgSvgSceneBuilder.h" #include "tvgSvgSceneBuilder.h"
#include "tvgSvgPath.h" #include "tvgSvgPath.h"
@ -543,10 +544,17 @@ static unique_ptr<Picture> _imageBuildHelper(SvgNode* node, const Box& vBox, con
imageMimeTypeEncoding encoding; imageMimeTypeEncoding encoding;
if (!_isValidImageMimeTypeAndEncoding(&href, &mimetype, &encoding)) return nullptr; //not allowed mime type or encoding if (!_isValidImageMimeTypeAndEncoding(&href, &mimetype, &encoding)) return nullptr; //not allowed mime type or encoding
if (encoding == imageMimeTypeEncoding::base64) { if (encoding == imageMimeTypeEncoding::base64) {
string decoded = svgUtilBase64Decode(href); char* decoded = nullptr;
if (picture->load(decoded.c_str(), decoded.size(), mimetype, true) != Result::Success) return nullptr; auto size = b64Decode(href, strlen(href), &decoded);
//OPTIMIZE: Skip data copy.
if (picture->load(decoded, size, mimetype, true) != Result::Success) {
free(decoded);
return nullptr;
}
free(decoded);
} else { } else {
string decoded = svgUtilURLDecode(href); string decoded = svgUtilURLDecode(href);
//OPTIMIZE: Skip data copy.
if (picture->load(decoded.c_str(), decoded.size(), mimetype, true) != Result::Success) return nullptr; if (picture->load(decoded.c_str(), decoded.size(), mimetype, true) != Result::Success) return nullptr;
} }
} else { } else {

View file

@ -34,15 +34,6 @@ static uint8_t _hexCharToDec(const char c)
else return c - '0'; else return c - '0';
} }
static uint8_t _base64Value(const char chr)
{
if (chr >= 'A' && chr <= 'Z') return chr - 'A';
else if (chr >= 'a' && chr <= 'z') return chr - 'a' + ('Z' - 'A') + 1;
else if (chr >= '0' && chr <= '9') return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2;
else if (chr == '+' || chr == '-') return 62;
else return 63;
}
/************************************************************************/ /************************************************************************/
/* External Class Implementation */ /* External Class Implementation */
@ -73,37 +64,4 @@ string svgUtilURLDecode(const char *src)
} }
} }
return decoded; return decoded;
}
string svgUtilBase64Decode(const char *src)
{
if (!src) return nullptr;
auto length = strlen(src);
if (length == 0) return nullptr;
string decoded;
decoded.reserve(3*(1+(length >> 2)));
while (*src && *(src+1)) {
if (*src <= 0x20) {
++src;
continue;
}
auto value1 = _base64Value(src[0]);
auto value2 = _base64Value(src[1]);
decoded += (value1 << 2) + ((value2 & 0x30) >> 4);
if (!src[2] || src[2] == '=' || src[2] == '.') break;
auto value3 = _base64Value(src[2]);
decoded += ((value2 & 0x0f) << 4) + ((value3 & 0x3c) >> 2);
if (!src[3] || src[3] == '=' || src[3] == '.') break;
auto value4 = _base64Value(src[3]);
decoded += ((value3 & 0x03) << 6) + value4;
src += 4;
}
return decoded;
} }

View file

@ -26,6 +26,5 @@
#include "tvgCommon.h" #include "tvgCommon.h"
string svgUtilURLDecode(const char *src); string svgUtilURLDecode(const char *src);
string svgUtilBase64Decode(const char *src);
#endif //_TVG_SVG_UTIL_H_ #endif //_TVG_SVG_UTIL_H_

View file

@ -24,7 +24,7 @@
#include <fstream> #include <fstream>
#include "tvgLoader.h" #include "tvgLoader.h"
#include "tvgTvgLoader.h" #include "tvgTvgLoader.h"
#include "tvgLzw.h" #include "tvgCompressor.h"
/************************************************************************/ /************************************************************************/

View file

@ -24,7 +24,7 @@
#include "tvgSaveModule.h" #include "tvgSaveModule.h"
#include "tvgTvgSaver.h" #include "tvgTvgSaver.h"
#include "tvgLzw.h" #include "tvgCompressor.h"
#include "tvgShapeImpl.h" #include "tvgShapeImpl.h"
#include "tvgPictureImpl.h" #include "tvgPictureImpl.h"

View file

@ -1,11 +1,11 @@
source_file = [ source_file = [
'tvgArray.h', 'tvgArray.h',
'tvgBezier.h', 'tvgBezier.h',
'tvgLzw.h', 'tvgCompressor.h',
'tvgMath.h', 'tvgMath.h',
'tvgStr.h', 'tvgStr.h',
'tvgBezier.cpp', 'tvgBezier.cpp',
'tvgLzw.cpp', 'tvgCompressor.cpp',
'tvgMath.cpp', 'tvgMath.cpp',
'tvgStr.cpp' 'tvgStr.cpp'
] ]

View file

@ -56,15 +56,18 @@
#include "config.h" #include "config.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
#include <string> #include <string>
#include <memory.h> #include <memory.h>
#include "tvgLzw.h" #include "tvgCompressor.h"
namespace tvg {
/************************************************************************/
/* LZW Implementation */
/************************************************************************/
namespace {
//LZW Dictionary helper: //LZW Dictionary helper:
constexpr int Nil = -1; constexpr int Nil = -1;
@ -334,15 +337,8 @@ static bool outputSequence(const Dictionary& dict, int code, uint8_t*& output, i
} }
return true; return true;
} }
}
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
namespace tvg {
uint8_t* lzwDecode(const uint8_t* compressed, uint32_t compressedSizeBytes, uint32_t compressedSizeBits, uint32_t uncompressedSizeBytes) uint8_t* lzwDecode(const uint8_t* compressed, uint32_t compressedSizeBytes, uint32_t compressedSizeBits, uint32_t uncompressedSizeBytes)
{ {
int code = Nil; int code = Nil;
@ -423,4 +419,57 @@ uint8_t* lzwEncode(const uint8_t* uncompressed, uint32_t uncompressedSizeBytes,
return bitStream.release(); return bitStream.release();
} }
/************************************************************************/
/* B64 Implementation */
/************************************************************************/
size_t b64Decode(const char* encoded, const size_t len, char** decoded)
{
static constexpr const char B64_INDEX[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 0, 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
};
if (!decoded || !encoded || len == 0) return 0;
auto reserved = 3 * (1 + (len >> 2)) + 1;
auto output = static_cast<char*>(malloc(reserved * sizeof(char)));
if (!output) return 0;
output[reserved - 1] = '\0';
size_t idx = 0;
while (*encoded && *(encoded + 1)) {
if (*encoded <= 0x20) {
++encoded;
continue;
}
auto value1 = B64_INDEX[(size_t)encoded[0]];
auto value2 = B64_INDEX[(size_t)encoded[1]];
output[idx++] = (value1 << 2) + ((value2 & 0x30) >> 4);
if (!encoded[2] || encoded[2] == '=' || encoded[2] == '.') break;
auto value3 = B64_INDEX[(size_t)encoded[2]];
output[idx++] = ((value2 & 0x0f) << 4) + ((value3 & 0x3c) >> 2);
if (!encoded[3] || encoded[3] == '=' || encoded[3] == '.') break;
auto value4 = B64_INDEX[(size_t)encoded[3]];
output[idx++] = ((value3 & 0x03) << 6) + value4;
encoded += 4;
}
*decoded = output;
return reserved;
}
} }

View file

@ -20,8 +20,8 @@
* SOFTWARE. * SOFTWARE.
*/ */
#ifndef _TVG_LZW_H_ #ifndef _TVG_COMPRESSOR_H_
#define _TVG_LZW_H_ #define _TVG_COMPRESSOR_H_
#include <cstdint> #include <cstdint>
@ -29,6 +29,7 @@ namespace tvg
{ {
uint8_t* lzwEncode(const uint8_t* uncompressed, uint32_t uncompressedSizeBytes, uint32_t* compressedSizeBytes, uint32_t* compressedSizeBits); uint8_t* lzwEncode(const uint8_t* uncompressed, uint32_t uncompressedSizeBytes, uint32_t* compressedSizeBytes, uint32_t* compressedSizeBits);
uint8_t* lzwDecode(const uint8_t* compressed, uint32_t compressedSizeBytes, uint32_t compressedSizeBits, uint32_t uncompressedSizeBytes); uint8_t* lzwDecode(const uint8_t* compressed, uint32_t compressedSizeBytes, uint32_t compressedSizeBits, uint32_t uncompressedSizeBytes);
size_t b64Decode(const char* encoded, const size_t len, char** decoded);
} }
#endif //_TVG_LZW_H #endif //_TVG_COMPRESSOR_H_