Implement the bytes command

The `bytes` command on HP calculators returns the size of the object
in the first level of the stack, and the CRC32 (hash) of the object
in the second level fo the stack.

The implememntation here returns the _complete_ representation of the
object in level 2. Also, the size is always an integral number of
bytes (the Saturn-based calculators were 4-bit, so byte sizes could be
half integer)

The lowest part of the number matches the result of the `type` command.

Fixes: #284

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
This commit is contained in:
Christophe de Dinechin 2023-08-02 23:49:20 +02:00
parent 2f651819cc
commit f36dda69dc
11 changed files with 69 additions and 11 deletions

View file

@ -83,8 +83,17 @@ Get newRPL version string
Get available memory in bytes
## BYTES
Size of an object in bytes and CRC32
## Bytes
Return the size of the object and a hash of its value. On classic RPL systems,
teh hash is a 5-nibbles CRC32. On DB48X, the hash is a based integer of the
current [wordsize](#stws) corresponding to the binary representation of the
object.
For example, the integer `7` hash will be in the form `#7xx`, where `7` is the
value of the integer, and `xx` represents the integer type.
`X``Hash` `Size`
## PEEK

View file

@ -7,7 +7,7 @@ extern const unsigned char EditorFont_sparse_font_data[];
const unsigned char EditorFont_sparse_font_data[74100] FONT_QSPI =
{
0x80, 0x02, 0xEF, 0xC2, 0x04, 0x36, 0x00, 0x01, 0x00, 0x2C, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01,
0x81, 0x02, 0xEF, 0xC2, 0x04, 0x36, 0x00, 0x01, 0x00, 0x2C, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01,
0x00, 0x2C, 0x01, 0x01, 0x08, 0x00, 0x20, 0x5F, 0x00, 0x2C, 0x01, 0x01, 0x08, 0x00, 0x02, 0x0B,
0x05, 0x21, 0x09, 0xEF, 0xBD, 0xF7, 0xDE, 0x7B, 0xEF, 0xBD, 0xF7, 0xDE, 0x7B, 0xEF, 0xBD, 0xF7,
0x1E, 0x00, 0x00, 0xB8, 0xFF, 0xFF, 0xFF, 0x0E, 0x03, 0x0B, 0x0B, 0x0F, 0x11, 0x8F, 0x7F, 0xFC,

View file

@ -7,7 +7,7 @@ extern const unsigned char HelpFont_sparse_font_data[];
const unsigned char HelpFont_sparse_font_data[15113] FONT_QSPI =
{
0x80, 0x02, 0x85, 0x76, 0x14, 0x00, 0x01, 0x00, 0x11, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01, 0x00,
0x81, 0x02, 0x85, 0x76, 0x14, 0x00, 0x01, 0x00, 0x11, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01, 0x00,
0x11, 0x01, 0x01, 0x03, 0x00, 0x20, 0x5F, 0x00, 0x11, 0x01, 0x01, 0x03, 0x00, 0x01, 0x04, 0x02,
0x0D, 0x04, 0xFF, 0xFF, 0xF3, 0x03, 0x01, 0x04, 0x04, 0x05, 0x06, 0xFF, 0xFF, 0x0F, 0x01, 0x04,
0x08, 0x0D, 0x0A, 0x12, 0x12, 0x14, 0x7F, 0x7F, 0x24, 0x24, 0x24, 0xFE, 0xFE, 0x28, 0x48, 0x48,

View file

@ -7,7 +7,7 @@ extern const unsigned char StackFont_sparse_font_data[];
const unsigned char StackFont_sparse_font_data[36629] FONT_QSPI =
{
0x80, 0x02, 0x90, 0x9E, 0x02, 0x24, 0x00, 0x01, 0x00, 0x1C, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01,
0x81, 0x02, 0x90, 0x9E, 0x02, 0x24, 0x00, 0x01, 0x00, 0x1C, 0x01, 0x01, 0x00, 0x00, 0x0D, 0x01,
0x00, 0x1C, 0x01, 0x01, 0x06, 0x00, 0x20, 0x5F, 0x00, 0x1C, 0x01, 0x01, 0x06, 0x00, 0x02, 0x05,
0x03, 0x17, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xC0, 0xFF, 0x1F, 0x02, 0x05, 0x08, 0x0A,
0x0C, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x01, 0x05, 0x0E, 0x17, 0x10,

View file

@ -29,6 +29,7 @@
#include "command.h"
#include "bignum.h"
#include "decimal-32.h"
#include "decimal-64.h"
#include "decimal128.h"
@ -317,6 +318,34 @@ COMMAND_BODY(Ticks)
COMMAND_BODY(Bytes)
// ----------------------------------------------------------------------------
// Return the bytes and a binary represenetation of the object
// ----------------------------------------------------------------------------
{
if (object_p top = rt.top())
{
size_t size = top->size();
size_t maxsize = (Settings.wordsize + 7) / 8;
size_t hashsize = size > maxsize ? maxsize : size;
gcbytes bytes = byte_p(top);
#if CONFIG_FIXED_BASED_OBJECTS
// Force base 16 if we have that option
const id type = ID_hex_bignum;
#else // !CONFIG_FIXED_BASED_OBJECTS
const id type = ID_based_bignum;
#endif // CONFIG_FIXED_BASED_OBJECTS
if (bignum_p bin = rt.make<bignum>(type, bytes, hashsize))
if (rt.top(bin))
if (rt.push(integer::make(size)))
return OK;
}
return ERROR;
}
COMMAND_BODY(Off)
// ----------------------------------------------------------------------------
// Switch the calculator off

View file

@ -136,6 +136,7 @@ COMMAND_DECLARE(Eval); // Evaluate an object
COMMAND_DECLARE(ToText); // Convert an object to text
COMMAND_DECLARE(SelfInsert); // Enter menu label in the editor
COMMAND_DECLARE(Ticks); // Return number of ticks
COMMAND_DECLARE(Bytes); // Return the bytes representation of object
COMMAND_DECLARE(Off); // Switch the calculator off
COMMAND_DECLARE(SaveState); // Save state to disk
COMMAND_DECLARE(SystemSetup); // Select the system menu

View file

@ -303,6 +303,7 @@ CMD(GarbageCollect)
CMD(HomeDirectory)
CMD(Ticks)
CMD(Bytes)
// ============================================================================

View file

@ -672,7 +672,7 @@ MENU(ObjectMenu,
// ----------------------------------------------------------------------------
"→Obj", ID_Unimplemented,
"Obj→", ID_Unimplemented,
"Bytes", ID_Unimplemented,
"Bytes", ID_Bytes,
"Type", ID_Unimplemented,
"Clone", ID_Unimplemented,
"Size", ID_Unimplemented,

View file

@ -742,7 +742,7 @@ SETTINGS_COMMAND_LABEL(stws)
// ----------------------------------------------------------------------------
{
static char buffer[16];
snprintf(buffer, sizeof(buffer), "WSz %u", Settings.wordsize);
snprintf(buffer, sizeof(buffer), "WSz %zu", Settings.wordsize);
return buffer;
}
@ -956,7 +956,7 @@ SETTINGS_COMMAND_LABEL(MaxBigNumBits)
// ----------------------------------------------------------------------------
{
static char buffer[16];
snprintf(buffer, sizeof(buffer), "BigNum %u", Settings.maxbignum);
snprintf(buffer, sizeof(buffer), "BigNum %zu", Settings.maxbignum);
return buffer;
}

View file

@ -175,8 +175,8 @@ public:
uint16_t standard_exp; // Maximum exponent before switching to sci
angles angle_mode; // Angle mode ( degrees, radians or grads)
uint8_t base; // The default base for #numbers
uint16_t wordsize; // Wordsize for binary numbers (in bits)
uint16_t maxbignum; // Maximum size for a bignum (in bits)
size_t wordsize; // Wordsize for binary numbers (in bits)
size_t maxbignum; // Maximum size for a bignum (in bits)
uint16_t maxrewrites; // Maximum number of rewrites
uint16_t fraciter; // Number of iterations for ->Q
uint16_t fracprec; // Number of digits for ->Q

View file

@ -97,8 +97,16 @@ void tests::current()
// Test the current thing (this is a temporary test)
// ----------------------------------------------------------------------------
{
fraction_decimal_conversions();
step ("Bytes command");
test(CLEAR, "12", ENTER, "bytes", ENTER)
.expect("2")
.test(BSP)
.match("#C....");
test(CLEAR, "129", ENTER, "bytes", ENTER)
.expect("3")
.test(BSP)
.match("#181....");
#if 0
step("Testing sign of modulo for bignum");
@ -396,6 +404,16 @@ void tests::data_types()
test(DOWN, CHS, ENTER).type(object::ID_big_fraction).expect(mbf+1);
clear();
step ("Bytes command");
test(CLEAR, "12", ENTER, "bytes", ENTER)
.expect("2")
.test(BSP)
.match("#C....");
test(CLEAR, "129", ENTER, "bytes", ENTER)
.expect("3")
.test(BSP)
.match("#181....");
}