/** * @brief * Advance the input cursor by one character. * @remark * If the file is was not opened, end of the input was reached or an error was encountered, * before a call to this method, the call immediatly returns, not observably modifying the * state of this object or the file. */ virtual void advance() { // (1) If an error or the end of the input was encountered ... if (_current == Traits::error() || _current == Traits::endOfInput()) { // ... do nothing. return; } // (2) If the backing VFS file is not opened ... if (!_file) { // ... raise an error. _current = Traits::error(); return; } // (3) Otherwise: Read a single Byte. uint8_t byte; size_t size = vfs_read(&byte, 1, 1, _file); if (1 != size) { if (vfs_error(_file)) { _current = Traits::error(); return; } else if (vfs_eof(_file)) { _current = Traits::endOfInput(); return; } else { ostringstream message; message << __FILE__ << ":" << __LINE__ << ": " << "inconsistent state of file object of file `" << this->getFileName() << "`"; throw runtime_error(message.str()); } } // (4) Verify that it is a Byte the represents the starting Byte of a UTF-8 character sequence of length 1. if (byte > 0x7F) { _current = Traits::error(); return; } // (5) Verify that it is not the zero terminator. if ('\0' == byte) { _current = Traits::error(); return; } // (6) Propage the Byte to an extended character and store it. _current = (typename Traits::ExtendedType)byte; }
void vfs_mount(const char* dir) { if (dir == NULL) { vfs_error("Mount directory is NULL\n"); return; } char path[VFS_MOUNT_PATH_MAX]; strcpy(path, dir); size_t pathlen = strlen(path); if (pathlen == 0) { vfs_error("Mount directory is of length 0\n"); return; } if (path[pathlen - 1] == '\\' || path[pathlen - 1] == '/') { path[pathlen - 1] = '\0'; } char** filenames = stb_readdir_recursive(path, NULL); if (filenames == NULL) { vfs_error("Could not read directory: %s\n", path); return; } int num_new_files = stb_arr_len(filenames); for (int i = 0; i < num_new_files; i++) { struct vfs_file new_file; strcpy(new_file.name, filenames[i]); strcpy(new_file.simplename, filenames[i] + strlen(path) + 1); int replaced = 0; for (int j = 0; j < vfs_global->file_count; j++) { if (strcmp(vfs_global->file_table[j].simplename, new_file.simplename) == 0) { stb_fclose(vfs_global->file_table[j].file, 0); free(vfs_global->file_table[j].data); strcpy(vfs_global->file_table[j].name, new_file.name); vfs_global->file_table[j].file = stb_fopen(vfs_global->file_table[j].name, "rb"); vfs_global->file_table[j].lastChange = stb_ftimestamp(vfs_global->file_table[j].name); vfs_global->file_table[j].size = stb_filelen(vfs_global->file_table[j].file); vfs_global->file_table[j].data = malloc(vfs_global->file_table[j].size); fread(vfs_global->file_table[j].data, 1, vfs_global->file_table[j].size, vfs_global->file_table[j].file); stb_fclose(vfs_global->file_table[i].file, 0); replaced = 1; break; } } if (!replaced) { new_file.read_callbacks = 0; new_file.file = stb_fopen(new_file.name, "rb"); new_file.lastChange = stb_ftimestamp(new_file.name); new_file.size = stb_filelen(new_file.file); new_file.data = malloc(new_file.size); fread(new_file.data, 1, new_file.size, new_file.file); stb_fclose(new_file.file, 0); vfs_global->file_table[vfs_global->file_count] = new_file; vfs_global->file_count++; } } }