84 Commits

Author SHA1 Message Date
gary 579e584120 Add fuse libfuse-dev to .travis.yml 2017-10-11 17:04:37 -05:00
gary fa925c5519 Add start of FUSE mounting code for FS 2017-10-11 16:59:04 -05:00
gary c63e0c1d72 Revert back to C++11 2017-10-11 16:54:37 -05:00
gary 124f6de221 Start on log package 2017-10-11 16:52:17 -05:00
gary 9f8b805e4a Remove OxLog from oxfstool 2017-10-11 16:46:41 -05:00
gary 7da4009df0 Add toollib to fs CMakeLists.txt 2017-10-11 16:43:42 -05:00
gary 9d563d2736 Add toollib files for oxfs tool 2017-10-11 16:34:35 -05:00
gary 6ae08fe259 Give walk command more structured output 2017-10-11 16:27:41 -05:00
gary b01cacc2db Fix filename error with untruncated / at end of paths 2017-10-11 16:26:26 -05:00
gary cdaf21f415 Cleanup walk table 2017-09-10 00:17:24 -05:00
gary f98c1bbb11 Fix FileStore walk not to circle around 2017-09-09 23:43:18 -05:00
gary 8b436d97b4 Add size field to walk command 2017-09-09 23:41:43 -05:00
gary 0689506c47 Remove narf output 2017-09-09 23:33:23 -05:00
gary 4887d55a98 Merge branch 'master' of github.com:wombatant/ox 2017-09-09 19:33:05 -05:00
gary 84533e557e Add walk command. 2017-09-09 19:32:45 -05:00
gary 916d07e530 Merge branch 'master' of github.com:wombatant/ox into ox_master 2017-09-09 19:26:00 -05:00
gary 31af2167d6 Add operator< for DirectoryListing 2017-09-09 19:19:56 -05:00
gary 218511c98a Fix mkdir not to overwrite an existing dir 2017-09-09 19:19:56 -05:00
gary 15e05df202 Remove unused scripts 2017-07-30 02:25:54 -05:00
gary 292caad1e6 Add link count to stat in FS 2017-07-29 20:49:38 -05:00
gary 99e459a4ae Add links count field to inodes 2017-07-29 20:42:21 -05:00
gary 3211cc40d5 Add . and .. directory entries to directores 2017-07-29 02:28:37 -05:00
gary 30c28373d4 Switch to .liccor.yml 2017-07-28 17:59:43 -05:00
gary 16b6ed330a Add a check to ls to prevent ls-ing of non-directories 2017-07-01 16:21:03 -05:00
gary 56d91c18bd Fix delete/new[] mismatch 2017-07-01 02:22:41 -05:00
gary 8a071380b9 Fix m_store delete to use delete[] 2017-07-01 02:22:32 -05:00
gary b4a6aed14e Change auto expand to own buff attribute in OxFS 2017-07-01 02:22:23 -05:00
gary 7fa43dad71 Make auto expand loop if necessary 2017-07-01 02:22:14 -05:00
gary c1e8d07d9c Fix auto expand condition 2017-07-01 02:22:02 -05:00
gary d43aecd76b Add auto expand to OxFS 2017-07-01 02:21:48 -05:00
gary d7785709b6 Merge branch 'master' of github.com:wombatant/ox 2017-05-19 21:05:57 -05:00
gary 4798e545c9 Add -s flag to nested make calls 2017-05-19 21:04:43 -05:00
gary 038ca96f9e Add missing error reporting to file system ls 2017-05-14 10:43:27 -05:00
gary ac3f12fbe4 Remove unnecessary ls from FileSystemTemplate 2017-05-14 10:43:27 -05:00
gary c19a71793f Fix readDirectory use the right type of directory 2017-05-14 10:43:26 -05:00
gary 4a44a23014 Add default constructor for DirectoryListing 2017-05-14 10:43:26 -05:00
gary 68c144fe75 Add ls to file system 2017-05-12 00:05:51 -05:00
gary 1ce2797f33 Flatten out namespaces to only ox 2017-05-11 00:48:28 -05:00
gary e0063a7b55 Cleanup oxfstool format output 2017-05-09 15:15:27 -05:00
gary a2dfb41b79 Fix FS read by type to read byte by byte 2017-05-09 14:40:05 -05:00
gary a5166e03bb Fix oxfstool format to use FileSystem::format instead of FileStore::format 2017-05-04 00:50:53 -05:00
gary 796241cda6 Remove inodemgr.hpp from install 2017-05-02 17:44:54 -05:00
gary 1889cfcb58 Add compare for added MC test fields 2017-05-01 02:49:57 -05:00
gary ed8ff4bb11 Add empty struct to MC test 2017-05-01 02:39:55 -05:00
gary 4e610c3167 Fix MC to ommit empty objects 2017-05-01 02:35:14 -05:00
gary 746dae0ec5 Fix default values for MC reader and add 8+ fields struct to MC test 2017-04-30 22:00:54 -05:00
gary c3388c58f9 Fix issue with writing setting field presence mask for empty arrays 2017-04-30 21:57:57 -05:00
gary 5328f9004e Remove InodeManager 2017-04-29 14:04:48 -05:00
gary 49bc32abf9 Fix issues with MetalClaw reader iteration too many fields 2017-04-29 08:59:10 -05:00
gary 99c3ca72f5 Add array support to MetalClaw 2017-04-29 08:15:31 -05:00
gary 80ecd429c3 Fix for GCC 2017-04-28 12:50:17 -05:00
gary 7378ce4c32 Get MetalClaw read/write test passing 2017-04-28 12:42:28 -05:00
gary 50ecefdb38 Add bstring type 2017-04-28 01:36:47 -05:00
gary 6bc6230eb6 Add MetalClawWriter 2017-04-27 04:53:05 -05:00
gary 89ff3844fd Add move and strip directories functionality to FileSystem 2017-04-26 19:43:24 -05:00
gary 1cd34a9ba4 Add missing includes to the install step 2017-04-26 19:42:08 -05:00
gary fdd9dead43 Add recursive remove option to FileSystem 2017-04-26 06:43:30 -05:00
gary efa54547d0 Add support for removing files by path 2017-04-26 04:07:00 -05:00
gary 544eb94f34 Add support for removing directory entries 2017-04-26 04:01:19 -05:00
gary a7a9256503 Make warnings non-fatal during debug builds 2017-04-26 04:00:21 -05:00
gary c4c70ddabe Make FileSystem store a copy of ox::Random 2017-04-26 02:37:54 -05:00
gary a916205cdb Fix GCC compile issue 2017-04-26 01:55:38 -05:00
gary 1b6eee4d85 Fix FileStore::write test and fix missed error report 2017-04-26 01:40:46 -05:00
gary 9cd8eb2167 Fix FileSystem32::write(string) test 2017-04-25 22:29:59 -05:00
gary 493c59fa5e Merge branch 'master' of github.com:wombatant/ox 2017-04-25 22:01:34 -05:00
gary 52f326f96c Add mkdir support 2017-04-25 22:01:21 -05:00
gary 7b58d2ef06 Merge branch 'master' of github.com:wombatant/ox 2017-04-25 20:55:23 -05:00
gary 386c72a77b Add gmake switch to use gmake if it is present
gmake is expected to be the default on most platforms, but it needs to be
explicitly specified on some systems.
2017-04-25 20:36:05 -05:00
gary c5410c8755 Fix issue with allocator that caused deallocation to reset the
allocation point
2017-04-25 18:30:29 -05:00
gary b7b5772c34 Add comment crediting the random number generation algorithm 2017-04-24 20:13:15 -05:00
gary 41c017e305 Remove use of std::function in fs test 2017-04-24 02:41:57 -05:00
gary 7abbf8768f Add support for writing file by path 2017-04-24 02:38:23 -05:00
gary 7c54d3fb47 Add initial support for looking up file by path 2017-04-23 04:10:12 -05:00
gary 32d50a42df Fix oxfstool format to corrctly set the use directories setting 2017-04-23 03:58:31 -05:00
gary c3fe5e9cc2 Fix PathIterator to allow paths that don't start with / 2017-04-22 14:34:20 -05:00
gary f9634a2f3a Fix PathIterator for paths that don't end with / 2017-04-22 07:11:48 -05:00
gary d48183218c Delete byteswap.cpp 2017-04-22 02:50:58 -05:00
gary 21b83c7188 Merge branch 'master' of github.com:wombatant/ox 2017-04-22 02:46:51 -05:00
gary 1743b8ceba Reduce max string length for strops to fit 32 bit systems 2017-04-22 01:51:02 -05:00
gary a3fac6529b Fix to build with GCC 2017-04-22 01:42:16 -05:00
gary 5936a751d3 Add PathIterator class for file system 2017-04-22 01:27:26 -05:00
gary 7bce077ea8 Made libraries use position indepentent code (PIC) 2017-04-21 05:37:24 -05:00
gary 87c265e17b Put FileSystem format version bump in createFileSystem 2017-04-19 00:58:14 -05:00
gary cb4f11d41f Merge branch 'release-0.1' of github.com:wombatant/ox 2017-04-18 05:02:09 -05:00
56 changed files with 2992 additions and 306 deletions
-5
View File
@@ -1,5 +0,0 @@
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/.
+9
View File
@@ -0,0 +1,9 @@
---
source:
- src
copyright_notice: |-
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/.
+1
View File
@@ -8,4 +8,5 @@ addons:
apt:
packages:
- cmake
- libfuse-dev
script: ./scripts/cibuild
+6 -1
View File
@@ -24,10 +24,15 @@ if(NOT MSVC)
-fno-rtti
-Wsign-compare
-Wunused-variable
-Werror
#--analyze
#-Os # GCC size optimization flag
)
if (CMAKE_BUILD_TYPE STREQUAL "Release")
add_definitions(
-Werror
)
endif()
endif(NOT MSVC)
enable_testing()
+14 -7
View File
@@ -2,22 +2,29 @@ OS=$(shell uname | tr [:upper:] [:lower:])
HOST_ENV=${OS}-$(shell uname -m)
DEVENV=devenv$(shell pwd | sed 's/\//-/g')
DEVENV_IMAGE=wombatant/devenv
ifeq ($(shell docker inspect --format="{{.State.Status}}" ${DEVENV} 2>&1),running)
ENV_RUN=docker exec -i -t --user $(shell id -u ${USER}) ${DEVENV}
ifneq ($(shell which gmake),)
MAKE=gmake -s
else
MAKE=make -s
endif
ifneq ($(shell which docker 2>&1),)
ifeq ($(shell docker inspect --format="{{.State.Status}}" ${DEVENV} 2>&1),running)
ENV_RUN=docker exec -i -t --user $(shell id -u ${USER}) ${DEVENV}
endif
endif
make:
${ENV_RUN} make -j -C build HOST_ENV=${HOST_ENV}
${ENV_RUN} ${MAKE} -j -C build HOST_ENV=${HOST_ENV}
preinstall:
${ENV_RUN} make -j -C build ARGS="preinstall" HOST_ENV=${HOST_ENV}
${ENV_RUN} ${MAKE} -j -C build ARGS="preinstall" HOST_ENV=${HOST_ENV}
install:
${ENV_RUN} make -j -C build ARGS="install" HOST_ENV=${HOST_ENV}
${ENV_RUN} ${MAKE} -j -C build ARGS="install" HOST_ENV=${HOST_ENV}
clean:
${ENV_RUN} make -j -C build ARGS="clean" HOST_ENV=${HOST_ENV}
${ENV_RUN} ${MAKE} -j -C build ARGS="clean" HOST_ENV=${HOST_ENV}
purge:
${ENV_RUN} rm -rf $(shell find build -mindepth 1 -maxdepth 1 -type d)
test:
${ENV_RUN} make -j -C build ARGS="test" HOST_ENV=${HOST_ENV}
${ENV_RUN} ${MAKE} -j -C build ARGS="test" HOST_ENV=${HOST_ENV}
run: make
./build/current/src/wombat/wombat -debug
gdb: make
+6 -2
View File
@@ -1,6 +1,10 @@
all: gba_build native_build native_debug_build windows_release windows_debug
ifneq ($(shell which gmake),)
MAKE=gmake -j
else
MAKE=make
endif
MAKE=make -j
all: gba_build native_build native_debug_build windows_release windows_debug
gba_build:
@if [ -d gba-release ]; then \
-1
View File
@@ -1 +0,0 @@
clang-check `find . | grep "\.cpp" | grep -v CMakeFiles | grep -v editormodels\.cpp`
-16
View File
@@ -1,16 +0,0 @@
#! /usr/bin/env python
import sys
if len(sys.argv) < 3:
sys.exit(1)
pkg = sys.argv[1]
name = sys.argv[2]
ifdef = "WOMBAT_%s_%s_HPP" % (pkg.upper(), name.upper())
namespace = "namespace wombat {\nnamespace %s {\n\n}\n}" % pkg
hpp = "#ifndef %s\n#define %s\n\n%s\n\n#endif" % (ifdef, ifdef, namespace)
cpp = "#include \"%s.hpp\"\n\n%s" % (name, namespace)
open("src/%s/%s.hpp" % (pkg, name), "w").write(hpp)
open("src/%s/%s.cpp" % (pkg, name), "w").write(cpp)
+2
View File
@@ -4,4 +4,6 @@ if(OX_USE_STDLIB STREQUAL "ON")
add_subdirectory(clargs)
endif(OX_USE_STDLIB STREQUAL "ON")
add_subdirectory(fs)
add_subdirectory(log)
add_subdirectory(mc)
add_subdirectory(std)
+7
View File
@@ -5,6 +5,13 @@ add_library(
clargs.cpp
)
set_property(
TARGET
OxClArgs
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
install(
FILES
clargs.hpp
-2
View File
@@ -10,7 +10,6 @@
#include "clargs.hpp"
namespace ox {
namespace clargs {
using namespace ::std;
@@ -52,4 +51,3 @@ int ClArgs::getInt(const char *arg) {
}
}
}
-2
View File
@@ -12,7 +12,6 @@
#include <string>
namespace ox {
namespace clargs {
class ClArgs {
private:
@@ -31,4 +30,3 @@ class ClArgs {
};
}
}
+18 -2
View File
@@ -3,22 +3,38 @@ 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")
add_executable(
oxfstool
oxfs_fuse.cpp
toollib.cpp
oxfstool.cpp
)
set_target_properties(oxfstool PROPERTIES OUTPUT_NAME oxfs)
target_link_libraries(oxfstool OxFS OxStd)
target_link_libraries(
oxfstool
OxFS
OxLog
OxStd
fuse
)
endif()
install(
FILES
filestore.hpp
filesystem.hpp
inodemgr.hpp
pathiterator.hpp
DESTINATION
include/ox/fs
)
+164 -59
View File
@@ -5,19 +5,19 @@
* 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 <ox/std/std.hpp>
namespace ox {
namespace fs {
template<typename FsT, typename InodeId>
struct __attribute__((packed)) FileStoreHeader {
public:
typedef InodeId InodeId_t;
typedef FsT FsSize_t;
const static auto VERSION = 5;
const static auto VERSION = 6;
private:
uint16_t m_version;
@@ -45,52 +45,52 @@ struct __attribute__((packed)) FileStoreHeader {
template<typename FsSize_t, typename InodeId_t>
void FileStoreHeader<FsSize_t, InodeId_t>::setVersion(uint16_t version) {
m_version = std::bigEndianAdapt(version);
m_version = bigEndianAdapt(version);
}
template<typename FsSize_t, typename InodeId_t>
uint16_t FileStoreHeader<FsSize_t, InodeId_t>::getVersion() {
return std::bigEndianAdapt(m_version);
return bigEndianAdapt(m_version);
}
template<typename FsSize_t, typename InodeId_t>
void FileStoreHeader<FsSize_t, InodeId_t>::setFsType(uint16_t fsType) {
m_fsType = std::bigEndianAdapt(fsType);
m_fsType = bigEndianAdapt(fsType);
}
template<typename FsSize_t, typename InodeId_t>
uint16_t FileStoreHeader<FsSize_t, InodeId_t>::getFsType() {
return std::bigEndianAdapt(m_fsType);
return bigEndianAdapt(m_fsType);
}
template<typename FsSize_t, typename InodeId_t>
void FileStoreHeader<FsSize_t, InodeId_t>::setSize(FsSize_t size) {
m_size = std::bigEndianAdapt(size);
m_size = bigEndianAdapt(size);
}
template<typename FsSize_t, typename InodeId_t>
FsSize_t FileStoreHeader<FsSize_t, InodeId_t>::getSize() {
return std::bigEndianAdapt(m_size);
return bigEndianAdapt(m_size);
}
template<typename FsSize_t, typename InodeId_t>
void FileStoreHeader<FsSize_t, InodeId_t>::setMemUsed(FsSize_t memUsed) {
m_memUsed = std::bigEndianAdapt(memUsed);
m_memUsed = bigEndianAdapt(memUsed);
}
template<typename FsSize_t, typename InodeId_t>
FsSize_t FileStoreHeader<FsSize_t, InodeId_t>::getMemUsed() {
return std::bigEndianAdapt(m_memUsed);
return bigEndianAdapt(m_memUsed);
}
template<typename FsSize_t, typename InodeId_t>
void FileStoreHeader<FsSize_t, InodeId_t>::setRootInode(FsSize_t rootInode) {
m_rootInode = std::bigEndianAdapt(rootInode);
m_rootInode = bigEndianAdapt(rootInode);
}
template<typename FsSize_t, typename InodeId_t>
FsSize_t FileStoreHeader<FsSize_t, InodeId_t>::getRootInode() {
return std::bigEndianAdapt(m_rootInode);
return bigEndianAdapt(m_rootInode);
}
template<typename Header>
@@ -103,6 +103,7 @@ class FileStore {
struct StatInfo {
InodeId_t inodeId;
InodeId_t links;
typename Header::FsSize_t size;
uint8_t fileType;
};
@@ -116,6 +117,7 @@ class FileStore {
typename Header::FsSize_t m_dataLen;
InodeId_t m_id;
InodeId_t m_links;
uint8_t m_fileType;
typename Header::FsSize_t m_left;
typename Header::FsSize_t m_right;
@@ -135,6 +137,9 @@ class FileStore {
void setId(InodeId_t);
InodeId_t getId();
void setLinks(InodeId_t);
InodeId_t getLinks();
void setFileType(uint8_t);
uint8_t getFileType();
@@ -178,6 +183,24 @@ class FileStore {
*/
int remove(InodeId_t id);
/**
* Increments the links of the inode of the given ID.
* @param id the id of the inode
*/
int incLinks(InodeId_t id);
/**
* Decrements the links of the inode of the given ID.
* @param id the id of the inode
*/
int decLinks(InodeId_t id);
/**
* Removes all inodes of the type.
* @param fileType the type of file to remove
*/
int removeAllType(uint8_t fileType);
/**
* Reads the "file" at the given id. You are responsible for freeing
* the data when done with it.
@@ -245,10 +268,12 @@ class FileStore {
*/
typename Header::FsSize_t available();
void walk(int(*cb)(const char*, uint64_t start, uint64_t end));
uint16_t fsType();
uint16_t version();
static uint8_t *format(uint8_t *buffer, typename Header::FsSize_t size, uint16_t fsType = 0);
private:
@@ -262,7 +287,7 @@ class FileStore {
Inode *getInode(Inode *root, InodeId_t id);
/**
* Gets the inode at the given id.
* Gets the parent inode at the given id.
* @param root the root node to start comparing on
* @param id id of the "file"
* @param pathLen number of characters in pathLen
@@ -361,72 +386,82 @@ typename Header::FsSize_t FileStore<Header>::Inode::size() {
template<typename Header>
void FileStore<Header>::Inode::setDataLen(typename Header::FsSize_t dataLen) {
this->m_dataLen = std::bigEndianAdapt(dataLen);
this->m_dataLen = bigEndianAdapt(dataLen);
}
template<typename Header>
typename Header::FsSize_t FileStore<Header>::Inode::getDataLen() {
return std::bigEndianAdapt(m_dataLen);
return bigEndianAdapt(m_dataLen);
}
template<typename Header>
void FileStore<Header>::Inode::setPrev(typename Header::FsSize_t prev) {
this->m_prev = std::bigEndianAdapt(prev);
this->m_prev = bigEndianAdapt(prev);
}
template<typename Header>
typename Header::FsSize_t FileStore<Header>::Inode::getPrev() {
return std::bigEndianAdapt(m_prev);
return bigEndianAdapt(m_prev);
}
template<typename Header>
void FileStore<Header>::Inode::setNext(typename Header::FsSize_t next) {
this->m_next = std::bigEndianAdapt(next);
this->m_next = bigEndianAdapt(next);
}
template<typename Header>
typename Header::FsSize_t FileStore<Header>::Inode::getNext() {
return std::bigEndianAdapt(m_next);
return bigEndianAdapt(m_next);
}
template<typename Header>
void FileStore<Header>::Inode::setId(InodeId_t id) {
this->m_id = std::bigEndianAdapt(id);
this->m_id = bigEndianAdapt(id);
}
template<typename Header>
typename Header::InodeId_t FileStore<Header>::Inode::getId() {
return std::bigEndianAdapt(m_id);
return bigEndianAdapt(m_id);
}
template<typename Header>
void FileStore<Header>::Inode::setLinks(InodeId_t links) {
this->m_links = bigEndianAdapt(links);
}
template<typename Header>
typename Header::InodeId_t FileStore<Header>::Inode::getLinks() {
return bigEndianAdapt(m_links);
}
template<typename Header>
void FileStore<Header>::Inode::setFileType(uint8_t fileType) {
this->m_fileType = std::bigEndianAdapt(fileType);
this->m_fileType = bigEndianAdapt(fileType);
}
template<typename Header>
uint8_t FileStore<Header>::Inode::getFileType() {
return std::bigEndianAdapt(m_fileType);
return bigEndianAdapt(m_fileType);
}
template<typename Header>
void FileStore<Header>::Inode::setLeft(typename Header::FsSize_t left) {
this->m_left = std::bigEndianAdapt(left);
this->m_left = bigEndianAdapt(left);
}
template<typename Header>
typename Header::FsSize_t FileStore<Header>::Inode::getLeft() {
return std::bigEndianAdapt(m_left);
return bigEndianAdapt(m_left);
}
template<typename Header>
void FileStore<Header>::Inode::setRight(typename Header::FsSize_t right) {
this->m_right = std::bigEndianAdapt(right);
this->m_right = bigEndianAdapt(right);
}
template<typename Header>
typename Header::FsSize_t FileStore<Header>::Inode::getRight() {
return std::bigEndianAdapt(m_right);
return bigEndianAdapt(m_right);
}
template<typename Header>
@@ -435,7 +470,6 @@ void FileStore<Header>::Inode::setData(void *data, typename Header::FsSize_t siz
setDataLen(size);
}
template<typename Header>
uint8_t *FileStore<Header>::Inode::getData() {
return (uint8_t*) (this + 1);
@@ -487,8 +521,15 @@ int FileStore<Header>::write(InodeId_t id, void *data, typename Header::FsSize_t
auto root = ptr<Inode*>(m_header.getRootInode());
if (insert(root, inode) || root == inode) {
retval = 0;
} else {
dealloc(inode);
retval = 2;
}
} else {
retval = 3;
}
} else {
retval = 4;
}
return retval;
}
@@ -498,47 +539,73 @@ int FileStore<Header>::remove(InodeId_t id) {
return remove(ptr<Inode*>(m_header.getRootInode()), id);
}
/**
* Increments the links of the inode of the given ID.
* @param id the id of the inode
*/
template<typename Header>
int FileStore<Header>::incLinks(InodeId_t id) {
auto inode = getInode(ptr<Inode*>(m_header.getRootInode()), id);
if (inode) {
inode->setLinks(inode->getLinks() + 1);
return 0;
} else {
return 1;
}
}
/**
* Decrements the links of the inode of the given ID.
* @param id the id of the inode
*/
template<typename Header>
int FileStore<Header>::decLinks(InodeId_t id) {
auto inode = getInode(ptr<Inode*>(m_header.getRootInode()), id);
if (inode) {
inode->setLinks(inode->getLinks() - 1);
return 0;
} else {
return 1;
}
}
template<typename Header>
int FileStore<Header>::remove(Inode *root, InodeId_t id) {
auto err = 1;
if (root->getId() > id) {
if (root->getLeft()) {
auto node = ptr<Inode*>(root->getLeft());
if (node->getId() != id) {
err = remove(node, id);
auto left = ptr<Inode*>(root->getLeft());
if (left->getId() != id) {
err = remove(left, id);
} else {
root->setLeft(0);
if (node->getRight()) {
insert(root, ptr<Inode*>(node->getRight()));
// pass children to parent
if (left->getRight()) {
insert(root, ptr<Inode*>(left->getRight()));
}
if (node->getLeft()) {
insert(root, ptr<Inode*>(node->getLeft()));
if (left->getLeft()) {
insert(root, ptr<Inode*>(left->getLeft()));
}
dealloc(node);
node->setId(0);
node->setLeft(0);
node->setRight(0);
dealloc(left);
err = 0;
}
}
} else if (root->getId() < id) {
if (root->getRight()) {
auto node = ptr<Inode*>(root->getRight());
if (node->getId() != id) {
err = remove(node, id);
auto right = ptr<Inode*>(root->getRight());
if (right->getId() != id) {
err = remove(right, id);
} else {
root->setRight(0);
if (node->getRight()) {
insert(root, ptr<Inode*>(node->getRight()));
// pass children to parent
if (right->getRight()) {
insert(root, ptr<Inode*>(right->getRight()));
}
if (node->getLeft()) {
insert(root, ptr<Inode*>(node->getLeft()));
if (right->getLeft()) {
insert(root, ptr<Inode*>(right->getLeft()));
}
dealloc(node);
node->setId(0);
node->setLeft(0);
node->setRight(0);
dealloc(right);
err = 0;
}
}
@@ -548,15 +615,37 @@ int FileStore<Header>::remove(Inode *root, InodeId_t id) {
insert(ptr<Inode*>(m_header.getRootInode()), ptr<Inode*>(root->getLeft()));
}
dealloc(root);
root->setId(0);
root->setLeft(0);
root->setRight(0);
err = 0;
}
return err;
}
template<typename Header>
int FileStore<Header>::removeAllType(uint8_t fileType) {
int err = 0;
auto first = ptr<Inode*>(firstInode());
// skip the first inode for now, because removing the first inode will cause compact to run
auto current = first;
auto next = ptr<Inode*>(current->getNext());
while (next != first) {
current = next;
// get next before current is possibly cleared
next = ptr<Inode*>(current->getNext());
if (current->getFileType() == fileType) {
err |= remove(current->getId());
}
}
if (first->getFileType() == fileType) {
err |= remove(first->getId());
}
return err;
}
template<typename Header>
void FileStore<Header>::dealloc(Inode *inode) {
auto next = ptr<Inode*>(inode->getNext());
@@ -615,9 +704,13 @@ int FileStore<Header>::read(Inode *inode, typename Header::FsSize_t readStart,
}
readSize /= sizeof(T);
T *it = (T*) &(inode->getData()[readStart]);
uint8_t *it = &(inode->getData()[readStart]);
for (typename Header::FsSize_t i = 0; i < readSize; i++) {
*(data++) = *(it++);
T val;
for (size_t i = 0; i < sizeof(T); i++) {
((uint8_t*) (&val))[i] = *(it++);
}
*(data++) = val;
}
return 0;
}
@@ -629,6 +722,7 @@ typename FileStore<Header>::StatInfo FileStore<Header>::stat(InodeId_t id) {
if (inode) {
stat.size = inode->getDataLen();
stat.fileType = inode->getFileType();
stat.links = inode->getLinks();
stat.inodeId = id;
} else {
stat.inodeId = 0;
@@ -717,6 +811,7 @@ void *FileStore<Header>::alloc(typename Header::FsSize_t size) {
inode->setPrev(ptr<Inode*>(firstInode())->getPrev());
inode->setNext(firstInode());
m_header.setMemUsed(m_header.getMemUsed() + size);
ptr<Inode*>(lastInode())->setNext(retval);
ptr<Inode*>(firstInode())->setPrev(retval);
return inode;
}
@@ -794,6 +889,17 @@ uint16_t FileStore<Header>::version() {
return m_header.getVersion();
};
template<typename Header>
void FileStore<Header>::walk(int(*cb)(const char*, uint64_t start, uint64_t end)) {
auto err = cb("Header", 0, sizeof(Header));
auto inode = ptr<Inode*>(firstInode());
do {
auto start = ptr(inode);
err = cb("Inode", start, start + inode->size());
inode = ptr<Inode*>(inode->getNext());
} while (!err && inode != ptr<Inode*>(firstInode()));
}
template<typename Header>
uint8_t *FileStore<Header>::format(uint8_t *buffer, typename Header::FsSize_t size, uint16_t fsType) {
ox_memset(buffer, 0, size);
@@ -811,8 +917,7 @@ uint8_t *FileStore<Header>::format(uint8_t *buffer, typename Header::FsSize_t si
}
typedef FileStore<FileStoreHeader<uint16_t, uint16_t>> FileStore16;
typedef FileStore<FileStoreHeader<uint32_t, uint16_t>> FileStore32;
typedef FileStore<FileStoreHeader<uint64_t, uint16_t>> FileStore64;
typedef FileStore<FileStoreHeader<uint32_t, uint64_t>> FileStore32;
typedef FileStore<FileStoreHeader<uint64_t, uint64_t>> FileStore64;
}
}
+9 -10
View File
@@ -5,27 +5,27 @@
* 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 "filesystem.hpp"
namespace ox {
namespace fs {
FileSystem *createFileSystem(void *buff, size_t buffSize) {
FileSystem *createFileSystem(uint8_t *buff, size_t buffSize, bool ownsBuff) {
auto version = ((FileStore16*) buff)->version();
auto type = ((FileStore16*) buff)->fsType();
FileSystem *fs = nullptr;
switch (version) {
case 4:
case 6:
switch (type) {
case ox::fs::OxFS_16:
fs = new FileSystem16(buff);
case ox::OxFS_16:
fs = new FileSystem16(buff, ownsBuff);
break;
case ox::fs::OxFS_32:
fs = new FileSystem32(buff);
case ox::OxFS_32:
fs = new FileSystem32(buff, ownsBuff);
break;
case ox::fs::OxFS_64:
fs = new FileSystem64(buff);
case ox::OxFS_64:
fs = new FileSystem64(buff, ownsBuff);
break;
}
break;
@@ -71,4 +71,3 @@ FileSystem *expandCopyCleanup(FileSystem *fs, size_t size) {
}
}
}
+655 -74
View File
@@ -8,10 +8,10 @@
#pragma once
#include <ox/std/std.hpp>
#include "pathiterator.hpp"
#include "filestore.hpp"
namespace ox {
namespace fs {
enum FsType {
OxFS_16 = 1,
@@ -20,34 +20,227 @@ enum FsType {
};
enum FileType {
NormalFile = 1,
Directory = 2
FileType_NormalFile = 1,
FileType_Directory = 2
};
struct FileStat {
uint64_t inode;
uint64_t links;
uint64_t size;
uint8_t fileType;
};
template<typename String>
struct DirectoryListing {
String name;
FileStat stat;
DirectoryListing() = default;
DirectoryListing(const char *name) {
this->name = name;
}
};
template<typename String>
bool operator<(const DirectoryListing<String> &a, const DirectoryListing<String> &b) {
return a.name < b.name;
}
template<typename InodeId_t>
struct __attribute__((packed)) DirectoryEntry {
InodeId_t inode;
char *getName() {
return (char*) (this + 1);
}
void setName(const char *name) {
auto data = getName();
auto nameLen = ox_strlen(name);
ox_memcpy(data, name, nameLen);
data[nameLen] = 0;
}
static uint64_t spaceNeeded(const char *fileName) {
return sizeof(DirectoryEntry) + ox_strlen(fileName) + 1;
}
/**
* The size in bytes.
*/
uint64_t size() {
return spaceNeeded(getName());
}
};
template<typename InodeId_t, typename FsSize_t>
struct __attribute__((packed)) Directory {
/**
* Number of bytes after this Directory struct.
*/
FsSize_t size = 0;
FsSize_t children = 0;
DirectoryEntry<InodeId_t> *files() {
return size ? (DirectoryEntry<InodeId_t>*) (this + 1) : nullptr;
}
uint64_t getFileInode(const char *name);
int getChildrenInodes(InodeId_t *inodes, size_t inodesLen);
int rmFile(const char *name);
int copy(Directory<uint64_t, uint64_t> *dirOut);
template<typename List>
int ls(List *list);
};
template<typename InodeId_t, typename FsSize_t>
uint64_t Directory<InodeId_t, FsSize_t>::getFileInode(const char *name) {
uint64_t inode = 0;
auto current = files();
if (current) {
for (uint64_t i = 0; ox_strcmp(current->getName(), name) != 0;) {
i += current->size();
if (i < this->size) {
current = (DirectoryEntry<InodeId_t>*) (((uint8_t*) current) + current->size());
} else {
current = nullptr;
break;
}
}
if (current) {
inode = current->inode;
}
}
return inode;
}
template<typename InodeId_t, typename FsSize_t>
int Directory<InodeId_t, FsSize_t>::getChildrenInodes(InodeId_t *inodes, size_t inodesLen) {
if (inodesLen >= this->children) {
auto current = files();
if (current) {
for (uint64_t i = 0; i < this->children; i++) {
if (ox_strcmp(current->getName(), ".") and ox_strcmp(current->getName(), "..")) {
inodes[i] = current->inode;
}
current = (DirectoryEntry<InodeId_t>*) (((uint8_t*) current) + current->size());
}
return 0;
} else {
return 1;
}
} else {
return 2;
}
}
template<typename InodeId_t, typename FsSize_t>
int Directory<InodeId_t, FsSize_t>::rmFile(const char *name) {
int err = 1;
auto current = files();
if (current) {
for (uint64_t i = 0; i < this->size;) {
i += current->size();
if (ox_strcmp(current->getName(), name) == 0) {
auto dest = (uint8_t*) current;
auto src = dest + current->size();
ox_memcpy(dest, src, this->size - i);
this->size -= current->size();
this->children--;
err = 0;
break;
}
current = (DirectoryEntry<InodeId_t>*) (((uint8_t*) current) + current->size());
}
}
return err;
}
template<typename InodeId_t, typename FsSize_t>
int Directory<InodeId_t, FsSize_t>::copy(Directory<uint64_t, uint64_t> *dirOut) {
auto current = files();
auto dirOutBuff = (uint8_t*) dirOut;
dirOutBuff += sizeof(Directory<uint64_t, uint64_t>);
dirOut->size = this->size;
dirOut->children = this->children;
if (current) {
for (uint64_t i = 0; i < this->children; i++) {
auto entry = (DirectoryEntry<uint64_t>*) dirOutBuff;
entry->inode = current->inode;
entry->setName(current->getName());
current = (DirectoryEntry<InodeId_t>*) (((uint8_t*) current) + current->size());
dirOutBuff += entry->size();
}
return 0;
} else {
return 1;
}
}
template<typename InodeId_t, typename FsSize_t>
template<typename List>
int Directory<InodeId_t, FsSize_t>::ls(List *list) {
auto current = files();
if (current) {
for (uint64_t i = 0; i < this->children; i++) {
list->push_back(current->getName());
(*list)[i].stat.inode = current->inode;
current = (DirectoryEntry<InodeId_t>*) (((uint8_t*) current) + current->size());
}
return 0;
} else {
return 1;
}
}
class FileSystem {
public:
virtual ~FileSystem() {};
virtual int stripDirectories() = 0;
virtual int mkdir(const char *path) = 0;
/**
* Moves an entry from one directory to another.
* @param src the path to the file
* @param dest the path of the destination directory
*/
virtual int move(const char *src, const char *dest) = 0;
template<typename List>
int ls(const char *path, List *list);
virtual int read(const char *path, void *buffer, size_t buffSize) = 0;
virtual int read(uint64_t inode, void *buffer, size_t size) = 0;
virtual int read(uint64_t inode, size_t readStart, size_t readSize, void *buffer, size_t *size) = 0;
virtual uint8_t *read(uint64_t inode, size_t *size) = 0;
virtual int remove(uint64_t inode) = 0;
virtual int remove(uint64_t inode, bool recursive = false) = 0;
virtual int remove(const char *path, bool recursive = false) = 0;
virtual void resize(uint64_t size = 0) = 0;
virtual int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = NormalFile) = 0;
virtual int write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) = 0;
virtual int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) = 0;
virtual FileStat stat(uint64_t inode) = 0;
virtual FileStat stat(const char *path) = 0;
virtual uint64_t spaceNeeded(uint64_t size) = 0;
virtual uint64_t available() = 0;
@@ -55,9 +248,27 @@ class FileSystem {
virtual uint64_t size() = 0;
virtual uint8_t *buff() = 0;
virtual void walk(int(*cb)(const char*, uint64_t, uint64_t)) = 0;
protected:
virtual int readDirectory(const char *path, Directory<uint64_t, uint64_t> *dirOut) = 0;
};
FileSystem *createFileSystem(void *buff, size_t buffSize);
template<typename List>
int FileSystem::ls(const char *path, List *list) {
int err = 0;
auto s = stat(path);
if (s.fileType == FileType_Directory) {
uint8_t dirBuff[s.size * 4];
auto dir = (Directory<uint64_t, uint64_t>*) dirBuff;
err = readDirectory(path, dir);
err |= dir->ls(list);
}
return err;
}
FileSystem *createFileSystem(uint8_t *buff, size_t buffSize, bool ownsBuff = false);
/**
* Creates a larger version of the given FileSystem.
@@ -74,43 +285,24 @@ template<typename FileStore, FsType FS_TYPE>
class FileSystemTemplate: public FileSystem {
private:
struct DirectoryEntry {
typename FileStore::InodeId_t inode;
char *getName() {
return (char*) (this + 1);
}
void setName(const char *name) {
auto data = getName();
auto nameLen = ox_strlen(name);
ox_memcpy(data, &name, nameLen);
data[nameLen] = 0;
}
};
struct Directory {
/**
* Number of files in this directory.
*/
typename FileStore::InodeId_t size = 0;
DirectoryEntry *files() {
return (DirectoryEntry*) (this + 1);
}
};
// static members
static typename FileStore::InodeId_t INODE_ROOT_DIR;
FileStore *store = nullptr;
FileStore *m_store = nullptr;
bool m_ownsBuff = false;
public:
explicit FileSystemTemplate(void *buff);
// static members
static typename FileStore::InodeId_t INODE_RANDOM;
static typename FileStore::InodeId_t INODE_ROOT_DIR;
static typename FileStore::InodeId_t INODE_RESERVED_END;
int mkdir(const char *path);
explicit FileSystemTemplate(uint8_t *buff, bool ownsBuff = false);
int read(const char *path, void *buffer);
~FileSystemTemplate();
int stripDirectories() override;
int mkdir(const char *path) override;
int read(const char *path, void *buffer, size_t buffSize) override;
int read(uint64_t inode, void *buffer, size_t buffSize) override;
@@ -120,14 +312,20 @@ class FileSystemTemplate: public FileSystem {
void resize(uint64_t size = 0) override;
int remove(uint64_t inode) override;
int remove(uint64_t inode, bool recursive = false) override;
int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) override;
int remove(const char *path, bool recursive = false) override;
FileStat stat(const char *path);
int write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override;
int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override;
FileStat stat(const char *path) override;
FileStat stat(uint64_t inode) override;
uint64_t findInodeOf(const char *name);
uint64_t spaceNeeded(uint64_t size) override;
uint64_t available() override;
@@ -136,25 +334,106 @@ class FileSystemTemplate: public FileSystem {
uint8_t *buff() override;
static uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories);
int move(const char *src, const char *dest) override;
/**
* Removes an entry from a directory. This does not delete the referred to file.
*/
int rmDirectoryEntry(const char *path);
void walk(int(*cb)(const char*, uint64_t, uint64_t)) override;
static uint8_t *format(uint8_t *buffer, typename FileStore::FsSize_t size, bool useDirectories);
protected:
int readDirectory(const char *path, Directory<uint64_t, uint64_t> *dirOut) override;
private:
uint64_t generateInodeId();
int insertDirectoryEntry(const char *dirPath, const char *fileName, uint64_t inode);
void expand(uint64_t size);
};
template<typename FileStore, FsType FS_TYPE>
FileSystemTemplate<FileStore, FS_TYPE>::FileSystemTemplate(void *buff) {
store = (FileStore*) buff;
FileSystemTemplate<FileStore, FS_TYPE>::FileSystemTemplate(uint8_t *buff, bool ownsBuff) {
m_store = (FileStore*) buff;
m_ownsBuff = ownsBuff;
}
template<typename FileStore, FsType FS_TYPE>
FileSystemTemplate<FileStore, FS_TYPE>::~FileSystemTemplate() {
if (m_ownsBuff) {
delete[] (uint8_t*) m_store;
}
}
template<typename FileStore, FsType FS_TYPE>
typename FileStore::InodeId_t FileSystemTemplate<FileStore, FS_TYPE>::INODE_RANDOM = 1;
template<typename FileStore, FsType FS_TYPE>
typename FileStore::InodeId_t FileSystemTemplate<FileStore, FS_TYPE>::INODE_ROOT_DIR = 2;
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::mkdir(const char *path) {
return 0;
typename FileStore::InodeId_t FileSystemTemplate<FileStore, FS_TYPE>::INODE_RESERVED_END = 100;
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::stripDirectories() {
return m_store->removeAllType(FileType::FileType_Directory);
}
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::mkdir(const char *pathIn) {
if (!findInodeOf(pathIn)) {
auto pathLen = ox_strlen(pathIn);
char path[pathLen + 1];
ox_memcpy(path, pathIn, pathLen + 1);
// make sure last character does not end with /
if (pathLen >= 1 && path[pathLen - 1] == '/') {
path[pathLen - 1] = 0;
pathLen--;
}
Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t> dir;
auto err = write(path, &dir, sizeof(dir), FileType::FileType_Directory);
if (err) {
return err;
}
// add . entry for self
auto inode = findInodeOf(path);
err = insertDirectoryEntry(path, ".", inode);
if (err) {
remove(inode);
return err;
}
// add .. entry for parent
char dirPath[pathLen];
PathIterator pathReader(path, pathLen);
err |= pathReader.dirPath(dirPath, pathLen);
err = insertDirectoryEntry(path, "..", findInodeOf(dirPath));
if (err) {
remove(inode);
return err;
}
return err;
} else {
return 1;
}
}
template<typename FileStore, FsType FS_TYPE>
FileStat FileSystemTemplate<FileStore, FS_TYPE>::stat(const char *path) {
auto inode = findInodeOf(path);
FileStat stat;
auto s = m_store->stat(inode);
stat.size = s.size;
stat.inode = s.inodeId;
stat.fileType = s.fileType;
return stat;
}
@@ -164,9 +443,10 @@ FileStat FileSystemTemplate<FileStore, FS_TYPE>::stat(const char *path) {
template<typename FileStore, FsType FS_TYPE>
FileStat FileSystemTemplate<FileStore, FS_TYPE>::stat(uint64_t inode) {
FileStat stat;
auto s = store->stat(inode);
auto s = m_store->stat(inode);
stat.size = s.size;
stat.inode = s.inodeId;
stat.links = s.links;
stat.fileType = s.fileType;
return stat;
}
@@ -178,13 +458,33 @@ FileStat FileSystemTemplate<FileStore, FS_TYPE>::stat(uint64_t inode) {
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, void *buffer, size_t buffSize) {
auto stat = store->stat(inode);
if (stat.size <= buffSize) {
return store->read(inode, buffer, nullptr);
int FileSystemTemplate<FileStore, FS_TYPE>::read(const char *path, void *buffer, size_t buffSize) {
int retval = -1;
// find the inode for the given path
auto inode = findInodeOf(path);
// if inode exists, read the data into buffer
if (inode) {
retval = read(inode, buffer, buffSize);
}
return 0;
;
return retval;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, void *buffer, size_t buffSize) {
auto stat = m_store->stat(inode);
if (stat.size <= buffSize) {
return m_store->read(inode, buffer, nullptr);
}
return -1;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
@@ -198,10 +498,10 @@ int FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, size_t readStar
size_t readSize, void *buffer,
size_t *size) {
if (size) {
auto stat = store->stat(inode);
auto stat = m_store->stat(inode);
*size = stat.size;
}
return store->read(inode, readStart, readSize, buffer, nullptr);
return m_store->read(inode, readStart, readSize, buffer, nullptr);
}
#ifdef _MSC_VER
#pragma warning(disable:4244)
@@ -212,12 +512,12 @@ int FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, size_t readStar
#endif
template<typename FileStore, FsType FS_TYPE>
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, size_t *size) {
auto s = store->stat(inode);
auto s = m_store->stat(inode);
auto buff = new uint8_t[s.size];
if (size) {
*size = s.size;
}
if (store->read(inode, buff, nullptr)) {
if (m_store->read(inode, buff, nullptr)) {
delete []buff;
buff = nullptr;
}
@@ -227,12 +527,88 @@ uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, size_t *si
#pragma warning(default:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::remove(const char *path, bool recursive) {
auto inode = findInodeOf(path);
if (inode) {
return rmDirectoryEntry(path) | remove(inode, recursive);
} else {
return 1;
}
}
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::remove(uint64_t inode) {
return store->remove(inode);
int FileSystemTemplate<FileStore, FS_TYPE>::remove(uint64_t inode, bool recursive) {
auto fileType = stat(inode).fileType;
if (fileType != FileType::FileType_Directory) {
return m_store->remove(inode);
} else if (fileType == FileType::FileType_Directory && recursive) {
int err = 0;
auto dirStat = stat(inode);
auto dirBuffLen = dirStat.size;
uint8_t dirBuff[dirBuffLen];
auto dir = (Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t>*) dirBuff;
err = read(dirStat.inode, dirBuff, dirBuffLen);
if (err) {
return 1;
}
typename FileStore::InodeId_t inodes[dir->children];
ox_memset(inodes, 0, sizeof(typename FileStore::InodeId_t) * dir->children);
dir->getChildrenInodes(inodes, dir->children);
for (auto i : inodes) {
if (i) {
err |= remove(i, true);
}
}
if (!err) {
err |= m_store->remove(inode);
}
return err;
} else {
return 1;
}
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::write(const char *path, void *buffer, uint64_t size, uint8_t fileType) {
int err = 0;
size_t pathLen = ox_strlen(path);
char dirPath[pathLen];
char fileName[pathLen];
PathIterator pathReader(path, pathLen);
err |= pathReader.fileName(fileName, pathLen);
err |= pathReader.dirPath(dirPath, pathLen);
if (err) {
return err;
}
uint64_t inode = findInodeOf(path);
// find an inode value for the given path
if (!inode) {
inode = generateInodeId();
err |= write(inode, buffer, 0, fileType); // ensure file exists before indexing it
err |= insertDirectoryEntry(dirPath, fileName, inode);
}
if (!err) {
err = write(inode, buffer, size, fileType);
}
return err;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
@@ -243,7 +619,48 @@ int FileSystemTemplate<FileStore, FS_TYPE>::remove(uint64_t inode) {
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) {
return store->write(inode, buffer, size, fileType);
if (m_ownsBuff) {
while (m_store->spaceNeeded(size) > m_store->available()) {
expand(this->size() * 2);
}
}
return m_store->write(inode, buffer, size, fileType);
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::findInodeOf(const char *path) {
const auto pathLen = ox_strlen(path);
PathIterator it(path, pathLen);
char fileName[pathLen];
uint64_t inode = INODE_ROOT_DIR;
while (it.hasNext() && it.next(fileName, pathLen) == 0 && ox_strlen(fileName)) {
auto dirStat = stat(inode);
if (dirStat.inode && dirStat.size >= sizeof(Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t>)) {
uint8_t dirBuffer[dirStat.size];
auto dir = (Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t>*) dirBuffer;
if (read(inode, dirBuffer, dirStat.size) == 0) {
if (dirStat.fileType == FileType::FileType_Directory) {
inode = dir->getFileInode(fileName);
} else {
inode = 0; // null out inode and break
break;
}
} else {
inode = 0; // null out inode and break
break;
}
} else {
inode = 0; // null out inode and break
break;
}
}
return inode;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
@@ -251,42 +668,40 @@ int FileSystemTemplate<FileStore, FS_TYPE>::write(uint64_t inode, void *buffer,
template<typename FileStore, FsType FS_TYPE>
void FileSystemTemplate<FileStore, FS_TYPE>::resize(uint64_t size) {
return store->resize(size);
return m_store->resize(size);
}
template<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::spaceNeeded(uint64_t size) {
return store->spaceNeeded(size);
return m_store->spaceNeeded(size);
}
template<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::available() {
return store->available();
return m_store->available();
}
template<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::size() {
return store->size();
return m_store->size();
}
template<typename FileStore, FsType FS_TYPE>
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::buff() {
return (uint8_t*) store;
return (uint8_t*) m_store;
}
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories) {
buffer = FileStore::format((uint8_t*) buffer, size, (uint16_t) FS_TYPE);
FileSystemTemplate<FileStore, FS_TYPE> fs(buffer);
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::format(uint8_t *buffer, typename FileStore::FsSize_t size, bool useDirectories) {
buffer = FileStore::format(buffer, size, (uint16_t) FS_TYPE);
if (buffer && useDirectories) {
char dirBuff[sizeof(Directory) + sizeof(DirectoryEntry) + 2];
auto *dir = (Directory*) dirBuff;
dir->files();
fs.write(INODE_ROOT_DIR, dirBuff, useDirectories, FileType::Directory);
Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t> dir;
FileSystemTemplate<FileStore, FS_TYPE> fs((uint8_t*) buffer);
fs.write(INODE_ROOT_DIR, &dir, sizeof(dir), FileType::FileType_Directory);
}
return (uint8_t*) buffer;
@@ -295,9 +710,175 @@ uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::format(void *buffer, typename F
#pragma warning(default:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::generateInodeId() {
Random rand;
read(INODE_RANDOM, &rand, sizeof(rand));
uint64_t inode = 0;
// find an inode value for the given path
while (!inode) {
inode = rand.gen();
inode >>= 64 - 8 * sizeof(typename FileStore::InodeId_t);
// make sure this does not already exist
if (inode < INODE_RESERVED_END || stat(inode).inode) {
// that result was unusable, try again
inode = 0;
}
}
write(INODE_RANDOM, &rand, sizeof(rand));
return inode;
}
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::insertDirectoryEntry(const char *dirPath, const char *fileName, uint64_t inode) {
auto s = stat(dirPath);
if (s.inode) {
auto spaceNeeded = DirectoryEntry<typename FileStore::InodeId_t>::spaceNeeded(fileName);
size_t dirBuffSize = s.size + spaceNeeded;
uint8_t dirBuff[dirBuffSize];
int err = read(s.inode, dirBuff, dirBuffSize);
if (!err) {
auto dir = (Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t>*) dirBuff;
dir->size += spaceNeeded;
dir->children++;
auto entry = (DirectoryEntry<typename FileStore::InodeId_t>*) &dirBuff[s.size];
entry->inode = inode;
entry->setName(fileName);
err = write(s.inode, dirBuff, dirBuffSize, FileType_Directory);
err |= m_store->incLinks(inode);
return err;
} else {
return 1;
}
} else {
return 2;
}
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::move(const char *src, const char *dest) {
auto inode = stat(src).inode;
if (inode && !stat(dest).inode) {
int err = 0;
size_t srcLen = ox_strlen(src);
char srcDirPath[srcLen];
char srcFileName[srcLen];
PathIterator srcPathReader(src, srcLen);
err |= srcPathReader.fileName(srcFileName, srcLen);
err |= srcPathReader.dirPath(srcDirPath, srcLen);
if (err) {
return err;
}
size_t destLen = ox_strlen(dest);
char destDirPath[destLen];
char destFileName[destLen];
PathIterator destPathReader(dest, destLen);
err |= destPathReader.fileName(destFileName, destLen);
err |= destPathReader.dirPath(destDirPath, destLen);
if (err) {
return err;
}
err = rmDirectoryEntry(src);
if (err) {
return err;
}
err = insertDirectoryEntry(destDirPath, destFileName, inode);
if (!err) {
return err;
}
return 0;
} else {
return 1;
}
}
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::rmDirectoryEntry(const char *path) {
int err = 0;
size_t pathLen = ox_strlen(path);
char dirPath[pathLen];
char fileName[pathLen];
PathIterator pathReader(path, pathLen);
err |= pathReader.fileName(fileName, pathLen);
err |= pathReader.dirPath(dirPath, pathLen);
if (err) {
return err;
}
auto dirStat = stat(dirPath);
auto dirBuffLen = dirStat.size;
uint8_t dirBuff[dirBuffLen];
err = read(dirStat.inode, dirBuff, dirBuffLen);
if (err) {
return err;
}
auto dir = (Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t>*) dirBuff;
auto inode = dir->getFileInode(fileName);
err |= dir->rmFile(fileName);
err |= m_store->decLinks(inode);
if (err) {
return err;
}
err = write(dirStat.inode, dirBuff, dirBuffLen - DirectoryEntry<typename FileStore::InodeId_t>::spaceNeeded(fileName));
return err;
}
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::readDirectory(const char *path, Directory<uint64_t, uint64_t> *dirOut) {
int err = 0;
auto inode = findInodeOf(path);
auto dirStat = stat(inode);
auto dirBuffLen = dirStat.size;
uint8_t dirBuff[dirBuffLen];
auto dir = (Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t>*) dirBuff;
err = read(dirStat.inode, dirBuff, dirBuffLen);
if (!err) {
return dir->copy(dirOut);
} else {
return 1;
}
}
template<typename FileStore, FsType FS_TYPE>
void FileSystemTemplate<FileStore, FS_TYPE>::expand(uint64_t newSize) {
if (newSize > size()) {
auto newBuff = new uint8_t[newSize];
ox_memcpy(newBuff, m_store, m_store->size());
delete[] m_store;
m_store = (FileStore*) newBuff;
resize(newSize);
}
}
template<typename FileStore, FsType FS_TYPE>
void FileSystemTemplate<FileStore, FS_TYPE>::walk(int(*cb)(const char*, uint64_t, uint64_t)) {
m_store->walk(cb);
}
typedef FileSystemTemplate<FileStore16, OxFS_16> FileSystem16;
typedef FileSystemTemplate<FileStore32, OxFS_32> FileSystem32;
typedef FileSystemTemplate<FileStore64, OxFS_64> FileSystem64;
}
}
-53
View File
@@ -1,53 +0,0 @@
/*
* 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
namespace ox {
namespace fs {
/**
* Used to track unused inodes.
*/
template<typename InodeId_t>
struct InodeFile {
InodeId_t length;
InodeId_t *inodes();
};
template<typename InodeId_t>
InodeId_t *InodeFile<InodeId_t>::inodes() {
return (InodeId_t*) (this + 1);
}
template<typename InodeId_t>
int generateInodeFile(InodeId_t *inodes, int count) {
const static InodeId_t endPoint = ~0;
auto it = count;
auto multiplier = 1;
auto current = endPoint / 2;
auto lowestNode = current;
inodes[0] = count;
while (it > 0) {
current = lowestNode * multiplier;
if (current < endPoint) {
inodes[it--] = current;
multiplier += 2;
} else {
multiplier = 1;
lowestNode /= 2;
}
}
return 0;
}
}
}
+132
View File
@@ -0,0 +1,132 @@
/*
* 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 <string>
#include <vector>
#define _FILE_OFFSET_BITS 64
#define FUSE_USE_VERSION 30
#include <fuse.h>
#include <unistd.h>
#include <ox/log/log.hpp>
#include <ox/std/std.hpp>
#include "filesystem.hpp"
#include "toollib.hpp"
#include "oxfs_fuse.hpp"
using namespace ox;
using namespace std;
static FileSystem *fuse = nullptr;
static FileSystem *fs() {
return fuse;
}
static const fuse_operations &fuseOps() {
static fuse_operations ops;
ops.getattr = [](const char *path, struct stat *out) -> int {
debug("FUSE: getattr: %s", path);
auto stat = fs()->stat(path);
if (stat.inode) {
mode_t mode;
if (stat.fileType == FileType_Directory) {
mode = S_IFDIR | 0755;
} else {
mode = S_IFREG | 0644;
}
out->st_mode = mode; /* permissions */
out->st_nlink = (nlink_t) stat.links; /* number of hard links */
out->st_uid = getuid(); /* user ID of owner */
out->st_gid = getgid(); /* group ID of owner */
out->st_size = (uint32_t) stat.size; /* total size, in bytes */
#ifndef __APPLE__
out->st_atim = {time(nullptr)}; /* time of last access */
out->st_mtim = {time(nullptr)}; /* time of last modification */
out->st_ctim = {time(nullptr)}; /* time of last change */
#endif
return 0;
} else {
debug("FUSE: getattr: %s: not found", path);
return 1;
}
};
ops.mkdir = [](const char *path, mode_t) -> int {
debug("FUSE: mkdir: %s", path);
return fs()->mkdir(path);
};
ops.open = [](const char *path, struct fuse_file_info*) -> int {
debug("FUSE: open: %s", path);
return 0;
};
ops.read = [](const char *path, char *buffer, size_t size,
off_t offset, struct fuse_file_info *fi) -> int {
debug("FUSE: read: %s", path);
auto inode = fs()->stat(path).inode;
size_t readSize = -1;
fs()->read(inode, offset, size, buffer, &readSize);
return readSize;
};
ops.readdir = [](const char *path, void *buffer, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi) -> int {
debug("FUSE: readdir: %s", path);
vector<DirectoryListing<string>> files;
if (fs()->ls(path, &files) == 0) {
for (auto file : files) {
filler(buffer, file.name.c_str(), nullptr, 0);
}
}
return 0;
};
ops.rename = [](const char *src, const char *dest) -> int {
debug("FUSE: rename: %s to %s", src, dest);
return fs()->move(src, dest);
};
ops.rmdir = [](const char *path) -> int {
debug("FUSE: rmdir: %s", path);
return fs()->remove(path);
};
ops.unlink = [](const char *path) -> int {
debug("FUSE: unlink: %s", path);
return fs()->remove(path);
};
return ops;
};
int mount(int argc, char **args) {
logFile("/home/gary/log");
int err = 0;
size_t fsSize;
auto fsPath = args[2];
auto mountPoint = args[3];
auto fsBuff = loadFileBuff(fsPath, &fsSize);
if (fsBuff) {
fuse = createFileSystem(fsBuff, fsSize);
if (fuse) {
const char *fuseArgs[2] = {(char*) "oxfuse", mountPoint};
err = fuse_main(2, (char**) fuseArgs, &fuseOps(), nullptr);
} else {
err = 1;
}
} else {
err = 2;
}
return err;
}
@@ -6,4 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "byteswap.hpp"
#pragma once
int mount(int argc, char **args);
+86 -51
View File
@@ -5,22 +5,28 @@
* 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 <iomanip>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <map>
#include <ox/std/strops.hpp>
#include <ox/fs/filesystem.hpp>
#include "oxfs_fuse.hpp"
#include "toollib.hpp"
// suppress warnings about using fopen
#ifdef _MSC_VER
#pragma warning(disable:4996)
#endif
using namespace ox::fs;
using namespace ox;
using namespace std;
const static auto oxfstoolVersion = "1.2.0";
const static auto oxfstoolVersion = "1.4.0";
const static auto usage = "usage:\n"
"\toxfs format [16,32,64] <size> <path>\n"
"\toxfs read <FS file> <inode>\n"
@@ -28,29 +34,10 @@ const static auto usage = "usage:\n"
"\toxfs write-expand <FS file> <inode> <insertion file>\n"
"\toxfs rm <FS file> <inode>\n"
"\toxfs compact <FS file>\n"
"\toxfs walk <FS file>\n"
"\toxfs mount <FS file> <mount point>\n"
"\toxfs version\n";
char *loadFileBuff(FILE *file, ::size_t *sizeOut = nullptr) {
if (file) {
fseek(file, 0, SEEK_END);
const auto size = ftell(file);
rewind(file);
auto buff = new char[size];
auto itemsRead = fread(buff, size, 1, file);
fclose(file);
if (sizeOut) {
*sizeOut = itemsRead ? size : 0;
}
return buff;
} else {
return nullptr;
}
}
char *loadFileBuff(const char *path, ::size_t *sizeOut = nullptr) {
return loadFileBuff(fopen(path, "rb"), sizeOut);
}
size_t bytes(const char *str) {
auto size = ::ox_strlen(str);
const auto lastChar = str[size-1];
@@ -99,13 +86,13 @@ int format(int argc, char **args) {
// format
switch (type) {
case 16:
FileStore16::format(buff, (FileStore16::FsSize_t) size, ox::fs::OxFS_16);
FileSystem16::format(buff, (FileStore16::FsSize_t) size, true);
break;
case 32:
FileStore32::format(buff, (FileStore32::FsSize_t) size, ox::fs::OxFS_32);
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
break;
case 64:
FileStore64::format(buff, size, ox::fs::OxFS_64);
FileSystem64::format(buff, size, true);
break;
default:
err = 1;
@@ -128,7 +115,9 @@ int format(int argc, char **args) {
delete []buff;
if (err == 0) {
fprintf(stderr, "Created file system %s\n", path);
cerr << "Created file system " << path << endl;
cerr << " type " << type << endl;
cerr << " wrote " << size << " bytes\n";
}
} else {
fprintf(stderr, "Insufficient arguments\n");
@@ -146,7 +135,7 @@ int read(int argc, char **args) {
size_t fileSize;
auto fsBuff = loadFileBuff(fsPath, &fsSize);
if (fsBuff) {
auto fs = createFileSystem(fsBuff, fsSize);
@@ -331,33 +320,79 @@ int remove(int argc, char **args) {
return err;
}
int main(int argc, char **args) {
auto err = 0;
if (argc > 1) {
auto cmd = args[1];
if (ox_strcmp(cmd, "format") == 0) {
err = format(argc, args);
} else if (ox_strcmp(cmd, "read") == 0) {
err = read(argc, args);
} else if (ox_strcmp(cmd, "write") == 0) {
err = write(argc, args, false);
} else if (ox_strcmp(cmd, "write-expand") == 0) {
err = write(argc, args, true);
} else if (ox_strcmp(cmd, "compact") == 0) {
err = compact(argc, args);
} else if (ox_strcmp(cmd, "rm") == 0) {
err = remove(argc, args);
} else if (ox_strcmp(cmd, "help") == 0) {
printf("%s\n", usage);
} else if (ox_strcmp(cmd, "version") == 0) {
printf("oxfstool version %s\n", oxfstoolVersion);
printf("oxfs format version %d\n", FileStore16::VERSION);
int walk(int argc, char **args) {
int err = 0;
size_t fsSize;
auto fsPath = args[2];
auto fsBuff = loadFileBuff(fsPath, &fsSize);
if (fsBuff) {
auto fs = createFileSystem(fsBuff, fsSize);
if (fs) {
cout << setw(9) << "Type |";
cout << setw(10) << "Start |";
cout << setw(10) << "End |";
cout << setw(8) << "Size";
cout << endl;
cout << "-------------------------------------";
cout << endl;
fs->walk([](const char *type, uint64_t start, uint64_t end) {
cout << setw(7) << type << " |";
cout << setw(8) << start << " |";
cout << setw(8) << end << " |";
cout << setw(8) << (end - start);
cout << endl;
return 0;
});
delete fs;
} else {
printf("Command '%s' not recognized.\n", cmd);
cerr << "Invalid file system.\n";
err = 1;
}
delete []fsBuff;
} else {
printf("%s\n", usage);
err = 2;
}
return err;
}
int help(int, char**) {
cout << usage << endl;
return 0;
}
int version(int, char**) {
cout << "oxfstool version " << oxfstoolVersion << endl;
cout << "oxfs format version " << FileStore16::VERSION << endl;
return 0;
}
int main(int argc, char **args) {
auto err = 0;
map<string, int(*)(int, char**)> cmdMap = {
{ "format", format },
{ "read", read },
{ "write", [](int argc, char **args) { return write(argc, args, false); } },
{ "write-expand", [](int argc, char **args) { return write(argc, args, true); } },
{ "compact", compact },
{ "rm", remove },
{ "walk", walk },
{ "mount", mount },
{ "help", help },
{ "version", version },
};
if (argc > 1) {
auto cmd = args[1];
auto f = cmdMap[cmd];
if (f) {
err = f(argc, args);
} else {
cout << "Command '" << cmd << "' not recognized." << endl;
err = 1;
}
} else {
help(argc, args);
}
return err;
}
+107
View File
@@ -0,0 +1,107 @@
/*
* 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 <ox/std/memops.hpp>
#include <ox/std/strops.hpp>
#include "pathiterator.hpp"
namespace ox {
PathIterator::PathIterator(const char *path, size_t maxSize) {
m_path = path;
m_maxSize = maxSize;
}
/**
* @return 0 if no error
*/
int PathIterator::dirPath(char *out, size_t outSize) {
int idx = ox_lastIndexOf(m_path, '/', m_maxSize);
size_t size = idx + 1;
if (idx >= 0 && size < outSize) {
ox_memcpy(out, m_path, size);
out[size] = 0;
return 0;
} else {
return 1;
}
}
/**
* @return 0 if no error
*/
int PathIterator::fileName(char *out, size_t outSize) {
auto idx = ox_lastIndexOf(m_path, '/', m_maxSize);
if (idx >= 0) {
idx++; // pass up the preceding /
size_t fileNameSize = ox_strlen(&m_path[idx]);
if (fileNameSize < outSize) {
ox_memcpy(out, &m_path[idx], fileNameSize);
out[fileNameSize] = 0;
return 0;
} else {
return 1;
}
} else {
return 2;
}
}
// Gets the next item in the path
int PathIterator::next(char *pathOut, size_t pathOutSize) {
size_t size = 0;
int retval = 1;
if (m_iterator < m_maxSize && ox_strlen(&m_path[m_iterator])) {
retval = 0;
if (m_path[m_iterator] == '/') {
m_iterator++;
}
size_t start = m_iterator;
// end is at the next /
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
// correct end if it is invalid, which happens if there is no next /
if (!substr) {
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
}
size_t end = substr - m_path;
size = end - start;
// cannot fit the output in the output parameter
if (size >= pathOutSize) {
return -1;
}
ox_memcpy(pathOut, &m_path[start], size);
}
// truncate trailing /
if (size && pathOut[size - 1] == '/') {
size--;
}
pathOut[size] = 0; // end with null terminator
m_iterator += size;
return retval;
}
bool PathIterator::hasNext() {
size_t size = 0;
if (m_iterator < m_maxSize && ox_strlen(&m_path[m_iterator])) {
size_t start = m_iterator;
if (m_path[start] == '/') {
start++;
}
// end is at the next /
const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start);
// correct end if it is invalid, which happens if there is no next /
if (!substr) {
substr = ox_strchr(&m_path[start], 0, m_maxSize - start);
}
size_t end = substr - m_path;
size = end - start;
}
return size > 0;
}
}
+42
View File
@@ -0,0 +1,42 @@
/*
* 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 <ox/std/types.hpp>
namespace ox {
class PathIterator {
private:
const char *m_path = nullptr;
size_t m_iterator = 0;
size_t m_maxSize = 0;
public:
PathIterator(const char *path, size_t maxSize);
/**
* @return 0 if no error
*/
int dirPath(char *pathOut, size_t pathOutSize);
/**
* @return 0 if no error
*/
int fileName(char *out, size_t outSize);
/**
* @return 0 if no error
*/
int next(char *pathOut, size_t pathOutSize);
bool hasNext();
};
}
+48 -3
View File
@@ -15,10 +15,55 @@ add_executable(
filestoreio.cpp
)
target_link_libraries(FileStoreFormat OxFS OxStd)
target_link_libraries(FileSystemFormat OxFS OxStd)
target_link_libraries(FileStoreIO OxFS OxStd)
add_executable(
FSTests
tests.cpp
)
target_link_libraries(
FileStoreFormat
OxFS
OxStd
OxLog
)
target_link_libraries(
FileSystemFormat
OxFS
OxStd
OxLog
)
target_link_libraries(
FileStoreIO
OxFS
OxStd
OxLog
)
target_link_libraries(
FSTests
OxFS
OxStd
OxLog
)
add_test("FileStoreFormat" FileStoreFormat)
add_test("FileSystemFormat" FileSystemFormat)
add_test("FileStoreIO" FileStoreIO)
add_test("Test\\ PathIterator::next1" FSTests PathIterator::next1)
add_test("Test\\ PathIterator::next2" FSTests PathIterator::next2)
add_test("Test\\ PathIterator::next3" FSTests PathIterator::next3)
add_test("Test\\ PathIterator::next4" FSTests PathIterator::next4)
add_test("Test\\ PathIterator::next5" FSTests PathIterator::next5)
add_test("Test\\ PathIterator::dirPath" FSTests PathIterator::dirPath)
add_test("Test\\ PathIterator::fileName" FSTests PathIterator::fileName)
add_test("Test\\ FileSystem32::findInodeOf\\ /" FSTests "FileSystem32::findInodeOf /")
add_test("Test\\ FileSystem32::write\\(string\\)" FSTests "FileSystem32::write(string)")
add_test("Test\\ FileSystem32::rmDirectoryEntry\\(string\\)" FSTests "FileSystem32::rmDirectoryEntry(string)")
add_test("Test\\ FileSystem32::remove\\(string,\\ true\\)" FSTests "FileSystem32::remove(string, true)")
add_test("Test\\ FileSystem32::move" FSTests "FileSystem32::move")
add_test("Test\\ FileSystem32::stripDirectories" FSTests "FileSystem32::stripDirectories")
add_test("Test\\ FileSystem32::ls" FSTests "FileSystem32::ls")
+1 -1
View File
@@ -7,7 +7,7 @@
*/
#include <ox/fs/filestore.hpp>
using namespace ox::fs;
using namespace ox;
int main() {
const auto size = 65535;
+1 -2
View File
@@ -9,8 +9,7 @@
#include <ox/std/std.hpp>
#include <ox/fs/filestore.hpp>
using namespace ox::fs;
using namespace ox::std;
using namespace ox;
template<typename FileStore>
int test() {
+3 -4
View File
@@ -5,11 +5,10 @@
* 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 <ox/fs/filesystem.hpp>
#include <ox/fs/inodemgr.hpp>
using namespace ox::fs;
using namespace ox::std;
#include <ox/fs/filesystem.hpp>
using namespace ox;
template<typename FileSystem>
int test() {
+346
View File
@@ -0,0 +1,346 @@
/*
* 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 <iostream>
#include <assert.h>
#include <map>
#include <vector>
#include <string>
#include <ox/fs/filesystem.hpp>
#include <ox/fs/pathiterator.hpp>
#include <ox/std/std.hpp>
using namespace std;
using namespace ox;
map<string, int(*)(string)> tests = {
{
{
"PathIterator::next1",
[](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;
}
},
{
"PathIterator::next2",
[](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;
}
},
{
"PathIterator::next3",
[](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;
}
},
{
"PathIterator::next4",
[](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;
}
},
{
"PathIterator::next5",
[](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;
}
},
{
"PathIterator::dirPath",
[] (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.dirPath(buff, path.size()) == 0 && ox_strcmp(buff, "/usr/share/") == 0);
return retval;
}
},
{
"PathIterator::fileName",
[](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.fileName(buff, path.size()) == 0 && ox_strcmp(buff, "charset.gbag") == 0);
return retval;
}
},
{
"FileSystem32::findInodeOf /",
[](string) {
int retval = 0;
const auto size = 1024;
uint8_t buff[size];
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
auto fs = (FileSystem32*) createFileSystem(buff, size);
retval |= !(fs->findInodeOf("/") == FileSystem32::INODE_ROOT_DIR);
delete fs;
return retval;
}
},
{
"FileSystem32::write(string)",
[](string) {
int retval = 0;
auto path = "/usr/share/test.txt";
auto dataIn = "test string";
auto dataOutLen = ox_strlen(dataIn) + 1;
auto dataOut = new char[dataOutLen];
const auto size = 1024 * 1024;
auto buff = new uint8_t[size];
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
auto fs = (FileSystem32*) createFileSystem(buff, size);
retval |= fs->mkdir("/usr");
retval |= fs->mkdir("/usr/share");
retval |= fs->mkdir("/usr/lib");
retval |= fs->write(path, (void*) dataIn, ox_strlen(dataIn) + 1);
retval |= fs->read(path, dataOut, dataOutLen);
retval |= ox_strcmp(dataIn, dataOut) != 0;
delete fs;
delete []buff;
delete []dataOut;
return retval;
}
},
{
"FileSystem32::rmDirectoryEntry(string)",
[](string) {
int retval = 0;
auto path = "/usr/share/test.txt";
auto dataIn = "test string";
auto dataOutLen = ox_strlen(dataIn) + 1;
auto dataOut = new char[dataOutLen];
const auto size = 1024 * 1024 * 10;
auto buff = new uint8_t[size];
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
auto fs = (FileSystem32*) createFileSystem(buff, size);
retval |= fs->mkdir("/usr");
retval |= fs->mkdir("/usr/share");
retval |= fs->write(path, (void*) dataIn, ox_strlen(dataIn) + 1);
retval |= fs->read(path, dataOut, dataOutLen);
retval |= ox_strcmp(dataIn, dataOut) != 0;
retval |= fs->rmDirectoryEntry(path);
// the lookup should fail
retval |= fs->read(path, dataOut, dataOutLen) == 0;
delete fs;
delete []buff;
delete []dataOut;
return retval;
}
},
{
"FileSystem32::remove(string, true)",
[](string) {
int retval = 0;
auto dataIn = "test string";
auto dataOutLen = 1024 * 64;
auto dataOut = new char[dataOutLen];
vector<uint64_t> inodes;
const auto size = 1024 * 1024;
auto buff = new uint8_t[size];
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
auto fs = (FileSystem32*) createFileSystem(buff, size);
retval |= fs->mkdir("/usr");
retval |= fs->mkdir("/usr/share");
retval |= fs->write("/usr/share/test.txt", (void*) dataIn, ox_strlen(dataIn) + 1);
inodes.push_back(fs->stat("/usr").inode);
inodes.push_back(fs->stat("/usr/share").inode);
inodes.push_back(fs->stat("/usr/share/test.txt").inode);
retval |= fs->remove("/usr", true);
// the lookup should fail
for (auto inode : inodes) {
retval |= fs->read(inode, dataOut, dataOutLen) == 0;
}
delete fs;
delete []buff;
delete []dataOut;
return retval;
}
},
{
"FileSystem32::move",
[](string) {
int retval = 0;
auto dataIn = "test string";
auto dataOutLen = ox_strlen(dataIn) + 1;
auto dataOut = new char[dataOutLen];
vector<uint64_t> inodes;
const auto size = 1024 * 1024;
auto buff = new uint8_t[size];
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
auto fs = (FileSystem32*) createFileSystem(buff, size);
retval |= fs->mkdir("/usr");
retval |= fs->mkdir("/usr/share");
retval |= fs->write("/usr/share/test.txt", (void*) dataIn, ox_strlen(dataIn) + 1);
retval |= fs->move("/usr/share", "/share");
retval |= fs->read("/share/test.txt", dataOut, dataOutLen);
retval |= !(ox_strcmp(dataIn, dataOut) == 0);
delete fs;
delete []buff;
delete []dataOut;
return retval;
}
},
{
"FileSystem32::stripDirectories",
[](string) {
int retval = 0;
auto dataIn = "test string";
auto dataOutLen = ox_strlen(dataIn) + 1;
auto dataOut = new char[dataOutLen];
vector<uint64_t> inodes;
const auto size = 1024 * 1024;
auto buff = new uint8_t[size];
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
auto fs = (FileSystem32*) createFileSystem(buff, size);
retval |= fs->mkdir("/usr");
retval |= fs->mkdir("/usr/share");
retval |= fs->write("/usr/share/test.txt", (void*) dataIn, ox_strlen(dataIn) + 1);
auto inode = fs->stat("/usr/share/test.txt").inode;
retval |= fs->stripDirectories();
// make sure normal file is still there and the directories are gone
retval |= fs->read(inode, dataOut, dataOutLen);
retval |= !(ox_strcmp(dataIn, dataOut) == 0);
retval |= !(fs->stat("/usr").inode == 0);
retval |= !(fs->stat("/usr/share").inode == 0);
delete fs;
delete []buff;
delete []dataOut;
return retval;
}
},
{
"FileSystem32::ls",
[](string) {
int retval = 0;
auto dataIn = "test string";
auto dataOutLen = ox_strlen(dataIn) + 1;
auto dataOut = new char[dataOutLen];
vector<uint64_t> inodes;
vector<DirectoryListing<string>> files;
const auto size = 1024 * 1024;
auto buff = new uint8_t[size];
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
auto fs = (FileSystem32*) createFileSystem(buff, size);
retval |= fs->mkdir("/usr");
retval |= fs->mkdir("/usr/share");
retval |= fs->write("/usr/share/a.txt", (void*) dataIn, ox_strlen(dataIn) + 1);
retval |= fs->write("/usr/share/b.txt", (void*) dataIn, ox_strlen(dataIn) + 1);
retval |= fs->write("/usr/share/c.txt", (void*) dataIn, ox_strlen(dataIn) + 1);
fs->ls("/usr/share/", &files);
retval |= !(files[0].name == ".");
retval |= !(files[1].name == "..");
retval |= !(files[2].name == "a.txt");
retval |= !(files[3].name == "b.txt");
retval |= !(files[4].name == "c.txt");
delete fs;
delete []buff;
delete []dataOut;
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;
}
+33
View File
@@ -0,0 +1,33 @@
/*
* 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 <iostream>
#include <string.h>
#include "toollib.hpp"
uint8_t *loadFileBuff(FILE *file, ::size_t *sizeOut) {
if (file) {
fseek(file, 0, SEEK_END);
const auto size = ftell(file);
rewind(file);
auto buff = new uint8_t[size];
auto itemsRead = fread(buff, size, 1, file);
fclose(file);
if (sizeOut) {
*sizeOut = itemsRead ? size : 0;
}
return buff;
} else {
return nullptr;
}
}
uint8_t *loadFileBuff(const char *path, ::size_t *sizeOut) {
return loadFileBuff(fopen(path, "rb"), sizeOut);
}
+14
View File
@@ -0,0 +1,14 @@
/*
* 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 <stdio.h>
#include <stdlib.h>
uint8_t *loadFileBuff(FILE *file, size_t *sizeOut = nullptr);
uint8_t *loadFileBuff(const char *path, size_t *sizeOut = nullptr);
+25
View File
@@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 2.8)
add_library(
OxLog
log.cpp
)
set_property(
TARGET
OxLog
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
install(
FILES
log.hpp
DESTINATION
include/ox/mc
)
install(TARGETS OxLog
LIBRARY DESTINATION lib/ox
ARCHIVE DESTINATION lib/ox
)
+105
View File
@@ -0,0 +1,105 @@
/*
* 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 <stdarg.h>
#include <stdio.h>
#include "log.hpp"
namespace ox {
class Logger {
private:
// void* stand-in for FILE*
const char *m_path = nullptr;
public:
Logger(const char *path = nullptr);
~Logger();
void log(LogLevel_t level, const char *msg, va_list args);
void info(const char *msg, ...);
void debug(const char *msg, ...);
void error(const char *msg, ...);
};
Logger::Logger(const char *path) {
m_path = path;
}
Logger::~Logger() {
}
void Logger::log(LogLevel_t level, const char *msg, va_list args) {
if (m_path) {
auto file = fopen(m_path, "a");
vfprintf(file, msg, args);
fprintf(file, "\n");
fclose(file);
}
}
void Logger::info(const char *msg, ...) {
va_list args;
va_start(args, msg);
log(LogLevel_t::Info, msg, args);
va_end(args);
}
void Logger::debug(const char *msg, ...) {
va_list args;
va_start(args, msg);
log(LogLevel_t::Debug, msg, args);
va_end(args);
}
void Logger::error(const char *msg, ...) {
va_list args;
va_start(args, msg);
log(LogLevel_t::Error, msg, args);
va_end(args);
}
static Logger logger;
void logFile(const char *path) {
logger = Logger(path);
}
void log(LogLevel_t level, const char *msg, va_list args) {
logger.log(level, msg, args);
}
void info(const char *msg, ...) {
va_list args;
va_start(args, msg);
log(LogLevel_t::Info, msg, args);
va_end(args);
}
void debug(const char *msg, ...) {
va_list args;
va_start(args, msg);
log(LogLevel_t::Debug, msg, args);
va_end(args);
}
void error(const char *msg, ...) {
va_list args;
va_start(args, msg);
log(LogLevel_t::Error, msg, args);
va_end(args);
}
}
+27
View File
@@ -0,0 +1,27 @@
/*
* 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
namespace ox {
enum class LogLevel_t: int {
Info,
Debug,
Error,
};
void logFile(const char *path);
void info(const char *msg, ...);
void debug(const char *msg, ...);
void error(const char *msg, ...);
}
+34
View File
@@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 2.8)
add_library(
OxMetalClaw
presencemask.cpp
read.cpp
write.cpp
)
set_property(
TARGET
OxMetalClaw
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
install(
FILES
err.hpp
presencemask.hpp
read.hpp
write.hpp
DESTINATION
include/ox/mc
)
install(TARGETS OxMetalClaw
LIBRARY DESTINATION lib/ox
ARCHIVE DESTINATION lib/ox
)
if(OX_RUN_TESTS STREQUAL "ON")
add_subdirectory(test)
endif()
+19
View File
@@ -0,0 +1,19 @@
/*
* 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
namespace ox {
enum {
MC_PRESENCEMASKOUTBOUNDS = 1,
MC_BUFFENDED = 2,
MC_OUTBUFFENDED = 4
};
}
+12
View File
@@ -0,0 +1,12 @@
/*
* 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 "read.hpp"
#include "write.hpp"
+49
View File
@@ -0,0 +1,49 @@
/*
* 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 <ox/std/byteswap.hpp>
#include "err.hpp"
#include "presencemask.hpp"
namespace ox {
FieldPresenseMask::FieldPresenseMask(uint8_t *mask, size_t maxLen) {
m_mask = mask;
m_maxLen = maxLen;
}
bool FieldPresenseMask::get(int i) {
if (i / 8 < m_maxLen) {
return (m_mask[i / 8] >> (i % 8)) & 1;
} else {
return MC_PRESENCEMASKOUTBOUNDS;
}
}
int FieldPresenseMask::set(int i, bool on) {
if (i / 8 < m_maxLen) {
if (on) {
m_mask[i / 8] |= 1 << (i % 8);
} else {
m_mask[i / 8] &= ~(1 << (i % 8));
}
return 0;
} else {
return MC_PRESENCEMASKOUTBOUNDS;
}
}
void FieldPresenseMask::setMaxLen(int maxLen) {
m_maxLen = maxLen;
}
int FieldPresenseMask::getMaxLen() {
return m_maxLen;
}
}
+32
View File
@@ -0,0 +1,32 @@
/*
* 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 <ox/std/types.hpp>
namespace ox {
class FieldPresenseMask {
private:
uint8_t *m_mask;
int m_maxLen = 0;
public:
FieldPresenseMask(uint8_t *mask, size_t maxLen);
bool get(int i);
int set(int i, bool on);
void setMaxLen(int);
int getMaxLen();
};
}
+55
View File
@@ -0,0 +1,55 @@
/*
* 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 <ox/std/byteswap.hpp>
#include <ox/std/memops.hpp>
#include "read.hpp"
namespace ox {
MetalClawReader::MetalClawReader(uint8_t *buff, size_t buffLen): m_fieldPresence(buff, buffLen) {
m_buff = buff;
m_buffLen = buffLen;
}
int MetalClawReader::op(const char*, int16_t *val) {
return readInteger(val);
}
int MetalClawReader::op(const char*, int32_t *val) {
return readInteger(val);
}
int MetalClawReader::op(const char*, int64_t *val) {
return readInteger(val);
}
int MetalClawReader::op(const char*, uint16_t *val) {
return readInteger(val);
}
int MetalClawReader::op(const char*, uint32_t *val) {
return readInteger(val);
}
int MetalClawReader::op(const char*, uint64_t *val) {
return readInteger(val);
}
int MetalClawReader::op(const char*, bool *val) {
*val = m_fieldPresence.get(m_field++);
return 0;
}
void MetalClawReader::setFields(int fields) {
m_fields = fields;
m_buffIt = (fields / 8 + 1) - (fields % 8 == 0);
m_fieldPresence.setMaxLen(m_buffIt);
}
}
+154
View File
@@ -0,0 +1,154 @@
/*
* 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 <ox/std/byteswap.hpp>
#include <ox/std/string.hpp>
#include "err.hpp"
#include "presencemask.hpp"
namespace ox {
class MetalClawReader {
private:
FieldPresenseMask m_fieldPresence;
int m_fields = 0;
int m_field = 0;
size_t m_buffIt = 0;
size_t m_buffLen = 0;
uint8_t *m_buff = nullptr;
public:
MetalClawReader(uint8_t *buff, size_t buffLen);
int op(const char*, int16_t *val);
int op(const char*, int32_t *val);
int op(const char*, int64_t *val);
int op(const char*, uint16_t *val);
int op(const char*, uint32_t *val);
int op(const char*, uint64_t *val);
int op(const char*, bool *val);
template<typename T>
int op(const char*, T *val, size_t len);
template<typename T>
int op(const char*, T *val);
template<size_t L>
int op(const char*, ox::bstring<L> *val);
void setFields(int fields);
private:
template<typename I>
int readInteger(I *val);
};
template<typename T>
int MetalClawReader::op(const char*, T *val) {
int err = 0;
if (m_fieldPresence.get(m_field)) {
MetalClawReader reader(m_buff + m_buffIt, m_buffLen - m_buffIt);
err |= ioOp(&reader, val);
m_buffIt += reader.m_buffIt;
}
m_field++;
return err;
};
template<size_t L>
int MetalClawReader::op(const char*, ox::bstring<L> *val) {
int err = 0;
if (m_fieldPresence.get(m_field)) {
// read the length
typedef uint32_t StringLength;
size_t size = 0;
if (m_buffIt + sizeof(StringLength) < m_buffLen) {
size = ox::bigEndianAdapt(*((StringLength*) &m_buff[m_buffIt]));
m_buffIt += sizeof(StringLength);
} else {
err |= MC_BUFFENDED;
}
// read the string
if (val->cap() >= size) {
if (m_buffIt + size < m_buffLen) {
ox_memcpy(val, &m_buff[m_buffIt], size);
m_buffIt += size;
} else {
err |= MC_BUFFENDED;
}
} else {
err |= MC_OUTBUFFENDED;
}
} else {
*val = "";
}
m_field++;
return err;
};
template<typename I>
int MetalClawReader::readInteger(I *val) {
int err = 0;
if (m_fieldPresence.get(m_field)) {
if (m_buffIt + sizeof(I) < m_buffLen) {
*val = ox::bigEndianAdapt(*((I*) &m_buff[m_buffIt]));
m_buffIt += sizeof(I);
} else {
err = MC_BUFFENDED;
}
} else {
*val = 0;
}
m_field++;
return err;
};
template<typename T>
int MetalClawReader::op(const char*, T *val, size_t valLen) {
int err = 0;
if (m_fieldPresence.get(m_field)) {
// read the length
typedef uint32_t ArrayLength;
size_t len = 0;
if (m_buffIt + sizeof(ArrayLength) < m_buffLen) {
len = ox::bigEndianAdapt(*((T*) &m_buff[m_buffIt]));
m_buffIt += sizeof(ArrayLength);
} else {
err = MC_BUFFENDED;
}
// read the list
if (valLen >= len) {
MetalClawReader reader(m_buff + m_buffIt, m_buffLen - m_buffIt);
reader.setFields(len);
for (size_t i = 0; i < len; i++) {
err |= reader.op("", &val[i]);
}
m_buffIt += reader.m_buffIt;
} else {
err = MC_OUTBUFFENDED;
}
}
m_field++;
return err;
};
template<typename T>
int read(uint8_t *buff, size_t buffLen, T *val) {
MetalClawReader reader(buff, buffLen);
return ioOp(&reader, val);
}
}
+16
View File
@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 2.8)
add_executable(
McTest
tests.cpp
)
target_link_libraries(
McTest
OxMetalClaw
OxStd
OxLog
)
add_test("Test\\ McTest\\ Writer" McTest MetalClawWriter)
add_test("Test\\ McTest\\ Reader" McTest MetalClawReader)
+158
View File
@@ -0,0 +1,158 @@
/*
* 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 <iostream>
#include <assert.h>
#include <map>
#include <vector>
#include <string>
#include <ox/mc/mc.hpp>
#include <ox/std/std.hpp>
using namespace std;
using namespace ox;
struct TestStructNest {
bool Bool = false;
uint32_t Int = 0;
bstring<32> String = "";
};
struct TestStruct {
bool Bool = false;
int32_t Int = 0;
int32_t Int1 = 0;
int32_t Int2 = 0;
int32_t Int3 = 0;
int32_t Int4 = 0;
int32_t Int5 = 0;
int32_t Int6 = 0;
int32_t Int7 = 0;
int32_t Int8 = 0;
bstring<32> String = "";
uint32_t List[4] = {0, 0, 0 , 0};
TestStructNest EmptyStruct;
TestStructNest Struct;
};
template<typename T>
int ioOp(T *io, TestStructNest *obj) {
int32_t err = 0;
io->setFields(3);
err |= io->op("Bool", &obj->Bool);
err |= io->op("Int", &obj->Int);
err |= io->op("String", &obj->String);
return err;
}
template<typename T>
int ioOp(T *io, TestStruct *obj) {
int err = 0;
io->setFields(13);
err |= io->op("Bool", &obj->Bool);
err |= io->op("Int", &obj->Int);
err |= io->op("Int1", &obj->Int1);
err |= io->op("Int2", &obj->Int2);
err |= io->op("Int3", &obj->Int3);
err |= io->op("Int4", &obj->Int4);
err |= io->op("Int5", &obj->Int5);
err |= io->op("Int6", &obj->Int6);
err |= io->op("Int7", &obj->Int7);
err |= io->op("Int8", &obj->Int8);
err |= io->op("String", &obj->String);
err |= io->op("List", obj->List, 4);
err |= io->op("EmptyStruct", &obj->EmptyStruct);
err |= io->op("Struct", &obj->Struct);
return err;
}
map<string, int(*)(string)> tests = {
{
{
"MetalClawWriter",
[](string) {
// This test doesn't confirm much, but it does show that the writer
// doesn't segfault
size_t buffLen = 1024;
auto buff = new uint8_t[buffLen];
int err = 0;
TestStruct ts;
err |= write(buff, buffLen, &ts);
delete []buff;
return err;
}
},
{
"MetalClawReader",
[](string) {
int err = 0;
size_t buffLen = 1024;
auto buff = new uint8_t[buffLen];
TestStruct testIn, testOut;
testIn.Bool = true;
testIn.Int = 42;
testIn.String = "Test String 1";
testIn.List[0] = 1;
testIn.List[1] = 2;
testIn.List[2] = 3;
testIn.List[3] = 4;
testIn.Struct.Bool = false;
testIn.Struct.Int = 300;
testIn.Struct.String = "Test String 2";
err |= write(buff, buffLen, &testIn);
err |= read(buff, buffLen, &testOut);
err |= !(testIn.Bool == testOut.Bool);
err |= !(testIn.Int == testOut.Int);
err |= !(testIn.Int1 == testOut.Int1);
err |= !(testIn.Int2 == testOut.Int2);
err |= !(testIn.Int3 == testOut.Int3);
err |= !(testIn.Int4 == testOut.Int4);
err |= !(testIn.Int5 == testOut.Int5);
err |= !(testIn.Int6 == testOut.Int6);
err |= !(testIn.Int7 == testOut.Int7);
err |= !(testIn.Int8 == testOut.Int8);
err |= !(testIn.String == testOut.String);
err |= !(testIn.List[0] == testOut.List[0]);
err |= !(testIn.List[1] == testOut.List[1]);
err |= !(testIn.List[2] == testOut.List[2]);
err |= !(testIn.List[3] == testOut.List[3]);
err |= !(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool);
err |= !(testIn.EmptyStruct.Int == testOut.EmptyStruct.Int);
err |= !(testIn.EmptyStruct.String == testOut.EmptyStruct.String);
err |= !(testIn.Struct.Int == testOut.Struct.Int);
err |= !(testIn.Struct.String == testOut.Struct.String);
err |= !(testIn.Struct.Bool == testOut.Struct.Bool);
delete []buff;
return err;
}
},
}
};
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;
}
+54
View File
@@ -0,0 +1,54 @@
/*
* 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 <ox/std/byteswap.hpp>
#include <ox/std/memops.hpp>
#include "write.hpp"
namespace ox {
MetalClawWriter::MetalClawWriter(uint8_t *buff, size_t buffLen): m_fieldPresence(buff, buffLen) {
m_buff = buff;
m_buffLen = buffLen;
}
int MetalClawWriter::op(const char*, int16_t *val) {
return appendInteger(*val);
}
int MetalClawWriter::op(const char*, int32_t *val) {
return appendInteger(*val);
}
int MetalClawWriter::op(const char*, int64_t *val) {
return appendInteger(*val);
}
int MetalClawWriter::op(const char*, uint16_t *val) {
return appendInteger(*val);
}
int MetalClawWriter::op(const char*, uint32_t *val) {
return appendInteger(*val);
}
int MetalClawWriter::op(const char*, uint64_t *val) {
return appendInteger(*val);
}
int MetalClawWriter::op(const char*, bool *val) {
return m_fieldPresence.set(m_field++, *val);
}
void MetalClawWriter::setFields(int fields) {
m_fields = fields;
m_buffIt = (fields / 8 + 1) - (fields % 8 == 0);
m_fieldPresence.setMaxLen(m_buffIt);
}
}
+152
View File
@@ -0,0 +1,152 @@
/*
* 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 <ox/std/string.hpp>
#include <ox/std/types.hpp>
#include "err.hpp"
#include "presencemask.hpp"
namespace ox {
class MetalClawWriter {
private:
FieldPresenseMask m_fieldPresence;
int m_fields = 0;
int m_field = 0;
size_t m_buffIt = 0;
size_t m_buffLen = 0;
uint8_t *m_buff = nullptr;
public:
MetalClawWriter(uint8_t *buff, size_t buffLen);
int op(const char*, int16_t *val);
int op(const char*, int32_t *val);
int op(const char*, int64_t *val);
int op(const char*, uint16_t *val);
int op(const char*, uint32_t *val);
int op(const char*, uint64_t *val);
int op(const char*, bool *val);
template<typename T>
int op(const char*, T *val, size_t len);
template<size_t L>
int op(const char*, ox::bstring<L> *val);
template<typename T>
int op(const char*, T *val);
void setFields(int fields);
private:
template<typename I>
int appendInteger(I val);
};
template<size_t L>
int MetalClawWriter::op(const char*, ox::bstring<L> *val) {
int err = 0;
bool fieldSet = false;
if (val->len()) {
// write the length
typedef uint32_t StringLength;
if (m_buffIt + sizeof(StringLength) + val->size() < m_buffLen) {
*((StringLength*) &m_buff[m_buffIt]) = ox::bigEndianAdapt((StringLength) val->size());
m_buffIt += sizeof(StringLength);
// write the string
ox_memcpy(&m_buff[m_buffIt], val, val->size());
m_buffIt += val->size();
fieldSet = true;
} else {
err = MC_BUFFENDED;
}
}
err |= m_fieldPresence.set(m_field, fieldSet);
m_field++;
return err;
};
template<typename T>
int MetalClawWriter::op(const char*, T *val) {
int err = 0;
bool fieldSet = false;
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
err |= ioOp(&writer, val);
if ((size_t) writer.m_fieldPresence.getMaxLen() < writer.m_buffIt) {
m_buffIt += writer.m_buffIt;
fieldSet = true;
}
err |= m_fieldPresence.set(m_field, fieldSet);
m_field++;
return err;
};
template<typename I>
int MetalClawWriter::appendInteger(I val) {
int err = 0;
bool fieldSet = false;
if (val) {
if (m_buffIt + sizeof(I) < m_buffLen) {
*((I*) &m_buff[m_buffIt]) = ox::bigEndianAdapt(val);
fieldSet = true;
m_buffIt += sizeof(I);
} else {
err |= MC_BUFFENDED;
}
}
err |= m_fieldPresence.set(m_field, fieldSet);
m_field++;
return err;
};
template<typename T>
int MetalClawWriter::op(const char*, T *val, size_t len) {
int err = 0;
bool fieldSet = false;
if (len) {
// write the length
typedef uint32_t ArrayLength;
if (m_buffIt + sizeof(ArrayLength) < m_buffLen) {
*((T*) &m_buff[m_buffIt]) = ox::bigEndianAdapt((ArrayLength) len);
m_buffIt += sizeof(ArrayLength);
} else {
err = MC_BUFFENDED;
}
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
writer.setFields(len);
// write the array
for (size_t i = 0; i < len; i++) {
err |= writer.op("", &val[i]);
}
m_buffIt += writer.m_buffIt;
fieldSet = true;
}
err |= m_fieldPresence.set(m_field, fieldSet);
m_field++;
return err;
};
template<typename T>
int write(uint8_t *buff, size_t buffLen, T *val) {
MetalClawWriter writer(buff, buffLen);
return ioOp(&writer, val);
}
}
+11 -1
View File
@@ -2,15 +2,25 @@ cmake_minimum_required(VERSION 2.8)
add_library(
OxStd
byteswap.cpp
memops.cpp
random.cpp
strops.cpp
)
set_property(
TARGET
OxStd
PROPERTY
POSITION_INDEPENDENT_CODE ON
)
install(
FILES
bitops.hpp
byteswap.hpp
memops.hpp
random.hpp
string.hpp
strops.hpp
std.hpp
types.hpp
+19
View File
@@ -0,0 +1,19 @@
/*
* 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 "types.hpp"
namespace ox {
inline uint64_t rotateLeft(uint64_t i, int shift) {
return (i << shift) | (i >> (64 - shift));
}
}
+62 -3
View File
@@ -11,8 +11,28 @@
#include "types.hpp"
namespace ox {
namespace std {
inline int16_t byteSwap(int16_t i) {
return (i << 8) | (i >> 8);
}
inline int32_t byteSwap(int32_t i) {
return ((i >> 24) & 0x000000ff) |
((i >> 8) & 0x0000ff00) |
((i << 8) & 0x00ff0000) |
((i << 24) & 0xff000000);
}
inline int64_t byteSwap(int64_t i) {
return ((i >> 56) & 0x00000000000000ff) |
((i >> 40) & 0x000000000000ff00) |
((i >> 24) & 0x0000000000ff0000) |
((i >> 8) & 0x00000000ff000000) |
((i << 8) & 0x000000ff00000000) |
((i << 24) & 0x0000ff0000000000) |
((i << 40) & 0x00ff000000000000) |
((i << 56) & 0xff00000000000000);
}
inline uint16_t byteSwap(uint16_t i) {
return (i << 8) | (i >> 8);
@@ -37,6 +57,47 @@ inline uint64_t byteSwap(uint64_t i) {
}
/**
* Takes an int and byte swaps if the platform is big endian.
*/
inline int8_t bigEndianAdapt(int8_t i) {
return i;
}
/**
* Takes an int and byte swaps if the platform is big endian.
*/
inline int16_t bigEndianAdapt(int16_t i) {
#ifdef __BIG_ENDIAN__
return byteSwap(i);
#else
return i;
#endif
}
/**
* Takes an int and byte swaps if the platform is big endian.
*/
inline int32_t bigEndianAdapt(int32_t i) {
#ifdef __BIG_ENDIAN__
return byteSwap(i);
#else
return i;
#endif
}
/**
* Takes an int and byte swaps if the platform is big endian.
*/
inline int64_t bigEndianAdapt(int64_t i) {
#ifdef __BIG_ENDIAN__
return byteSwap(i);
#else
return i;
#endif
}
/**
* Takes an int and byte swaps if the platform is big endian.
*/
@@ -77,6 +138,4 @@ inline uint64_t bigEndianAdapt(uint64_t i) {
#endif
}
}
}
+40
View File
@@ -0,0 +1,40 @@
/*
* 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 "bitops.hpp"
#include "random.hpp"
namespace ox {
RandomSeed Random::DEFAULT_SEED = {540932923848, 540932540932};
Random::Random(RandomSeed seed) {
m_seed[0] = seed[0];
m_seed[1] = seed[1];
}
uint64_t Random::gen() {
// An implementation of the Xoroshiro128+ algorithm
auto s0 = m_seed[0];
auto s1 = m_seed[1];
auto retval = s0 + s1;
s1 ^= s0;
m_seed[0] = ox::rotateLeft(s0, 55) ^ s1 ^ (s1 << 14);
m_seed[1] = ox::rotateLeft(s1, 36);
return retval;
}
}
uint64_t ox_rand() {
static ox::Random rand;
return rand.gen();
}
+30
View File
@@ -0,0 +1,30 @@
/*
* 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
uint64_t ox_rand();
namespace ox {
typedef uint64_t RandomSeed[2];
class Random {
public:
static RandomSeed DEFAULT_SEED;
private:
RandomSeed m_seed;
public:
Random(RandomSeed seed = DEFAULT_SEED);
uint64_t gen();
};
}
+3
View File
@@ -7,7 +7,10 @@
*/
#pragma once
#include "bitops.hpp"
#include "byteswap.hpp"
#include "memops.hpp"
#include "random.hpp"
#include "strops.hpp"
#include "string.hpp"
#include "types.hpp"
+128
View File
@@ -0,0 +1,128 @@
/*
* 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 "memops.hpp"
#include "strops.hpp"
#include "types.hpp"
namespace ox {
// Bounded String
template<size_t buffLen>
class bstring {
private:
uint8_t m_buff[buffLen];
public:
bstring();
bstring(const char *str);
const bstring &operator=(const char *str);
const bstring &operator=(char *str);
bool operator==(const bstring &other);
char *data();
/**
* Returns the number of characters in this string.
*/
size_t len();
/**
* Returns the number of bytes used for this string.
*/
size_t size();
/**
* Returns the capacity of bytes for this string.
*/
size_t cap();
};
template<size_t size>
bstring<size>::bstring() {
m_buff[0] = 0;
}
template<size_t size>
bstring<size>::bstring(const char *str) {
*this = str;
}
template<size_t size>
const bstring<size> &bstring<size>::operator=(const char *str) {
size_t strLen = ox_strlen(str) + 1;
if (cap() < strLen) {
strLen = cap();
}
ox_memcpy(m_buff, str, strLen);
// make sure last element is a null terminator
m_buff[cap() - 1] = 0;
return *this;
}
template<size_t size>
const bstring<size> &bstring<size>::operator=(char *str) {
return *this = (const char*) str;
}
template<size_t buffLen>
bool bstring<buffLen>::operator==(const bstring<buffLen> &other) {
bool retval = true;
size_t i = 0;
while (i < buffLen && (m_buff[i] || other.m_buff[i])) {
if (m_buff[i] != other.m_buff[i]) {
retval = false;
break;
}
i++;
}
return retval;
}
template<size_t buffLen>
char *bstring<buffLen>::data() {
return (char*) m_buff;
}
template<size_t buffLen>
size_t bstring<buffLen>::len() {
size_t length = 0;
for (size_t i = 0; i < buffLen; i++) {
uint8_t b = m_buff[i];
if (b) {
if ((b & 128) == 0) { // normal ASCII character
length++;
} else if ((b & (256 << 6)) == (256 << 6)) { // start of UTF-8 character
length++;
}
} else {
break;
}
}
return length;
}
template<size_t buffLen>
size_t bstring<buffLen>::size() {
size_t i;
for (i = 0; i < buffLen && m_buff[i]; i++);
return i + 1; // add one for null terminator
}
template<size_t buffLen>
size_t bstring<buffLen>::cap() {
return buffLen;
}
}
+50 -2
View File
@@ -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,54 @@ int ox_strlen(const char *str1) {
return len;
}
int ox_strlen(char *str1) {
int len;
for (len = 0; str1[len]; len++);
return len;
}
const char *ox_strchr(const char *str, int character, size_t maxLen) {
for (size_t i = 0; i <= maxLen; i++) {
if (str[i] == character) {
return &str[i];
} else if (str[i] == 0) {
return nullptr;
}
}
return nullptr;
}
char *ox_strchr(char *str, int character, size_t maxLen) {
for (size_t i = 0; i < maxLen; i++) {
if (str[i] == character) {
return &str[i];
} else if (str[i] == 0) {
return nullptr;
}
}
return nullptr;
}
int ox_lastIndexOf(const char *str, int character, int maxLen) {
int retval = -1;
for (int i = 0; i < maxLen && str[i]; i++) {
if (str[i] == character) {
retval = i;
}
}
return retval;
}
int ox_lastIndexOf(char *str, int character, int maxLen) {
int retval = -1;
for (int i = 0; i < maxLen && str[i]; i++) {
if (str[i] == character) {
retval = i;
}
}
return retval;
}
int ox_atoi(const char *str) {
int total = 0;
int multiplier = 1;
+11
View File
@@ -5,6 +5,7 @@
* 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 "types.hpp"
@@ -13,4 +14,14 @@ int ox_strcmp(const char *str1, const char *str2);
int ox_strlen(const char *str1);
int ox_strlen(char *str1);
const char *ox_strchr(const char *str, int character, size_t maxLen = 0xFFFFFFFF);
char *ox_strchr(char *str, int character, size_t maxLen = 0xFFFFFFFF);
int ox_lastIndexOf(const char *str, int character, int maxLen = 0xFFFFFFFF);
int ox_lastIndexOf(char *str, int character, int maxLen = 0xFFFFFFFF);
int ox_atoi(const char *str);
+14 -3
View File
@@ -5,7 +5,7 @@ add_executable(
tests.cpp
)
target_link_libraries(StdTest OxStd)
target_link_libraries(StdTest OxLog OxStd)
add_test("Test\\ ox_memcmp\\ ABCDEFG\\ !=\\ HIJKLMN" StdTest "ABCDEFG != HIJKLMN")
add_test("Test\\ ox_memcmp\\ HIJKLMN\\ !=\\ ABCDEFG" StdTest "HIJKLMN != ABCDEFG")
@@ -21,13 +21,20 @@ add_executable(
strops_test.cpp
)
target_link_libraries(StrOpsTest OxStd)
target_link_libraries(
StrOpsTest
OxStd
OxLog
)
add_test("Test\\ ox_strcmp\\ asdf\\ !=\\ hijk" StrOpsTest "asdf < hijk")
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\\ ''\\ ==\\ ''" StrOpsTest " == ")
add_test("Test\\ ox_strchr\\ 0" StrOpsTest "ox_strchr 0")
add_test("Test\\ ox_lastIndexOf\\ aaaa\\ a" StrOpsTest "ox_lastIndexOf aaaa a")
################################################################################
@@ -38,7 +45,11 @@ add_executable(
byteswap_test.cpp
)
target_link_libraries(ByteSwapTest OxStd)
target_link_libraries(
ByteSwapTest
OxStd
OxLog
)
add_test("Test\\ bigEndianAdapt\\ 0x00ff" ByteSwapTest bigEndianAdapt<uint16_t> 0x00ff)
add_test("Test\\ bigEndianAdapt\\ 0xff00" ByteSwapTest bigEndianAdapt<uint16_t> 0xff00)
+1 -1
View File
@@ -10,7 +10,7 @@
#include <ox/std/std.hpp>
using namespace std;
using namespace ox::std;
using namespace ox;
template<typename T>
int testBigEndianAdapt(string str) {
+23
View File
@@ -43,6 +43,29 @@ map<string, function<int()>> tests = {
return !(ox_strcmp("resize", "resize") == 0);
}
},
{
" == ",
[]() {
return !(ox_strcmp("", "") == 0);
}
},
{
"ox_strchr 0",
[]() {
auto testStr = "asdf";
return !(ox_strchr(testStr, 0, 4) == &testStr[4]);
}
},
{
"ox_lastIndexOf aaaa a",
[]() {
int retval = 0;
auto testStr = "aaaa";
retval |= !(ox_lastIndexOf((char*) testStr, 'a', ox_strlen(testStr)) == 3);
retval |= !(ox_lastIndexOf((const char*) testStr, 'a', ox_strlen(testStr)) == 3);
return retval;
}
},
};
int main(int argc, const char **args) {
+1
View File
@@ -5,6 +5,7 @@
* 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
typedef signed char int8_t;