Exemple #1
0
/*JSON{
  "type" : "staticmethod",
  "class" : "E",
  "name" : "openFile",
  "generate" : "jswrap_E_openFile",
  "params" : [
    ["path","JsVar","the path to the file to open."],
    ["mode","JsVar","The mode to use when opening the file. Valid values for mode are 'r' for read, 'w' for write new, 'w+' for write existing, and 'a' for append. If not specified, the default is 'r'."]
  ],
  "return" : ["JsVar","A File object"],
  "return_object" : "File"
}
Open a file
*/
JsVar *jswrap_E_openFile(JsVar* path, JsVar* mode) {
  FRESULT res = FR_INVALID_NAME;
  JsFile file;
  file.data = 0;
  file.fileVar = 0;
  FileMode fMode = FM_NONE;
  if (jsfsInit()) {
    JsVar *arr = fsGetArray(true);
    if (!arr) return 0; // out of memory

    char pathStr[JS_DIR_BUF_SIZE] = "";
    char modeStr[3] = "r";
    if (!jsvIsUndefined(path)) {
      if (!jsfsGetPathString(pathStr, path)) {
        jsvUnLock(arr);
        return 0;
      }

      if (!jsvIsUndefined(mode))
        jsvGetString(mode, modeStr, 3);

#ifndef LINUX
      BYTE ff_mode = 0;
      bool append = false;
#endif

      if(strcmp(modeStr,"r") == 0) {
        fMode = FM_READ;
#ifndef LINUX
        ff_mode = FA_READ | FA_OPEN_EXISTING;
#endif
      } else if(strcmp(modeStr,"a") == 0) {
        fMode = FM_WRITE;
#ifndef LINUX
        ff_mode = FA_WRITE | FA_OPEN_ALWAYS;
        append = true;
#endif
      } else if(strcmp(modeStr,"w") == 0) {
        fMode = FM_WRITE;
#ifndef LINUX
        ff_mode = FA_WRITE | FA_CREATE_ALWAYS;
#endif
      } else if(strcmp(modeStr,"w+") == 0) {
        fMode = FM_READ_WRITE;
#ifndef LINUX
        ff_mode = FA_WRITE | FA_OPEN_ALWAYS;
#endif
      }
      if(fMode != FM_NONE && allocateJsFile(&file, fMode, FT_FILE)) {
#ifndef LINUX
        if ((res=f_open(&file.data->handle, pathStr, ff_mode)) == FR_OK) {
          if (append) f_lseek(&file.data->handle, file.data->handle.fsize); // move to end of file
#else
        file.data->handle = fopen(pathStr, modeStr);
        if (file.data->handle) {
          res=FR_OK;
#endif
          file.data->state = FS_OPEN;
          // add to list of open files
          jsvArrayPush(arr, file.fileVar);
        } else {
          // File open failed
          jsvUnLock(file.fileVar);
          file.fileVar = 0;
        }

        if(res != FR_OK)
          jsfsReportError("Could not open file", res);

      }
    } else {
      jsExceptionHere(JSET_ERROR,"Path is undefined");
    }

    jsvUnLock(arr);
  }


  return file.fileVar;
}

/*JSON{
  "type" : "method",
  "class" : "File",
  "name" : "close",
  "generate_full" : "jswrap_file_close(parent)"
}
Close an open file.
*/
void jswrap_file_close(JsVar* parent) {
  if (jsfsInit()) {
    JsFile file;
    if (fileGetFromVar(&file, parent) && file.data->state == FS_OPEN) {
#ifndef LINUX
      f_close(&file.data->handle);
#else
      fclose(file.data->handle);
      file.data->handle = 0;
#endif
      file.data->state = FS_CLOSED;
      // TODO: could try and free the memory used by file.data ?

      JsVar *arr = fsGetArray(false);
      if (arr) {
        JsVar *idx = jsvGetIndexOf(arr, file.fileVar, true);
        if (idx) {
          jsvRemoveChild(arr, idx);
          jsvUnLock(idx);
        }
        jsvUnLock(arr);
      }
    }
  }
}

/*JSON{
  "type" : "method",
  "class" : "File",
  "name" : "write",
  "generate" : "jswrap_file_write",
  "params" : [
    ["buffer","JsVar","A string containing the bytes to write"]
  ],
  "return" : ["int32","the number of bytes written"]
}
Write data to a file.

**Note:** By default this function flushes all changes to the
SD card, which makes it slow (but also safe!). You can use
`E.setFlags({unsyncFiles:1})` to disable this behaviour and
really speed up writes - but then you must be sure to close
all files you are writing before power is lost or you will
cause damage to your SD card's filesystem.
*/
size_t jswrap_file_write(JsVar* parent, JsVar* buffer) {
  FRESULT res = 0;
  size_t bytesWritten = 0;
  if (jsfsInit()) {
    JsFile file;
    if (fileGetFromVar(&file, parent)) {
      if(file.data->mode == FM_WRITE || file.data->mode == FM_READ_WRITE) {
        JsvIterator it;
        jsvIteratorNew(&it, buffer, JSIF_EVERY_ARRAY_ELEMENT);
        char buf[32];

        while (jsvIteratorHasElement(&it)) {
          // pull in a buffer's worth of data
          size_t n = 0;
          while (jsvIteratorHasElement(&it) && n<sizeof(buf)) {
            buf[n++] = (char)jsvIteratorGetIntegerValue(&it);
            jsvIteratorNext(&it);
          }
          // write it out
          size_t written = 0;
#ifndef LINUX
          res = f_write(&file.data->handle, &buf, n, &written);
#else
          written = fwrite(&buf, 1, n, file.data->handle);
#endif
          bytesWritten += written;
          if(written == 0)
            res = FR_DISK_ERR;
          if (res) break;
        }
        jsvIteratorFree(&it);
        // finally, sync - just in case there's a reset or something
        if (!jsfGetFlag(JSF_UNSYNC_FILES)) {
#ifndef LINUX
          f_sync(&file.data->handle);
#else
          fflush(file.data->handle);
#endif
        }
      }
    }
  }

  if (res) {
    jsfsReportError("Unable to write file", res);
  }
  return bytesWritten;
}
/*JSON{
  "type" : "staticmethod",
  "class" : "E",
  "name" : "openFile",
  "generate" : "jswrap_E_openFile",
  "params" : [
    ["path","JsVar","the path to the file to open."],
    ["mode","JsVar","The mode to use when opening the file. Valid values for mode are 'r' for read, 'w' for write new, 'w+' for write existing, and 'a' for append. If not specified, the default is 'r'."]
  ],
  "return" : ["JsVar","A File object"],
  "return_object" : "File"
}
Open a file
*/
JsVar *jswrap_E_openFile(JsVar* path, JsVar* mode) {
    FRESULT res = FR_INVALID_NAME;
    JsFile file;
    file.fileVar = 0;
    FileMode fMode = FM_NONE;
    if (jsfsInit()) {
        JsVar *arr = fsGetArray(true);
        if (!arr) return 0; // out of memory

        char pathStr[JS_DIR_BUF_SIZE] = "";
        char modeStr[3] = "r";
        if (!jsvIsUndefined(path)) {
            if (!jsfsGetPathString(pathStr, path)) {
                jsvUnLock(arr);
                return 0;
            }

            if (!jsvIsUndefined(mode))
                jsvGetString(mode, modeStr, 3);

#ifndef LINUX
            BYTE ff_mode = 0;
            bool append = false;
#endif

            if(strcmp(modeStr,"r") == 0) {
                fMode = FM_READ;
#ifndef LINUX
                ff_mode = FA_READ | FA_OPEN_EXISTING;
#endif
            } else if(strcmp(modeStr,"a") == 0) {
                fMode = FM_WRITE;
#ifndef LINUX
                ff_mode = FA_WRITE | FA_OPEN_ALWAYS;
                append = true;
#endif
            } else if(strcmp(modeStr,"w") == 0) {
                fMode = FM_WRITE;
#ifndef LINUX
                ff_mode = FA_WRITE | FA_CREATE_ALWAYS;
#endif
            } else if(strcmp(modeStr,"w+") == 0) {
                fMode = FM_READ_WRITE;
#ifndef LINUX
                ff_mode = FA_WRITE | FA_OPEN_ALWAYS;
#endif
            }
            if(fMode != FM_NONE && allocateJsFile(&file, fMode, FT_FILE)) {
#ifndef LINUX
                if ((res=f_open(&file.data.handle, pathStr, ff_mode)) == FR_OK) {
                    if (append) f_lseek(&file.data.handle, file.data.handle.fsize); // move to end of file
#else
                file.data.handle = fopen(pathStr, modeStr);
                if (file.data.handle) {
                    res=FR_OK;
#endif
                    file.data.state = FS_OPEN;
                    fileSetVar(&file);
                    // add to list of open files
                    jsvArrayPush(arr, file.fileVar);
                } else {
                    // File open failed
                    jsvUnLock(file.fileVar);
                    file.fileVar = 0;
                }

                if(res != FR_OK)
                    jsfsReportError("Could not open file", res);

            }
        } else {
            jsError("Path is undefined");
        }

        jsvUnLock(arr);
    }


    return file.fileVar;
}

/*JSON{
  "type" : "method",
  "class" : "File",
  "name" : "close",
  "generate_full" : "jswrap_file_close(parent)"
}
Close an open file.
*/
void jswrap_file_close(JsVar* parent) {
    if (jsfsInit()) {
        JsFile file;
        if (fileGetFromVar(&file, parent) && file.data.state == FS_OPEN) {
#ifndef LINUX
            f_close(&file.data.handle);
#else
            fclose(file.data.handle);
            file.data.handle = 0;
#endif
            file.data.state = FS_CLOSED;
            fileSetVar(&file);
            // TODO: could try and free the memory used by file.data ?

            JsVar *arr = fsGetArray(false);
            if (arr) {
                JsVar *idx = jsvGetArrayIndexOf(arr, file.fileVar, true);
                if (idx) {
                    jsvRemoveChild(arr, idx);
                    jsvUnLock(idx);
                }
                jsvUnLock(arr);
            }
        }
    }
}

/*JSON{
  "type" : "method",
  "class" : "File",
  "name" : "write",
  "generate" : "jswrap_file_write",
  "params" : [
    ["buffer","JsVar","A string containing the bytes to write"]
  ],
  "return" : ["int32","the number of bytes written"]
}
write data to a file
*/
size_t jswrap_file_write(JsVar* parent, JsVar* buffer) {
    FRESULT res = 0;
    size_t bytesWritten = 0;
    if (jsfsInit()) {
        JsFile file;
        if (fileGetFromVar(&file, parent)) {
            if(file.data.mode == FM_WRITE || file.data.mode == FM_READ_WRITE) {
                JsvIterator it;
                jsvIteratorNew(&it, buffer);
                char buf[32];

                while (jsvIteratorHasElement(&it)) {
                    // pull in a buffer's worth of data
                    size_t n = 0;
                    while (jsvIteratorHasElement(&it) && n<sizeof(buf)) {
                        buf[n++] = (char)jsvIteratorGetIntegerValue(&it);
                        jsvIteratorNext(&it);
                    }
                    // write it out
                    size_t written = 0;
#ifndef LINUX
                    res = f_write(&file.data.handle, &buf, n, &written);
#else
                    written = fwrite(&buf, 1, n, file.data.handle);
#endif
                    bytesWritten += written;
                    if(written == 0)
                        res = FR_DISK_ERR;
                    if (res) break;
                }
                jsvIteratorFree(&it);
                // finally, sync - just in case there's a reset or something
#ifndef LINUX
                f_sync(&file.data.handle);
#else
                fflush(file.data.handle);
#endif
            }

            fileSetVar(&file);
        }
    }

    if (res) {
        jsfsReportError("Unable to write file", res);
    }
    return bytesWritten;
}