First draft of storage APIs (#122)
* First draft of storage APIs * bumped pxt-core * using fixed instances to seprate temp from permanent * send console to storage * sim support * missing sim stubs * adding storage blocks * more sim support * remove storage from default package * fix rendering of ms * render raw ms * slize at better place * duplicate bundled dir * refactor limit * simplify limit logic
This commit is contained in:
		
				
					committed by
					
						
						Peli de Halleux
					
				
			
			
				
	
			
			
			
						parent
						
							966fd81870
						
					
				
				
					commit
					20a4673f98
				
			@@ -10,10 +10,12 @@
 | 
				
			|||||||
  "MMap.getNumber": "Read a number in specified format from the buffer.",
 | 
					  "MMap.getNumber": "Read a number in specified format from the buffer.",
 | 
				
			||||||
  "MMap.ioctl": "Perform ioctl(2) on the underlaying file",
 | 
					  "MMap.ioctl": "Perform ioctl(2) on the underlaying file",
 | 
				
			||||||
  "MMap.length": "Returns the length of a Buffer object.",
 | 
					  "MMap.length": "Returns the length of a Buffer object.",
 | 
				
			||||||
 | 
					  "MMap.lseek": "Set pointer on the underlaying file.",
 | 
				
			||||||
  "MMap.read": "Perform read(2) on the underlaying file",
 | 
					  "MMap.read": "Perform read(2) on the underlaying file",
 | 
				
			||||||
  "MMap.setNumber": "Write a number in specified format in the buffer.",
 | 
					  "MMap.setNumber": "Write a number in specified format in the buffer.",
 | 
				
			||||||
  "MMap.slice": "Read a range of bytes into a buffer.",
 | 
					  "MMap.slice": "Read a range of bytes into a buffer.",
 | 
				
			||||||
  "MMap.write": "Perform write(2) on the underlaying file",
 | 
					  "MMap.write": "Perform write(2) on the underlaying file",
 | 
				
			||||||
 | 
					  "SeekWhence": "Mode for lseek()",
 | 
				
			||||||
  "brick.Button": "Generic button class, for device buttons and sensors.",
 | 
					  "brick.Button": "Generic button class, for device buttons and sensors.",
 | 
				
			||||||
  "brick.Button.isPressed": "Check if button is currently pressed or not.",
 | 
					  "brick.Button.isPressed": "Check if button is currently pressed or not.",
 | 
				
			||||||
  "brick.Button.onEvent": "Do something when a button or sensor is clicked, up or down.",
 | 
					  "brick.Button.onEvent": "Do something when a button or sensor is clicked, up or down.",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								libs/core/enums.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								libs/core/enums.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,17 @@
 | 
				
			|||||||
// Auto-generated. Do not edit.
 | 
					// Auto-generated. Do not edit.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Mode for lseek()
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    declare const enum SeekWhence {
 | 
				
			||||||
 | 
					    Set = 0,
 | 
				
			||||||
 | 
					    Current = 1,
 | 
				
			||||||
 | 
					    End = 2,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Drawing modes
 | 
					     * Drawing modes
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,16 @@
 | 
				
			|||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <sys/ioctl.h>
 | 
					#include <sys/ioctl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* Mode for lseek()
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					enum class SeekWhence {
 | 
				
			||||||
 | 
					    Set = 0,
 | 
				
			||||||
 | 
					    Current = 1,
 | 
				
			||||||
 | 
					    End = 2,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace pxt {
 | 
					namespace pxt {
 | 
				
			||||||
PXT_VTABLE_CTOR(MMap) {
 | 
					PXT_VTABLE_CTOR(MMap) {
 | 
				
			||||||
    length = 0;
 | 
					    length = 0;
 | 
				
			||||||
@@ -111,4 +121,10 @@ int read(MMap *mmap, Buffer data) {
 | 
				
			|||||||
    return ::read(mmap->fd, data->data, data->length);
 | 
					    return ::read(mmap->fd, data->data, data->length);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Set pointer on the underlaying file. */
 | 
				
			||||||
 | 
					//%
 | 
				
			||||||
 | 
					int lseek(MMap *mmap, int offset, SeekWhence whence) {
 | 
				
			||||||
 | 
					    return ::lseek(mmap->fd, offset, (int)whence);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								libs/core/shims.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								libs/core/shims.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -41,6 +41,10 @@ declare interface MMap {
 | 
				
			|||||||
    /** Perform read(2) on the underlaying file */
 | 
					    /** Perform read(2) on the underlaying file */
 | 
				
			||||||
    //% shim=MMapMethods::read
 | 
					    //% shim=MMapMethods::read
 | 
				
			||||||
    read(data: Buffer): int32;
 | 
					    read(data: Buffer): int32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Set pointer on the underlaying file. */
 | 
				
			||||||
 | 
					    //% shim=MMapMethods::lseek
 | 
				
			||||||
 | 
					    lseek(offset: int32, whence: SeekWhence): int32;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
declare namespace control {
 | 
					declare namespace control {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,3 +57,8 @@ namespace loops {
 | 
				
			|||||||
namespace light {
 | 
					namespace light {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//% color="#b0b0b0" advanced=true weight=5
 | 
				
			||||||
 | 
					namespace storage {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								libs/storage/_locales/storage-jsdoc-strings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								libs/storage/_locales/storage-jsdoc-strings.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "storage.Storage.append": "Append string data to a new or existing file.",
 | 
				
			||||||
 | 
					  "storage.Storage.appendBuffer": "Append a buffer to a new or existing file.",
 | 
				
			||||||
 | 
					  "storage.Storage.appendCSV": "Append a row of CSV data",
 | 
				
			||||||
 | 
					  "storage.Storage.appendCSV|param|data": "the data to append",
 | 
				
			||||||
 | 
					  "storage.Storage.appendCSV|param|filename": "the file name to append data, eg: \"data.txt\"",
 | 
				
			||||||
 | 
					  "storage.Storage.appendLine": "Appends a new line of data in the file",
 | 
				
			||||||
 | 
					  "storage.Storage.appendLine|param|data": "the data to append",
 | 
				
			||||||
 | 
					  "storage.Storage.appendLine|param|filename": "the file name to append data, eg: \"data.txt\"",
 | 
				
			||||||
 | 
					  "storage.Storage.append|param|data": "the data to append",
 | 
				
			||||||
 | 
					  "storage.Storage.append|param|filename": "the file name to append data, eg: \"data.txt\"",
 | 
				
			||||||
 | 
					  "storage.Storage.exists": "Tests if a file exists",
 | 
				
			||||||
 | 
					  "storage.Storage.exists|param|filename": "the file name to append data, eg: \"data.txt\"",
 | 
				
			||||||
 | 
					  "storage.Storage.limit": "Resizing the size of a file to stay under the limit",
 | 
				
			||||||
 | 
					  "storage.Storage.limit|param|filename": "name of the file to drop",
 | 
				
			||||||
 | 
					  "storage.Storage.limit|param|size": "maximum length",
 | 
				
			||||||
 | 
					  "storage.Storage.overwrite": "Overwrite file with string data.",
 | 
				
			||||||
 | 
					  "storage.Storage.overwriteWithBuffer": "Overwrite file with a buffer.",
 | 
				
			||||||
 | 
					  "storage.Storage.overwrite|param|data": "the data to append",
 | 
				
			||||||
 | 
					  "storage.Storage.overwrite|param|filename": "the file name to append data, eg: \"data.txt\"",
 | 
				
			||||||
 | 
					  "storage.Storage.read": "Read contents of file as a string.",
 | 
				
			||||||
 | 
					  "storage.Storage.readAsBuffer": "Read contents of file as a buffer.",
 | 
				
			||||||
 | 
					  "storage.Storage.remove": "Delete a file, or do nothing if it doesn't exist.",
 | 
				
			||||||
 | 
					  "storage.Storage.size": "Return the size of the file, or -1 if it doesn't exists.",
 | 
				
			||||||
 | 
					  "storage.temporary": "Temporary storage in memory, deleted when the device restarts."
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								libs/storage/_locales/storage-strings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								libs/storage/_locales/storage-strings.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "storage.Storage.appendCSV|block": "storage %source|%filename|append CSV %data",
 | 
				
			||||||
 | 
					  "storage.Storage.appendLine|block": "storage %source|%filename|append line %data",
 | 
				
			||||||
 | 
					  "storage.Storage.append|block": "storage %source|%filename|append %data",
 | 
				
			||||||
 | 
					  "storage.Storage.exists|block": "storage %source|%filename|exists",
 | 
				
			||||||
 | 
					  "storage.Storage.limit|block": "storage %source|limit %filename|to %size|bytes",
 | 
				
			||||||
 | 
					  "storage.Storage.overwrite|block": "storage %source|%filename|overwrite with|%data",
 | 
				
			||||||
 | 
					  "storage.Storage.read|block": "storage %source|read %filename|as string",
 | 
				
			||||||
 | 
					  "storage.Storage.remove|block": "storage %source|remove %filename",
 | 
				
			||||||
 | 
					  "storage.Storage.size|block": "storage %source|%filename|size",
 | 
				
			||||||
 | 
					  "storage.temporary|block": "temporary",
 | 
				
			||||||
 | 
					  "storage|block": "storage",
 | 
				
			||||||
 | 
					  "{id:category}Storage": "Storage"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								libs/storage/pxt.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								libs/storage/pxt.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "name": "storage",
 | 
				
			||||||
 | 
					    "description": "USB Pen-drive support and flash storage",
 | 
				
			||||||
 | 
					    "files": [
 | 
				
			||||||
 | 
					        "storage.cpp",
 | 
				
			||||||
 | 
					        "storage-core.ts",
 | 
				
			||||||
 | 
					        "storage.ts",
 | 
				
			||||||
 | 
					        "shims.d.ts"
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "public": true,
 | 
				
			||||||
 | 
					    "dependencies": {
 | 
				
			||||||
 | 
					        "core": "file:../core"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								libs/storage/shims.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								libs/storage/shims.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					// Auto-generated. Do not edit.
 | 
				
			||||||
 | 
					declare namespace storage {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Will be moved. */
 | 
				
			||||||
 | 
					    //% shim=storage::__stringToBuffer
 | 
				
			||||||
 | 
					    function __stringToBuffer(s: string): Buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Will be moved. */
 | 
				
			||||||
 | 
					    //% shim=storage::__bufferToString
 | 
				
			||||||
 | 
					    function __bufferToString(s: Buffer): string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Create named directory. */
 | 
				
			||||||
 | 
					    //% shim=storage::__mkdir
 | 
				
			||||||
 | 
					    function __mkdir(filename: string): void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Auto-generated. Do not edit. Really.
 | 
				
			||||||
							
								
								
									
										178
									
								
								libs/storage/storage-core.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								libs/storage/storage-core.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
				
			|||||||
 | 
					namespace storage {
 | 
				
			||||||
 | 
					    //% shim=storage::__unlink
 | 
				
			||||||
 | 
					    function __unlink(filename: string): void { }
 | 
				
			||||||
 | 
					    //% shim=storage::__truncate
 | 
				
			||||||
 | 
					    function __truncate(filename: string): void { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //% fixedInstances
 | 
				
			||||||
 | 
					    export class Storage {
 | 
				
			||||||
 | 
					        constructor() { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected mapFilename(filename: string) {
 | 
				
			||||||
 | 
					            return filename;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private getFile(filename: string): MMap {
 | 
				
			||||||
 | 
					            filename = this.mapFilename(filename)
 | 
				
			||||||
 | 
					            let r = control.mmap(filename, 0, 0)
 | 
				
			||||||
 | 
					            if (!r) {
 | 
				
			||||||
 | 
					                __mkdir(this.dirname(filename))
 | 
				
			||||||
 | 
					                __truncate(filename)
 | 
				
			||||||
 | 
					                r = control.mmap(filename, 0, 0)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (!r)
 | 
				
			||||||
 | 
					                control.panic(906)
 | 
				
			||||||
 | 
					            return r
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dirname(filename: string) {
 | 
				
			||||||
 | 
					            let last = 0
 | 
				
			||||||
 | 
					            for (let i = 0; i < filename.length; ++i)
 | 
				
			||||||
 | 
					                if (filename[i] == "/")
 | 
				
			||||||
 | 
					                    last = i
 | 
				
			||||||
 | 
					            return filename.substr(0, last)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         *  Append string data to a new or existing file. 
 | 
				
			||||||
 | 
					         * @param filename the file name to append data, eg: "data.txt"
 | 
				
			||||||
 | 
					         * @param data the data to append
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        //% blockId=storageAppend block="storage %source|%filename|append %data"
 | 
				
			||||||
 | 
					        append(filename: string, data: string): void {
 | 
				
			||||||
 | 
					            this.appendBuffer(filename, __stringToBuffer(data))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Appends a new line of data in the file
 | 
				
			||||||
 | 
					         * @param filename the file name to append data, eg: "data.txt"
 | 
				
			||||||
 | 
					         * @param data the data to append
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        //% blockId=storageAppendLine block="storage %source|%filename|append line %data"
 | 
				
			||||||
 | 
					        appendLine(filename: string, data: string): void {
 | 
				
			||||||
 | 
					            this.append(filename, data + "\r\n");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /** Append a buffer to a new or existing file. */
 | 
				
			||||||
 | 
					        appendBuffer(filename: string, data: Buffer): void {
 | 
				
			||||||
 | 
					            let f = this.getFile(filename);
 | 
				
			||||||
 | 
					            f.lseek(0, SeekWhence.End)
 | 
				
			||||||
 | 
					            f.write(data)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Append a row of CSV data
 | 
				
			||||||
 | 
					         * @param filename the file name to append data, eg: "data.txt"
 | 
				
			||||||
 | 
					         * @param data the data to append
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        //% blockId=storageAppendCSV block="storage %source|%filename|append CSV %data"
 | 
				
			||||||
 | 
					        appendCSV(filename: string, data: number[]) {
 | 
				
			||||||
 | 
					            let s = ""
 | 
				
			||||||
 | 
					            for (const d of data) {
 | 
				
			||||||
 | 
					                if (s) s += "\t"
 | 
				
			||||||
 | 
					                s = s + d;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            s += "\r\n"
 | 
				
			||||||
 | 
					            this.append(filename, s)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /** Overwrite file with string data.
 | 
				
			||||||
 | 
					         * @param filename the file name to append data, eg: "data.txt"
 | 
				
			||||||
 | 
					         * @param data the data to append
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        //% blockId=storageOverwrite block="storage %source|%filename|overwrite with|%data"
 | 
				
			||||||
 | 
					        overwrite(filename: string, data: string): void {
 | 
				
			||||||
 | 
					            this.overwriteWithBuffer(filename, __stringToBuffer(data))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /** Overwrite file with a buffer. */
 | 
				
			||||||
 | 
					        overwriteWithBuffer(filename: string, data: Buffer): void {
 | 
				
			||||||
 | 
					            __truncate(this.mapFilename(filename))
 | 
				
			||||||
 | 
					            this.appendBuffer(filename, data)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /** Tests if a file exists
 | 
				
			||||||
 | 
					         * @param filename the file name to append data, eg: "data.txt"
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        //% blockId=storageExists block="storage %source|%filename|exists"
 | 
				
			||||||
 | 
					        exists(filename: string): boolean {
 | 
				
			||||||
 | 
					            return !!control.mmap(this.mapFilename(filename), 0, 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /** Delete a file, or do nothing if it doesn't exist. */
 | 
				
			||||||
 | 
					        //% blockId=storageRemove block="storage %source|remove %filename"
 | 
				
			||||||
 | 
					        remove(filename: string): void {
 | 
				
			||||||
 | 
					            __unlink(this.mapFilename(filename))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /** Return the size of the file, or -1 if it doesn't exists. */
 | 
				
			||||||
 | 
					        //% blockId=storageSize block="storage %source|%filename|size"
 | 
				
			||||||
 | 
					        size(filename: string): int32 {
 | 
				
			||||||
 | 
					            let f = control.mmap(this.mapFilename(filename), 0, 0)
 | 
				
			||||||
 | 
					            if (!f) return -1;
 | 
				
			||||||
 | 
					            return f.lseek(0, SeekWhence.End)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /** Read contents of file as a string. */
 | 
				
			||||||
 | 
					        //% blockId=storageRead block="storage %source|read %filename|as string"
 | 
				
			||||||
 | 
					        read(filename: string): string {
 | 
				
			||||||
 | 
					            return __bufferToString(this.readAsBuffer(filename))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /** Read contents of file as a buffer. */
 | 
				
			||||||
 | 
					        //%
 | 
				
			||||||
 | 
					        readAsBuffer(filename: string): Buffer {
 | 
				
			||||||
 | 
					            let f = this.getFile(filename)
 | 
				
			||||||
 | 
					            let sz = f.lseek(0, SeekWhence.End)
 | 
				
			||||||
 | 
					            let b = output.createBuffer(sz)
 | 
				
			||||||
 | 
					            f.lseek(0, SeekWhence.Set);
 | 
				
			||||||
 | 
					            f.read(b)
 | 
				
			||||||
 | 
					            return b
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Resizing the size of a file to stay under the limit
 | 
				
			||||||
 | 
					         * @param filename name of the file to drop
 | 
				
			||||||
 | 
					         * @param size maximum length
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        //% blockId=storageLimit block="storage %source|limit %filename|to %size|bytes"
 | 
				
			||||||
 | 
					        limit(filename: string, size: number) {
 | 
				
			||||||
 | 
					            if (!this.exists(filename) || size < 0) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const sz = storage.temporary.size(filename);
 | 
				
			||||||
 | 
					            if (sz > size) {
 | 
				
			||||||
 | 
					                let buf = storage.temporary.readAsBuffer(filename)
 | 
				
			||||||
 | 
					                buf = buf.slice(buf.length / 2);
 | 
				
			||||||
 | 
					                storage.temporary.overwriteWithBuffer(filename, buf);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class TemporaryStorage extends Storage {
 | 
				
			||||||
 | 
					        constructor() {
 | 
				
			||||||
 | 
					            super();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected mapFilename(filename: string) {
 | 
				
			||||||
 | 
					            if (filename[0] == '/') filename = filename.substr(1);
 | 
				
			||||||
 | 
					            return '/tmp/logs/' + filename;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Temporary storage in memory, deleted when the device restarts.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    //% whenUsed fixedInstance block="temporary"
 | 
				
			||||||
 | 
					    export const temporary: Storage = new TemporaryStorage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class PermanentStorage extends Storage {
 | 
				
			||||||
 | 
					        constructor() {
 | 
				
			||||||
 | 
					            super()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected mapFilename(filename: string) {
 | 
				
			||||||
 | 
					            if (filename[0] == '/') return filename;
 | 
				
			||||||
 | 
					            return '/' + filename;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										44
									
								
								libs/storage/storage.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								libs/storage/storage.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					#include "pxt.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace storage {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Will be moved. */
 | 
				
			||||||
 | 
					//%
 | 
				
			||||||
 | 
					Buffer __stringToBuffer(String s) {
 | 
				
			||||||
 | 
					    return mkBuffer((uint8_t *)s->data, s->length);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Will be moved. */
 | 
				
			||||||
 | 
					//%
 | 
				
			||||||
 | 
					String __bufferToString(Buffer s) {
 | 
				
			||||||
 | 
					    return mkString((char*)s->data, s->length);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//%
 | 
				
			||||||
 | 
					void __init() {
 | 
				
			||||||
 | 
					    // do nothing
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//%
 | 
				
			||||||
 | 
					void __unlink(String filename) {
 | 
				
			||||||
 | 
					    ::unlink(filename->data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//%
 | 
				
			||||||
 | 
					void __truncate(String filename) {
 | 
				
			||||||
 | 
					    int fd = open(filename->data, O_CREAT | O_TRUNC | O_WRONLY, 0777);
 | 
				
			||||||
 | 
					    close(fd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Create named directory. */
 | 
				
			||||||
 | 
					//%
 | 
				
			||||||
 | 
					void __mkdir(String filename) {
 | 
				
			||||||
 | 
					    ::mkdir(filename->data, 0777);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace storage
 | 
				
			||||||
							
								
								
									
										11
									
								
								libs/storage/storage.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								libs/storage/storage.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					namespace storage {
 | 
				
			||||||
 | 
					    // automatically send console output to temp storage
 | 
				
			||||||
 | 
					    storage.temporary.remove("console.txt");
 | 
				
			||||||
 | 
					    console.addListener(function(line) {
 | 
				
			||||||
 | 
					        const fn = "console.txt";
 | 
				
			||||||
 | 
					        const mxs = 65536;
 | 
				
			||||||
 | 
					        const t = control.millis();
 | 
				
			||||||
 | 
					        storage.temporary.appendLine(fn, `${t}> ${line}`);
 | 
				
			||||||
 | 
					        storage.temporary.limit(fn, 65536);
 | 
				
			||||||
 | 
					    })    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -16,6 +16,7 @@
 | 
				
			|||||||
        "libs/infrared-sensor",
 | 
					        "libs/infrared-sensor",
 | 
				
			||||||
        "libs/gyro-sensor",
 | 
					        "libs/gyro-sensor",
 | 
				
			||||||
        "libs/chassis",
 | 
					        "libs/chassis",
 | 
				
			||||||
 | 
					        "libs/storage",
 | 
				
			||||||
        "libs/ev3",
 | 
					        "libs/ev3",
 | 
				
			||||||
        "libs/tests",
 | 
					        "libs/tests",
 | 
				
			||||||
        "libs/behaviors"
 | 
					        "libs/behaviors"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ namespace pxsim.MMapMethods {
 | 
				
			|||||||
        read?: (d: Buffer) => number;
 | 
					        read?: (d: Buffer) => number;
 | 
				
			||||||
        write?: (d: Buffer) => number;
 | 
					        write?: (d: Buffer) => number;
 | 
				
			||||||
        ioctl?: (id: number, d: Buffer) => number;
 | 
					        ioctl?: (id: number, d: Buffer) => number;
 | 
				
			||||||
 | 
					        lseek?: (offset: number, whence: number) => number;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    import BM = pxsim.BufferMethods
 | 
					    import BM = pxsim.BufferMethods
 | 
				
			||||||
@@ -23,6 +24,7 @@ namespace pxsim.MMapMethods {
 | 
				
			|||||||
            if (!impl.read) impl.read = () => 0
 | 
					            if (!impl.read) impl.read = () => 0
 | 
				
			||||||
            if (!impl.write) impl.write = () => 0
 | 
					            if (!impl.write) impl.write = () => 0
 | 
				
			||||||
            if (!impl.ioctl) impl.ioctl = () => -1
 | 
					            if (!impl.ioctl) impl.ioctl = () => -1
 | 
				
			||||||
 | 
					            if (!impl.lseek) impl.lseek = (offset, whence) => -1
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        destroy() {
 | 
					        destroy() {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -68,6 +70,10 @@ namespace pxsim.MMapMethods {
 | 
				
			|||||||
    export function read(m: MMap, data: Buffer): number {
 | 
					    export function read(m: MMap, data: Buffer): number {
 | 
				
			||||||
        return m.impl.read(data)
 | 
					        return m.impl.read(data)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    export function lseek(m: MMap, offset: number, whence: number): number {
 | 
				
			||||||
 | 
					        return m.impl.lseek(offset, whence);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace pxsim.control {
 | 
					namespace pxsim.control {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								sim/state/storage.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								sim/state/storage.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					namespace pxsim.storage {
 | 
				
			||||||
 | 
					    export function __stringToBuffer(s: string): RefBuffer {
 | 
				
			||||||
 | 
					        // TODO
 | 
				
			||||||
 | 
					        return new RefBuffer(new Uint8Array([]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    export function __bufferToString(b: RefBuffer): string {
 | 
				
			||||||
 | 
					        // TODO
 | 
				
			||||||
 | 
					        return "";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    export function __mkdir(fn: string) {
 | 
				
			||||||
 | 
					        // TODO
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    export function __unlink(filename: string): void { 
 | 
				
			||||||
 | 
					        // TODO
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    export function __truncate(filename: string): void { 
 | 
				
			||||||
 | 
					        // TODO
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user