void jsvStringIteratorNew(JsvStringIterator *it, JsVar *str, size_t startIdx) { assert(jsvHasCharacterData(str)); it->var = jsvLockAgain(str); it->varIndex = 0; it->charsInVar = jsvGetCharactersInVar(str); it->charIdx = startIdx; if (jsvIsFlatString(str)) { it->ptr = jsvGetFlatStringPointer(it->var); } else if (jsvIsNativeString(str)) { it->ptr = (char*)it->var->varData.nativeStr.ptr; } else{ it->ptr = &it->var->varData.str[0]; } while (it->charIdx>0 && it->charIdx >= it->charsInVar) { it->charIdx -= it->charsInVar; it->varIndex += it->charsInVar; if (it->var) { if (jsvGetLastChild(it->var)) { JsVar *next = jsvLock(jsvGetLastChild(it->var)); jsvUnLock(it->var); it->var = next; it->ptr = &next->varData.str[0]; it->charsInVar = jsvGetCharactersInVar(it->var); } else { jsvUnLock(it->var); it->var = 0; it->ptr = 0; it->charsInVar = 0; it->varIndex = startIdx - it->charIdx; return; // at end of string - get out of loop } } } }
JsVar *jslNewStringFromLexer(JslCharPos *charFrom, size_t charTo) { // Original method - just copy it verbatim size_t maxLength = charTo + 1 - jsvStringIteratorGetIndex(&charFrom->it); assert(maxLength>0); // will fail if 0 // Try and create a flat string first JsVar *var = 0; if (maxLength > JSV_FLAT_STRING_BREAK_EVEN) { var = jsvNewFlatStringOfLength((unsigned int)maxLength); if (var) { // Flat string char *flatPtr = jsvGetFlatStringPointer(var); *(flatPtr++) = charFrom->currCh; JsvStringIterator it = jsvStringIteratorClone(&charFrom->it); while (jsvStringIteratorHasChar(&it) && (--maxLength>0)) { *(flatPtr++) = jsvStringIteratorGetChar(&it); jsvStringIteratorNext(&it); } jsvStringIteratorFree(&it); return var; } } // Non-flat string... var = jsvNewFromEmptyString(); if (!var) { // out of memory return 0; } //jsvAppendStringVar(var, lex->sourceVar, charFrom->it->index, (int)(charTo-charFrom)); JsVar *block = jsvLockAgain(var); block->varData.str[0] = charFrom->currCh; size_t blockChars = 1; size_t l = maxLength; // now start appending JsvStringIterator it = jsvStringIteratorClone(&charFrom->it); while (jsvStringIteratorHasChar(&it) && (--maxLength>0)) { char ch = jsvStringIteratorGetChar(&it); if (blockChars >= jsvGetMaxCharactersInVar(block)) { jsvSetCharactersInVar(block, blockChars); JsVar *next = jsvNewWithFlags(JSV_STRING_EXT_0); if (!next) break; // out of memory // we don't ref, because StringExts are never reffed as they only have one owner (and ALWAYS have an owner) jsvSetLastChild(block, jsvGetRef(next)); jsvUnLock(block); block = next; blockChars=0; // it's new, so empty } block->varData.str[blockChars++] = ch; jsvStringIteratorNext(&it); } jsvSetCharactersInVar(block, blockChars); jsvUnLock(block); // Just make sure we only assert if there's a bug here. If we just ran out of memory or at end of string it's ok assert((l == jsvGetStringLength(var)) || (jsErrorFlags&JSERR_MEMORY) || !jsvStringIteratorHasChar(&it)); jsvStringIteratorFree(&it); return var; }
static bool fileGetFromVar(JsFile *file, JsVar *parent) { bool ret = false; JsVar *fHandle = jsvObjectGetChild(parent, JS_FS_DATA_NAME, 0); if (fHandle && jsvIsFlatString(fHandle)) { file->data = (JsFileData*)jsvGetFlatStringPointer(fHandle); file->fileVar = parent; if(file->data->state == FS_OPEN) {// return false if the file has been closed. ret = true; } } jsvUnLock(fHandle); return ret; }
static bool allocateJsFile(JsFile* file,FileMode mode, FileType type) { JsVar *parent = jspNewObject(0, "File"); if (!parent) return false; // low memory JsVar *data = jsvNewFlatStringOfLength(sizeof(JsFileData)); if (!data) { // out of memory for flat string jsvUnLock(parent); return false; } file->data = (JsFileData*)jsvGetFlatStringPointer(data); jsvObjectSetChildAndUnLock(parent, JS_FS_DATA_NAME, data); file->fileVar = parent; assert(file->data); file->data->mode = mode; file->data->type = type; file->data->state = FS_NONE; return true; }
/*JSON{ "type" : "method", "class" : "File", "name" : "read", "generate" : "jswrap_file_read", "params" : [ ["length","int32","is an integer specifying the number of bytes to read."] ], "return" : ["JsVar","A string containing the characters that were read"] } Read data in a file in byte size chunks */ JsVar *jswrap_file_read(JsVar* parent, int length) { if (length<0) length=0; JsVar *buffer = 0; JsvStringIterator it; FRESULT res = 0; size_t bytesRead = 0; if (jsfsInit()) { JsFile file; if (fileGetFromVar(&file, parent)) { if(file.data->mode == FM_READ || file.data->mode == FM_READ_WRITE) { size_t actual = 0; #ifndef LINUX // if we're able to load this into a flat string, do it! size_t len = f_size(&file.data->handle)-f_tell(&file.data->handle); if ( len == 0 ) { // file all read return 0; // if called from a pipe signal end callback } if (len > (size_t)length) len = (size_t)length; buffer = jsvNewFlatStringOfLength(len); if (buffer) { res = f_read(&file.data->handle, jsvGetFlatStringPointer(buffer), len, &actual); if (res) jsfsReportError("Unable to read file", res); return buffer; } #endif char buf[32]; while (bytesRead < (size_t)length) { size_t requested = (size_t)length - bytesRead; if (requested > sizeof( buf )) requested = sizeof( buf ); actual = 0; #ifndef LINUX res = f_read(&file.data->handle, buf, requested, &actual); if(res) break; #else actual = fread(buf, 1, requested, file.data->handle); #endif if (actual>0) { if (!buffer) { buffer = jsvNewFromEmptyString(); if (!buffer) return 0; // out of memory jsvStringIteratorNew(&it, buffer, 0); } size_t i; for (i=0;i<actual;i++) jsvStringIteratorAppend(&it, buf[i]); } bytesRead += actual; if(actual != requested) break; } } } } if (res) jsfsReportError("Unable to read file", res); if (buffer) jsvStringIteratorFree(&it); return buffer; }