Skip to content

Commit

Permalink
Allow Storage.read to make partial file reads (fix #1744)
Browse files Browse the repository at this point in the history
  • Loading branch information
gfwilliams committed Jan 13, 2020
1 parent 4a7be3f commit 24dac19
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 20 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Expand Up @@ -61,6 +61,7 @@
Bangle.js: Bangle.setLCDMode now errors if it can't allocate a flat string (also garbage collects and defrags to try and ensure it can)
Graphics: drawEllipse/fillEllipse now work correctly for very small ellipses
Fix type compare of string and flatstring
Allow Storage.read to make partial file reads (fix #1744)

2v04 : Allow \1..\9 escape codes in RegExp
ESP8266: reading storage is not working for boot from user2 (fix #1507)
Expand Down
2 changes: 1 addition & 1 deletion libs/banglejs/jswrap_bangle.c
Expand Up @@ -1529,7 +1529,7 @@ bool jswrap_banglejs_idle() {
}
#ifdef USE_TENSORFLOW
if (bangle && jsiObjectHasCallbacks(bangle, JS_EVENT_PREFIX"aiGesture")) {
//JsVar *model = jsfReadFile(jsfNameFromString(".tfmodel"));
//JsVar *model = jsfReadFile(jsfNameFromString(".tfmodel"),0,0);
JsfFileHeader header;
uint32_t modelAddr = jsfFindFile(jsfNameFromString(".tfmodel"), &header);

Expand Down
2 changes: 1 addition & 1 deletion libs/pixljs/jswrap_pixljs.c
Expand Up @@ -414,7 +414,7 @@ void jswrap_pixljs_init() {
* With bootloader this means apply power while holding button for >3 secs */
static bool firstStart = true;

JsVar *splashScreen = jsfReadFile(jsfNameFromString(".splash"));
JsVar *splashScreen = jsfReadFile(jsfNameFromString(".splash"),0,0);
if (jsvIsString(splashScreen)) {
if (jsvGetStringLength(splashScreen)) {
graphicsSetVar(&gfx);
Expand Down
29 changes: 19 additions & 10 deletions src/jsflash.c
Expand Up @@ -491,34 +491,43 @@ void jsfDebugFiles() {
} while (jsfGetNextFileHeader(&addr, &header, GNFH_GET_ALL));
}

JsVar *jsfReadFile(JsfFileName name) {
JsVar *jsfReadFile(JsfFileName name, int offset, int length) {
JsfFileHeader header;
uint32_t addr = jsfFindFile(name, &header);
if (!addr) return 0;
// clip requested read lengths
if (offset<0) offset=0;
uint32_t fileLen = jsfGetFileSize(&header);
if (length<=0) length=fileLen;
if (offset>fileLen) offset=fileLen;
if (offset+length>fileLen) length=fileLen-offset;
if (length<=0) return jsvNewFromEmptyString();
// now increment address by offset
addr += offset;

#ifdef LINUX
// linux fakes flash with a file, so we can't just return a pointer to it!
uint32_t alignedSize = jsfAlignAddress(jsfGetFileSize(&header));
uint32_t alignedSize = jsfAlignAddress(length);
char *d = (char*)malloc(alignedSize);
jshFlashRead(d, addr, alignedSize);
JsVar *v = jsvNewStringOfLength(jsfGetFileSize(&header), d);
JsVar *v = jsvNewStringOfLength(length, d);
free(d);
return v;
#else
size_t mappedAddr = jshFlashGetMemMapAddress((size_t)addr);
uint32_t len = jsfGetFileSize(&header);
#ifdef SPIFLASH_BASE // if using SPI flash it can't be memory-mapped
if (!mappedAddr) {
JsVar *v = jsvNewStringOfLength(len, NULL);
JsVar *v = jsvNewStringOfLength(length, NULL);
if (v) {
JsvStringIterator it;
jsvStringIteratorNew(&it, v, 0);
while (len && jsvStringIteratorHasChar(&it)) {
while (length && jsvStringIteratorHasChar(&it)) {
unsigned char *data;
unsigned int l = 0;
jsvStringIteratorGetPtrAndNext(&it, &data, &l);
jshFlashRead(data, addr, l);
addr += l;
len -= l;
length -= l;
}
jsvStringIteratorFree(&it);
}
Expand Down Expand Up @@ -744,17 +753,17 @@ void jsfSaveBootCodeToFlash(JsVar *code, bool runAfterReset) {
}

JsVar *jsfGetBootCodeFromFlash(bool isReset) {
JsVar *resetCode = jsfReadFile(jsfNameFromString(SAVED_CODE_BOOTCODE_RESET));
JsVar *resetCode = jsfReadFile(jsfNameFromString(SAVED_CODE_BOOTCODE_RESET),0,0);
if (isReset || resetCode) return resetCode;
return jsfReadFile(jsfNameFromString(SAVED_CODE_BOOTCODE));
return jsfReadFile(jsfNameFromString(SAVED_CODE_BOOTCODE),0,0);
}

bool jsfLoadBootCodeFromFlash(bool isReset) {
// Load code in .boot0/1/2/3
char filename[7] = ".bootX";
for (int i=0;i<4;i++) {
filename[5] = (char)('0'+i);
JsVar *code = jsfReadFile(jsfNameFromString(filename));
JsVar *code = jsfReadFile(jsfNameFromString(filename),0,0);
if (code)
jsvUnLock2(jspEvaluateVar(code,0,0), code);
}
Expand Down
2 changes: 1 addition & 1 deletion src/jsflash.h
Expand Up @@ -51,7 +51,7 @@ JsfFileFlags jsfGetFileFlags(JsfFileHeader *header);
/// Find a 'file' in the memory store. Return the address of data start (and header if returnedHeader!=0). Returns 0 if not found
uint32_t jsfFindFile(JsfFileName name, JsfFileHeader *returnedHeader);
/// Return the contents of a file as a memory mapped var
JsVar *jsfReadFile(JsfFileName name);
JsVar *jsfReadFile(JsfFileName name, int offset, int length);
/// Write a file. For simple stuff just leave offset and size as 0
bool jsfWriteFile(JsfFileName name, JsVar *data, JsfFileFlags flags, JsVarInt offset, JsVarInt _size);
/// Erase the given file, return true on success
Expand Down
2 changes: 1 addition & 1 deletion src/jswrap_modules.c
Expand Up @@ -90,7 +90,7 @@ JsVar *jswrap_require(JsVar *moduleName) {
// Has it been manually saved to Flash Storage? Use Storage support.
if ((!moduleExport) && (strlen(moduleNameBuf) <= JSF_MAX_FILENAME_LENGTH)) {
JsfFileName storageName = jsfNameFromString(moduleNameBuf);
JsVar *storageFile = jsfReadFile(storageName);
JsVar *storageFile = jsfReadFile(storageName,0,0);
if (storageFile) {
moduleExport = jspEvaluateModule(storageFile);
jsvUnLock(storageFile);
Expand Down
12 changes: 7 additions & 5 deletions src/jswrap_storage.c
Expand Up @@ -82,7 +82,9 @@ void jswrap_storage_erase(JsVar *name) {
"name" : "read",
"generate" : "jswrap_storage_read",
"params" : [
["name","JsVar","The filename - max 8 characters (case sensitive)"]
["name","JsVar","The filename - max 8 characters (case sensitive)"],
["offset","int","(optional) The offset in bytes to start from"],
["length","int","(optional) The length to read in bytes (if <=0, the entire file is read)"]
],
"return" : ["JsVar","A string of data"]
}
Expand All @@ -96,8 +98,8 @@ If you evaluate this string with `eval`, any functions
contained in the String will keep their code stored
in flash memory.
*/
JsVar *jswrap_storage_read(JsVar *name) {
return jsfReadFile(jsfNameFromVar(name));
JsVar *jswrap_storage_read(JsVar *name, int offset, int length) {
return jsfReadFile(jsfNameFromVar(name), offset, length);
}

/*JSON{
Expand All @@ -118,7 +120,7 @@ and parse JSON in it into a JavaScript object.
This is identical to `JSON.parse(require("Storage").read(...))`
*/
JsVar *jswrap_storage_readJSON(JsVar *name) {
JsVar *v = jsfReadFile(jsfNameFromVar(name));
JsVar *v = jsfReadFile(jsfNameFromVar(name),0,0);
if (!v) return 0;
JsVar *r = jswrap_json_parse(v);
jsvUnLock(v);
Expand Down Expand Up @@ -146,7 +148,7 @@ This can be used:
* In a `Uint8Array/Float32Array/etc` with `new Uint8Array(require("Storage").readArrayBuffer("x"))`
*/
JsVar *jswrap_storage_readArrayBuffer(JsVar *name) {
JsVar *v = jsfReadFile(jsfNameFromVar(name));
JsVar *v = jsfReadFile(jsfNameFromVar(name),0,0);
if (!v) return 0;
JsVar *r = jsvNewArrayBufferFromString(v, 0);
jsvUnLock(v);
Expand Down
2 changes: 1 addition & 1 deletion src/jswrap_storage.h
Expand Up @@ -16,7 +16,7 @@
#define WIFI_CONFIG_STORAGE_NAME ".wificfg"

void jswrap_storage_eraseAll();
JsVar *jswrap_storage_read(JsVar *name);
JsVar *jswrap_storage_read(JsVar *name, int offset, int length);
JsVar *jswrap_storage_readJSON(JsVar *name);
JsVar *jswrap_storage_readArrayBuffer(JsVar *name);
bool jswrap_storage_write(JsVar *name, JsVar *data, JsVarInt offset, JsVarInt size);
Expand Down

0 comments on commit 24dac19

Please sign in to comment.