diff --git a/src/ox/clargs/CMakeLists.txt b/src/ox/clargs/CMakeLists.txt index 172c773ae..a096079cc 100644 --- a/src/ox/clargs/CMakeLists.txt +++ b/src/ox/clargs/CMakeLists.txt @@ -5,6 +5,13 @@ add_library( clargs.cpp ) +set_property( + TARGET + OxClArgs + PROPERTY + POSITION_INDEPENDENT_CODE ON +) + install( FILES clargs.hpp diff --git a/src/ox/fs/CMakeLists.txt b/src/ox/fs/CMakeLists.txt index c7cd44c28..e318f0581 100644 --- a/src/ox/fs/CMakeLists.txt +++ b/src/ox/fs/CMakeLists.txt @@ -3,6 +3,14 @@ cmake_minimum_required(VERSION 2.8) add_library( OxFS filesystem.cpp + pathiterator.cpp +) + +set_property( + TARGET + OxFS + PROPERTY + POSITION_INDEPENDENT_CODE ON ) if(OX_BUILD_EXEC STREQUAL "ON") @@ -19,6 +27,7 @@ install( filestore.hpp filesystem.hpp inodemgr.hpp + pathiterator.hpp DESTINATION include/ox/fs ) diff --git a/src/ox/fs/filestore.hpp b/src/ox/fs/filestore.hpp index c309f50bc..a6319c463 100644 --- a/src/ox/fs/filestore.hpp +++ b/src/ox/fs/filestore.hpp @@ -17,7 +17,7 @@ struct __attribute__((packed)) FileStoreHeader { public: typedef InodeId InodeId_t; typedef FsT FsSize_t; - const static auto VERSION = 4; + const static auto VERSION = 5; private: uint16_t m_version; @@ -202,6 +202,21 @@ class FileStore { typename Header::FsSize_t readSize, void *data, typename Header::FsSize_t *size); + /** + * Reads the "file" at the given id. You are responsible for freeing + * the data when done with it. + * @param id id of the "file" + * @param readStart where in the data to start reading + * @param readSize how much data to read + * @param data pointer to the pointer where the data is stored + * @param size pointer to a value that will be assigned the size of data + * @return 0 if read is a success + */ + template + int read(InodeId_t id, typename Header::FsSize_t readStart, + typename Header::FsSize_t readSize, T *data, + typename Header::FsSize_t *size); + /** * Reads the stat information of the inode of the given inode id. * If the returned inode id is 0, then the requested inode was not found. @@ -266,8 +281,9 @@ class FileStore { * @param size pointer to a value that will be assigned the size of data * @return 0 if read is a success */ + template int read(Inode *inode, typename Header::FsSize_t readStart, - typename Header::FsSize_t readSize, void *data, + typename Header::FsSize_t readSize, T *data, typename Header::FsSize_t *size); /** @@ -568,19 +584,28 @@ void FileStore
::updateInodeAddress(InodeId_t id, typename Header::FsSize template int FileStore
::read(InodeId_t id, void *data, typename Header::FsSize_t *size) { auto inode = getInode(ptr(m_header.getRootInode()), id); - return inode ? read(inode, 0, inode->getDataLen(), data, size) : 1; + return inode ? read(inode, 0, inode->getDataLen(), (uint8_t*) data, size) : 1; } template int FileStore
::read(InodeId_t id, typename Header::FsSize_t readStart, typename Header::FsSize_t readSize, void *data, typename Header::FsSize_t *size) { auto inode = getInode(ptr(m_header.getRootInode()), id); + return inode ? read(inode, readStart, readSize, (uint8_t*) data, size) : 1; +} + +template +template +int FileStore
::read(InodeId_t id, typename Header::FsSize_t readStart, + typename Header::FsSize_t readSize, T *data, typename Header::FsSize_t *size) { + auto inode = getInode(ptr(m_header.getRootInode()), id); return inode ? read(inode, readStart, readSize, data, size) : 1; } template +template int FileStore
::read(Inode *inode, typename Header::FsSize_t readStart, - typename Header::FsSize_t readSize, void *data, typename Header::FsSize_t *size) { + typename Header::FsSize_t readSize, T *data, typename Header::FsSize_t *size) { // be sure read size is not greater than what is available to read if (inode->getDataLen() - readStart < readSize) { readSize = inode->getDataLen() - readStart; @@ -588,7 +613,12 @@ int FileStore
::read(Inode *inode, typename Header::FsSize_t readStart, if (size) { *size = readSize; } - ox_memcpy(data, inode->getData() + readStart, readSize); + + readSize /= sizeof(T); + T *it = (T*) &(inode->getData()[readStart]); + for (typename Header::FsSize_t i = 0; i < readSize; i++) { + *(data++) = *(it++); + } return 0; } diff --git a/src/ox/fs/filesystem.cpp b/src/ox/fs/filesystem.cpp index 9294a16be..ccc57173a 100644 --- a/src/ox/fs/filesystem.cpp +++ b/src/ox/fs/filesystem.cpp @@ -16,7 +16,7 @@ FileSystem *createFileSystem(void *buff, size_t buffSize) { FileSystem *fs = nullptr; switch (version) { - case 4: + case 5: switch (type) { case ox::fs::OxFS_16: fs = new FileSystem16(buff); diff --git a/src/ox/fs/filesystem.hpp b/src/ox/fs/filesystem.hpp index e31af75e9..fd4f83fd8 100644 --- a/src/ox/fs/filesystem.hpp +++ b/src/ox/fs/filesystem.hpp @@ -74,7 +74,7 @@ template class FileSystemTemplate: public FileSystem { private: - struct DirectoryEntry { + struct __attribute__((packed)) DirectoryEntry { typename FileStore::InodeId_t inode; char *getName() { @@ -89,7 +89,7 @@ class FileSystemTemplate: public FileSystem { } }; - struct Directory { + struct __attribute__((packed)) Directory { /** * Number of files in this directory. */ @@ -106,11 +106,11 @@ class FileSystemTemplate: public FileSystem { FileStore *store = nullptr; public: - FileSystemTemplate(void *buff); + explicit FileSystemTemplate(void *buff); int mkdir(const char *path); - int read(const char *path, void *buffer); + int read(const char *path, void *buffer, size_t buffSize); int read(uint64_t inode, void *buffer, size_t buffSize) override; @@ -174,6 +174,17 @@ FileStat FileSystemTemplate::stat(uint64_t inode) { #pragma warning(default:4244) #endif +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif +template +int FileSystemTemplate::read(const char *path, void *buffer, size_t buffSize) { + return 0; +} +#ifdef _MSC_VER +#pragma warning(default:4244) +#endif + #ifdef _MSC_VER #pragma warning(disable:4244) #endif diff --git a/src/ox/fs/pathiterator.cpp b/src/ox/fs/pathiterator.cpp new file mode 100644 index 000000000..a667a1098 --- /dev/null +++ b/src/ox/fs/pathiterator.cpp @@ -0,0 +1,39 @@ +/* + * Copyright 2015 - 2017 gtalent2@gmail.com + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include "pathiterator.hpp" + +namespace ox { +namespace fs { + +PathIterator::PathIterator(const char *path, size_t maxSize) { + m_path = path; + m_maxSize = maxSize; +} + +int PathIterator::next(char *pathOut, size_t pathOutSize) { + int size = 0; + const char *substr = ox_strchar(m_path + m_iterator, '/', m_maxSize - m_iterator); + m_iterator = (substr - m_path) + 1; + if (substr && m_iterator < m_maxSize) { + int start = m_iterator; + int end = (ox_strchar(m_path + start, '/', m_maxSize - start) - m_path); + if (end < 0) { + end = m_maxSize; + } + size = end - start; + ox_memcpy(pathOut, &m_path[start], size); + } + pathOut[size] = 0; // end with null terminator + return 0; +} + +} +} diff --git a/src/ox/fs/pathiterator.hpp b/src/ox/fs/pathiterator.hpp new file mode 100644 index 000000000..85a9ae939 --- /dev/null +++ b/src/ox/fs/pathiterator.hpp @@ -0,0 +1,29 @@ +/* + * Copyright 2015 - 2017 gtalent2@gmail.com + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +namespace ox { +namespace fs { + +class PathIterator { + private: + const char *m_path = nullptr; + int m_iterator = 0; + int m_maxSize = 0; + + public: + PathIterator(const char *path, size_t maxSize); + + int next(char *pathOut, size_t pathOutSize); +}; + +} +} diff --git a/src/ox/fs/test/CMakeLists.txt b/src/ox/fs/test/CMakeLists.txt index 9114a83e8..aeb7ad754 100644 --- a/src/ox/fs/test/CMakeLists.txt +++ b/src/ox/fs/test/CMakeLists.txt @@ -15,10 +15,19 @@ add_executable( filestoreio.cpp ) +add_executable( + FSTests + tests.cpp +) + target_link_libraries(FileStoreFormat OxFS OxStd) target_link_libraries(FileSystemFormat OxFS OxStd) target_link_libraries(FileStoreIO OxFS OxStd) +target_link_libraries(FSTests OxFS OxStd) add_test("FileStoreFormat" FileStoreFormat) add_test("FileSystemFormat" FileSystemFormat) add_test("FileStoreIO" FileStoreIO) +add_test("Test\\ PathIterator1" FSTests PathIterator1) +add_test("Test\\ PathIterator2" FSTests PathIterator2) +add_test("Test\\ PathIterator3" FSTests PathIterator3) diff --git a/src/ox/fs/test/tests.cpp b/src/ox/fs/test/tests.cpp new file mode 100644 index 000000000..903efa69b --- /dev/null +++ b/src/ox/fs/test/tests.cpp @@ -0,0 +1,80 @@ +/* + * Copyright 2015 - 2017 gtalent2@gmail.com + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace ox::fs; +using namespace ox::std; + +map tests = { + { + { + "PathIterator1", + [](string) { + int retval = 0; + string path = "/usr/share/charset.gbag"; + PathIterator it(path.c_str(), path.size()); + const auto buffSize = 1024; + char buff[buffSize]; + assert(buffSize >= path.size()); + retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "usr") == 0); + retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "share") == 0); + retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "charset.gbag") == 0); + return retval; + } + }, + { + "PathIterator2", + [](string) { + int retval = 0; + string path = "/usr/share/"; + PathIterator it(path.c_str(), path.size()); + const auto buffSize = 1024; + char buff[buffSize]; + assert(buffSize >= path.size()); + retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "usr") == 0); + retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "share") == 0); + return retval; + } + }, + { + "PathIterator3", + [](string) { + int retval = 0; + string path = "/"; + PathIterator it(path.c_str(), path.size()); + const auto buffSize = 1024; + char buff[buffSize]; + assert(buffSize >= path.size()); + retval |= !(it.next(buff, path.size()) == 0 && ox_strcmp(buff, "\0") == 0); + return retval; + } + }, + }, +}; + +int main(int argc, const char **args) { + int retval = -1; + if (argc > 1) { + auto testName = args[1]; + string testArg = ""; + if (args[2]) { + testArg = args[2]; + } + if (tests.find(testName) != tests.end()) { + retval = tests[testName](testArg); + } + } + return retval; +} diff --git a/src/ox/std/CMakeLists.txt b/src/ox/std/CMakeLists.txt index c0d2f10e2..70d68550f 100644 --- a/src/ox/std/CMakeLists.txt +++ b/src/ox/std/CMakeLists.txt @@ -7,6 +7,13 @@ add_library( strops.cpp ) +set_property( + TARGET + OxStd + PROPERTY + POSITION_INDEPENDENT_CODE ON +) + install( FILES byteswap.hpp diff --git a/src/ox/std/strops.cpp b/src/ox/std/strops.cpp index 83b7085be..f82984037 100644 --- a/src/ox/std/strops.cpp +++ b/src/ox/std/strops.cpp @@ -11,7 +11,7 @@ int ox_strcmp(const char *str1, const char *str2) { auto retval = 0; auto i = 0; - do { + while (str1[i] || str2[i]) { if (str1[i] < str2[i]) { retval = -1; break; @@ -20,7 +20,7 @@ int ox_strcmp(const char *str1, const char *str2) { break; } i++; - } while (str1[i] || str2[i]); + } return retval; } @@ -30,6 +30,24 @@ int ox_strlen(const char *str1) { return len; } +const char *ox_strchar(const char *str, int character, size_t maxLen) { + for (size_t i = 0; i < maxLen && str[i]; i++) { + if (str[i] == character) { + return &str[i]; + } + } + return nullptr; +} + +char *ox_strchar(char *str, int character, size_t maxLen) { + for (size_t i = 0; i < maxLen && str[i]; i++) { + if (str[i] == character) { + return &str[i]; + } + } + return nullptr; +} + int ox_atoi(const char *str) { int total = 0; int multiplier = 1; diff --git a/src/ox/std/strops.hpp b/src/ox/std/strops.hpp index e91a7415a..efea25c4f 100644 --- a/src/ox/std/strops.hpp +++ b/src/ox/std/strops.hpp @@ -13,4 +13,8 @@ int ox_strcmp(const char *str1, const char *str2); int ox_strlen(const char *str1); +const char *ox_strchar(const char *str, int character, size_t maxLen = 0xFFFFFFFF); + +char *ox_strchar(char *str, int character, size_t maxLen = 0xFFFFFFFF); + int ox_atoi(const char *str); diff --git a/src/ox/std/test/CMakeLists.txt b/src/ox/std/test/CMakeLists.txt index 82f23987c..8926e2528 100644 --- a/src/ox/std/test/CMakeLists.txt +++ b/src/ox/std/test/CMakeLists.txt @@ -28,6 +28,7 @@ add_test("Test\\ ox_strcmp\\ hijk\\ !=\\ asdf" StrOpsTest "hijk > asdf") add_test("Test\\ ox_strcmp\\ read\\ !=\\ resize" StrOpsTest "read < resize") add_test("Test\\ ox_strcmp\\ resize\\ !=\\ read" StrOpsTest "resize > read") add_test("Test\\ ox_strcmp\\ resize\\ ==\\ resize" StrOpsTest "resize == resize") +add_test("Test\\ ox_strcmp\\ resize\\ ==\\ resize" StrOpsTest " == ") ################################################################################ diff --git a/src/ox/std/test/strops_test.cpp b/src/ox/std/test/strops_test.cpp index 8950b5b0d..770c291a5 100644 --- a/src/ox/std/test/strops_test.cpp +++ b/src/ox/std/test/strops_test.cpp @@ -43,6 +43,12 @@ map> tests = { return !(ox_strcmp("resize", "resize") == 0); } }, + { + " == ", + []() { + return !(ox_strcmp("", "") == 0); + } + }, }; int main(int argc, const char **args) {