Skip to content

Commit

Permalink
Merge pull request #16977 from s-hadinger/berry_bytes_reverse
Browse files Browse the repository at this point in the history
Added Berry ``bytes().reverse()`` method
  • Loading branch information
s-hadinger committed Nov 2, 2022
2 parents da65c87 + 4c896cd commit fe6aecc
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
- Support for Digital Addressable Lighting Interface (DALI) by Andrei Kazmirtsuk (#16938)
- Support for two phase power calibration using commands ``PowerSet2``, ``VoltageSet2`` and ``CurrentSet2``
- Support for NTAG2xx tags read and write on PN532 NFC reader (#16939)
- Added Berry ``bytes().reverse()`` method

### Breaking Changed

Expand Down
69 changes: 65 additions & 4 deletions lib/libesp32/berry/src/be_byteslib.c
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,6 @@ static int m_setfloat(bvm *vm)
* `setbytes(index:int, fill:bytes [, from:int, len:int]) -> nil`
*
*/
#include <stdio.h>
static int m_setbytes(bvm *vm)
{
int argc = be_top(vm);
Expand All @@ -968,7 +967,7 @@ static int m_setbytes(bvm *vm)
size_t from_len_total;
const uint8_t* buf_ptr = (const uint8_t*) be_tobytes(vm, 3, &from_len_total);
if (idx < 0) { idx = 0; }
if ((size_t)idx >= attr.len) { idx = attr.len; }
if (idx >= attr.len) { idx = attr.len; }

int32_t from_byte = 0;
if (argc >= 4 && be_isint(vm, 4)) {
Expand All @@ -981,9 +980,9 @@ static int m_setbytes(bvm *vm)
if (argc >= 5 && be_isint(vm, 5)) {
from_len = be_toint(vm, 5);
if (from_len < 0) { from_len = 0; }
if (from_len >= from_len_total) { from_len = from_len_total; }
if (from_len >= (int32_t)from_len_total) { from_len = from_len_total; }
}
if ((size_t) idx + (size_t)from_len >= attr.len) { from_len = attr.len - idx; }
if (idx + from_len >= attr.len) { from_len = attr.len - idx; }

// all parameters ok
if (from_len > 0) {
Expand All @@ -993,6 +992,66 @@ static int m_setbytes(bvm *vm)
be_return_nil(vm);
}


/*
* Reverses in-place a sub-buffer composed of groups of n-bytes packets
*
* This is useful for pixel manipulation when displaying RGB pixels
*
* `reverse([index:int, len:int, grouplen:int]) -> self`
*
*/
static int m_reverse(bvm *vm)
{
int argc = be_top(vm);
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
check_ptr(vm, &attr);

int32_t idx = 0; /* start from index 0 */
int32_t len = attr.len; /* entire len */
int32_t grouplen = 1; /* default to 1-byte group */

if (argc >= 2 && be_isint(vm, 2)) {
idx = be_toint(vm, 2);
if (idx < 0) { idx = 0; } /* railguards */
if (idx > attr.len) { idx = attr.len; }
}
if (argc >= 3 && be_isint(vm, 3)) {
len = be_toint(vm, 3);
if (len < 0) { len = attr.len - idx; } /* negative len means */
}
if (idx + len >= attr.len) { len = attr.len - idx; }

// truncate len to multiple of grouplen
if (argc >= 4 && be_isint(vm, 4)) {
grouplen = be_toint(vm, 4);
if (grouplen <= 0) { grouplen = 1; }
}
len = len - (len % grouplen);

// apply reverse
if (len > 0) {
if (grouplen == 1) {
/* fast version if simple byte inversion */
for (int32_t i = idx, j = idx + len -1; i < j; i++, j--) {
uint8_t temp = attr.bufptr[i];
attr.bufptr[i] = attr.bufptr[j];
attr.bufptr[j] = temp;
}
} else {
for (int32_t i = idx, j = idx + len - grouplen; i < j; i += grouplen, j -= grouplen) {
for (int32_t k = 0; k < grouplen; k++) {
uint8_t temp = attr.bufptr[i+k];
attr.bufptr[i+k] = attr.bufptr[j+k];
attr.bufptr[j+k] = temp;
}
}
}
}
be_pushvalue(vm, 1); /* push bytes object */
be_return(vm);
}

static int m_setitem(bvm *vm)
{
int argc = be_top(vm);
Expand Down Expand Up @@ -1627,6 +1686,7 @@ void be_load_byteslib(bvm *vm)
{ "size", m_size },
{ "resize", m_resize },
{ "clear", m_clear },
{ "reverse", m_reverse },
{ "copy", m_copy },
{ "+", m_merge },
{ "..", m_connect },
Expand Down Expand Up @@ -1672,6 +1732,7 @@ class be_class_bytes (scope: global, name: bytes) {
size, func(m_size)
resize, func(m_resize)
clear, func(m_clear)
reverse, func(m_reverse)
copy, func(m_copy)
+, func(m_merge)
.., func(m_connect)
Expand Down
23 changes: 23 additions & 0 deletions lib/libesp32/berry/tests/bytes.be
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,26 @@ assert(a == bytes('112233445566CCDD99'))
a = b.copy()
a.setbytes(0, a0)
assert(a == bytes('112233445566'))

# reverse
assert(bytes().reverse() == bytes())
assert(bytes("AA").reverse() == bytes("AA"))
assert(bytes("1122334455").reverse() == bytes("5544332211"))
assert(bytes("11223344").reverse() == bytes("44332211"))

assert(bytes("0011223344").reverse(1) == bytes("0044332211"))
assert(bytes("0011223344").reverse(3) == bytes("0011224433"))
assert(bytes("0011223344").reverse(4) == bytes("0011223344"))
assert(bytes("0011223344").reverse(5) == bytes("0011223344"))
assert(bytes("0011223344").reverse(15) == bytes("0011223344"))
assert(bytes("0011223344").reverse(-2) == bytes("4433221100"))

assert(bytes("0011223344").reverse(1,3) == bytes("0033221144"))
assert(bytes("0011223344").reverse(1,0) == bytes("0011223344"))
assert(bytes("0011223344").reverse(2,2) == bytes("0011332244"))
assert(bytes("0011223344").reverse(0,2) == bytes("1100223344"))
assert(bytes("0011223344").reverse(nil,2) == bytes("1100223344"))
assert(bytes("0011223344").reverse(1, nil) == bytes("0044332211"))

assert(bytes("0011223344").reverse(nil, nil, 2) == bytes("2233001144"))
assert(bytes("001122334455").reverse(nil, nil, 3) == bytes("334455001122"))

0 comments on commit fe6aecc

Please sign in to comment.