#include #include #include #include #include CFile::CFile() { iFd = -1; mem_file = NULL; filesize = 0; pos = 0; } CFile::CFile(const std::string &filepath, eOpenTypes mode) { iFd = -1; this->open(filepath, mode); } CFile::CFile(const uint8_t *mem, int32_t size) { iFd = -1; this->open(mem, size); } CFile::~CFile() { this->close(); } int32_t CFile::open(const std::string &filepath, eOpenTypes mode) { this->close(); int32_t openMode = 0; // This depend on the devoptab implementation. // see https://github.com/devkitPro/wut/blob/master/libraries/wutdevoptab/devoptab_fs_open.c#L21 fpr reference switch (mode) { default: case ReadOnly: // file must exist openMode = O_RDONLY; break; case WriteOnly: // file will be created / zerod openMode = O_TRUNC | O_CREAT | O_WRONLY; break; case ReadWrite: // file must exist openMode = O_RDWR; break; case Append: // append to file, file will be created if missing. write only openMode = O_CREAT | O_APPEND | O_WRONLY; break; } //! Using fopen works only on the first launch as expected //! on the second launch it causes issues because we don't overwrite //! the .data sections which is needed for a normal application to re-init //! this will be added with launching as RPX iFd = ::open(filepath.c_str(), openMode); if (iFd < 0) return iFd; filesize = ::lseek(iFd, 0, SEEK_END); ::lseek(iFd, 0, SEEK_SET); return 0; } int32_t CFile::open(const uint8_t *mem, int32_t size) { this->close(); mem_file = mem; filesize = size; return 0; } void CFile::close() { if (iFd >= 0) ::close(iFd); iFd = -1; mem_file = NULL; filesize = 0; pos = 0; } int32_t CFile::read(uint8_t *ptr, size_t size) { if (iFd >= 0) { int32_t ret = ::read(iFd, ptr, size); if (ret > 0) pos += ret; return ret; } int32_t readsize = size; if (readsize > (int64_t) (filesize - pos)) readsize = filesize - pos; if (readsize <= 0) return readsize; if (mem_file != NULL) { memcpy(ptr, mem_file + pos, readsize); pos += readsize; return readsize; } return -1; } int32_t CFile::write(const uint8_t *ptr, size_t size) { if (iFd >= 0) { size_t done = 0; while (done < size) { int32_t ret = ::write(iFd, ptr, size - done); if (ret <= 0) return ret; ptr += ret; done += ret; pos += ret; } return done; } return -1; } int32_t CFile::seek(long int offset, int32_t origin) { int32_t ret = 0; int64_t newPos = pos; if (origin == SEEK_SET) { newPos = offset; } else if (origin == SEEK_CUR) { newPos += offset; } else if (origin == SEEK_END) { newPos = filesize + offset; } if (newPos < 0) { pos = 0; } else { pos = newPos; } if (iFd >= 0) ret = ::lseek(iFd, pos, SEEK_SET); if (mem_file != NULL) { if (pos > filesize) { pos = filesize; } } return ret; } int32_t CFile::fwrite(const char *format, ...) { char tmp[512]; tmp[0] = 0; int32_t result = -1; va_list va; va_start(va, format); if ((vsprintf(tmp, format, va) >= 0)) { result = this->write((uint8_t *) tmp, strlen(tmp)); } va_end(va); return result; }