diff --git a/lib/default/Unishox-1.0-shadinger/src/unishox.cpp b/lib/default/Unishox-1.0-shadinger/src/unishox.cpp
index 51c9d4701..1c0fd7142 100644
--- a/lib/default/Unishox-1.0-shadinger/src/unishox.cpp
+++ b/lib/default/Unishox-1.0-shadinger/src/unishox.cpp
@@ -76,13 +76,6 @@ static char sets[][11] PROGMEM =
{'.', ',', '-', '/', '?', '+', ' ', '(', ')', '$', '@'},
{';', '#', ':', '<', '^', '*', '"', '{', '}', '[', ']'},
{'=', '%', '\'', '>', '&', '_', '!', '\\', '|', '~', '`'}};
- // {{ 0, ' ', 'e', 0, 't', 'a', 'o', 'i', 'n', 's', 'r'},
- // { 0, 'l', 'c', 'd', 'h', 'u', 'p', 'm', 'b', 'g', 'w'},
- // {'f', 'y', 'v', 'k', 'q', 'j', 'x', 'z', 0, 0, 0},
- // { 0, '9', '0', '1', '2', '3', '4', '5', '6', '7', '8'},
- // {'.', ',', '-', '/', '=', '+', ' ', '(', ')', '$', '%'},
- // {'&', ';', ':', '<', '>', '*', '"', '{', '}', '[', ']'},
- // {'@', '?', '\'', '^', '#', '_', '!', '\\', '|', '~', '`'}};
// Decoder is designed for using less memory, not speed
// Decode lookup table for code index and length
@@ -117,28 +110,16 @@ static const uint16_t DICT_CODE = 0x0000;
static const uint16_t DICT_CODE_LEN = 5;
static const uint16_t DICT_OTHER_CODE = 0x0000; // not used
static const uint16_t DICT_OTHER_CODE_LEN = 6;
-// const uint16_t RPT_CODE = 0x2370;
-// const uint16_t RPT_CODE_LEN = 13;
static const uint16_t RPT_CODE_TASMOTA = 0x3780;
static const uint16_t RPT_CODE_TASMOTA_LEN = 10;
static const uint16_t BACK2_STATE1_CODE = 0x2000; // 0010 = back to lower case
static const uint16_t BACK2_STATE1_CODE_LEN = 4;
static const uint16_t BACK_FROM_UNI_CODE = 0xFE00;
static const uint16_t BACK_FROM_UNI_CODE_LEN = 8;
-// const uint16_t CRLF_CODE = 0x3780;
-// const uint16_t CRLF_CODE_LEN = 10;
static const uint16_t LF_CODE = 0x3700;
static const uint16_t LF_CODE_LEN = 9;
static const uint16_t TAB_CODE = 0x2400;
static const uint16_t TAB_CODE_LEN = 7;
-// const uint16_t UNI_CODE = 0x8000; // Unicode disabled
-// const uint16_t UNI_CODE_LEN = 3;
-// const uint16_t UNI_STATE_SPL_CODE = 0xF800;
-// const uint16_t UNI_STATE_SPL_CODE_LEN = 5;
-// const uint16_t UNI_STATE_DICT_CODE = 0xFC00;
-// const uint16_t UNI_STATE_DICT_CODE_LEN = 7;
-// const uint16_t CONT_UNI_CODE = 0x2800;
-// const uint16_t CONT_UNI_CODE_LEN = 7;
static const uint16_t ALL_UPPER_CODE = 0x2200;
static const uint16_t ALL_UPPER_CODE_LEN = 8;
static const uint16_t SW2_STATE2_CODE = 0x3800;
@@ -147,8 +128,6 @@ static const uint16_t ST2_SPC_CODE = 0x3B80;
static const uint16_t ST2_SPC_CODE_LEN = 11;
static const uint16_t BIN_CODE_TASMOTA = 0x8000;
static const uint16_t BIN_CODE_TASMOTA_LEN = 3;
-// const uint16_t BIN_CODE = 0x2000;
-// const uint16_t BIN_CODE_LEN = 9;
#define NICE_LEN 5
@@ -467,9 +446,9 @@ void Unishox::decodeRepeat(void) {
uint32_t dict_len = readCount() + NICE_LEN;
uint32_t dist = readCount() + NICE_LEN - 1;
if (ol + dict_len <= len_out) {
- memcpy(out + ol, out + ol - dist, dict_len);
- ol += dict_len;
-}
+ memcpy(out + ol, out + ol - dist, dict_len);
+ ol += dict_len;
+ }
}
int32_t Unishox::unishox_decompress(const char *p_in, size_t p_len, char *p_out, size_t p_len_out) {
@@ -485,10 +464,10 @@ int32_t Unishox::unishox_decompress(const char *p_in, size_t p_len, char *p_out,
dstate = SHX_SET1;
is_all_upper = 0;
- out[ol] = 0;
+ if (out) out[ol] = 0;
// while ((byte_no << 3) + bit_no - 8 < len) {
while (!in_eof) {
- if (ol >= len_out) {
+ if (out && ol >= len_out) {
break;
}
int32_t h, v;
@@ -535,7 +514,8 @@ int32_t Unishox::unishox_decompress(const char *p_in, size_t p_len, char *p_out,
if (v == 0 && h == SHX_SET1A) {
if (is_upper) {
- out[ol++] = 255 - readCount(); // binary
+ if (out) out[ol] = 255 - readCount(); // binary
+ ol++;
} else {
decodeRepeat(); // dist
}
@@ -544,7 +524,8 @@ int32_t Unishox::unishox_decompress(const char *p_in, size_t p_len, char *p_out,
if (h == SHX_SET1 && v == 3) {
// was Unicode, will do Binary instead
- out[ol++] = 255 - readCount(); // binary
+ if (out) out[ol] = 255 - readCount(); // binary
+ ol++;
continue;
}
if (h < 7 && v < 11) // TODO: are these the actual limits? Not 11x7 ?
@@ -557,17 +538,22 @@ int32_t Unishox::unishox_decompress(const char *p_in, size_t p_len, char *p_out,
c = '\t'; // If UpperCase Space, change to TAB
if (h == SHX_SET1B) {
if (8 == v) { // was LF or RPT, now only LF
- out[ol++] = '\n';
+ if (out) out[ol] = '\n';
+ ol++;
continue;
}
if (9 == v) { // was CRLF, now RPT
uint32_t count = readCount() + 4;
- if (ol + count >= len_out) {
+ if (out && ol + count >= len_out) {
return -1; // overflow
}
- char rpt_c = out[ol - 1];
- while (count--)
- out[ol++] = rpt_c;
+ if (out) {
+ char rpt_c = out[ol - 1];
+ while (count--)
+ out[ol++] = rpt_c;
+ } else {
+ ol += count;
+ }
continue;
}
if (10 == v) {
@@ -576,10 +562,11 @@ int32_t Unishox::unishox_decompress(const char *p_in, size_t p_len, char *p_out,
}
}
// Serial.printf(">>>>>>>>>>>>>>>>>>>>>> Out = %c\n", c);
- out[ol++] = c;
+ if (out) out[ol] = c;
+ ol++;
}
- if (ol > len_out) {
+ if (out && ol > len_out) {
return -1; // overflow
} else {
return ol;
diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/Berry/default/be_modtab.c
index 3ce4cecd3..46b5528a9 100644
--- a/lib/libesp32/Berry/default/be_modtab.c
+++ b/lib/libesp32/Berry/default/be_modtab.c
@@ -32,6 +32,7 @@ be_extern_native_module(energy);
be_extern_native_module(webserver);
be_extern_native_module(flash);
be_extern_native_module(path);
+be_extern_native_module(unishox);
#ifdef USE_LVGL
be_extern_native_module(lv);
#endif // USE_LVGL
@@ -89,6 +90,10 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
&be_native_module(light),
#endif
+#ifdef USE_UNISHOX_COMPRESSION
+ &be_native_module(unishox),
+#endif // USE_UNISHOX_COMPRESSION
+
#ifdef USE_LVGL
&be_native_module(lv),
#endif // USE_LVGL
diff --git a/lib/libesp32/Berry/default/be_unishox_lib.c b/lib/libesp32/Berry/default/be_unishox_lib.c
new file mode 100644
index 000000000..867e0870a
--- /dev/null
+++ b/lib/libesp32/Berry/default/be_unishox_lib.c
@@ -0,0 +1,28 @@
+/********************************************************************
+ * Berry module `unishox`
+ *
+ * To use: `import unishox`
+ *
+ * Allows to respond to HTTP request
+ *******************************************************************/
+#include "be_constobj.h"
+
+#ifdef USE_UNISHOX_COMPRESSION
+
+extern int be_unishox_compress(bvm *vm);
+extern int be_unishox_decompress(bvm *vm);
+
+/********************************************************************
+** Solidified module: unishox
+********************************************************************/
+be_local_module(unishox,
+ "unishox",
+ be_nested_map(2,
+ ( (struct bmapnode*) &(const bmapnode[]) {
+ { be_nested_key("decompress", -1407935646, 10, -1), be_const_func(be_unishox_decompress) },
+ { be_nested_key("compress", -1476883059, 8, -1), be_const_func(be_unishox_compress) },
+ }))
+);
+BE_EXPORT_VARIABLE be_define_const_native_module(unishox);
+
+#endif // USE_UNISHOX_COMPRESSION
diff --git a/tasmota/xdrv_52_3_berry_unishox.ino b/tasmota/xdrv_52_3_berry_unishox.ino
new file mode 100644
index 000000000..a7664a960
--- /dev/null
+++ b/tasmota/xdrv_52_3_berry_unishox.ino
@@ -0,0 +1,94 @@
+/*
+ xdrv_52_3_berry_unishox.ino - Berry scripting language, native fucnctions
+
+ Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+
+#ifdef USE_BERRY
+
+#include
+
+#ifdef USE_UNISHOX_COMPRESSION
+
+extern Unishox compressor;
+
+/*********************************************************************************************\
+ * Native functions mapped to Berry functions
+ *
+ * import unishox
+ *
+ *
+\*********************************************************************************************/
+extern "C" {
+
+ int be_unishox_compress(bvm *vm);
+ int be_unishox_compress(bvm *vm) {
+ int32_t argc = be_top(vm); // Get the number of arguments
+ if (argc == 1 && be_isstring(vm, 1)) {
+ const char * s = be_tostring(vm, 1);
+ // do a dry-run to know the compressed size
+ int32_t compressed_size = compressor.unishox_compress(s, strlen(s), (char*) nullptr, 0);
+ if (compressed_size < 0) {
+ be_raise(vm, "internal_error", nullptr);
+ }
+ void * buf = be_pushbytes(vm, NULL, compressed_size);
+ if (compressed_size > 0) {
+ int32_t ret = compressor.unishox_compress(s, strlen(s), (char*) buf, compressed_size+5); // We expand by 4 the buffer size to avoid an error, but we are sure it will not overflow (see unishox implementation)
+ if (ret < 0 || ret != compressed_size) {
+ be_raisef(vm, "internal_error", "unishox size=%i ret=%i", compressed_size, ret);
+ }
+ }
+ be_return(vm);
+ }
+ be_raise(vm, kTypeError, nullptr);
+ }
+
+ int be_unishox_decompress(bvm *vm);
+ int be_unishox_decompress(bvm *vm) {
+ int32_t argc = be_top(vm); // Get the number of arguments
+ if (argc == 1 && be_isbytes(vm, 1)) {
+ size_t len;
+ const void * buf = be_tobytes(vm, 1, &len);
+ if (len == 0) {
+ be_pushstring(vm, "");
+ } else {
+ int32_t decomp_size = compressor.unishox_decompress((const char*)buf, len, (char*) nullptr, 0);
+ if (decomp_size < 0) {
+ be_raise(vm, "internal_error", nullptr);
+ }
+ if (decomp_size == 0) {
+ be_pushstring(vm, "");
+ } else {
+ void * buf_out = be_pushbuffer(vm, decomp_size);
+ int32_t ret = compressor.unishox_decompress((const char*)buf, len, (char*) buf_out, decomp_size);
+ if (ret < 0 || ret != decomp_size) {
+ be_raisef(vm, "internal_error", "unishox size=%i ret=%i", decomp_size, ret);
+ }
+ be_pushnstring(vm, (const char*) buf_out, decomp_size);
+ }
+ }
+ be_return(vm);
+ }
+ be_raise(vm, kTypeError, nullptr);
+ }
+
+}
+
+
+#endif // USE_UNISHOX_COMPRESSION
+
+#endif // USE_BERRY