diff --git a/src/dawn/CMakeLists.txt b/src/dawn/CMakeLists.txt index 2d87c2fe..ba848087 100644 --- a/src/dawn/CMakeLists.txt +++ b/src/dawn/CMakeLists.txt @@ -42,4 +42,7 @@ target_compile_definitions(${DAWN_TARGET_NAME} PUBLIC ${DAWN_SHARED_DEFINITIONS} DAWN_DEBUG_BUILD=${DAWN_DEBUG_BUILD} -) \ No newline at end of file +) + +# Common Prefabs +tool_prefab("prefabs/ui/debug/FPSLabel.xml") \ No newline at end of file diff --git a/src/dawn/prefabs/FPSLabel.hpp b/src/dawn/prefabs/FPSLabel.hpp deleted file mode 100644 index c71acf8a..00000000 --- a/src/dawn/prefabs/FPSLabel.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2023 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -#pragma once -#include "prefab/SceneItemPrefab.hpp" -#include "scene/components/ui/UILabel.hpp" - -namespace Dawn { - class FPSLabel : public SceneItemPrefab, public StateOwner { - public: - static std::vector prefabAssets(AssetManager *man) { - return {}; - } - - UILabel *label; - - FPSLabel(Scene *s, sceneitemid_t i) : SceneItemPrefab(s, i) {} - - void prefabInit(AssetManager *man) override { - label = this->addComponent(); - label->text = "No Frame"; - - useEvent([&](float_t delta){ - std::string strFps = std::to_string((int32_t)(1.0f / delta)); - std::string strTick = std::to_string((int32_t)(delta * 1000.0f)); - label->text = strFps + "FPS (" + strTick + "ms)"; - }, scene->eventSceneUnpausedUpdate); - } - }; -} \ No newline at end of file diff --git a/src/dawn/scene/components/CMakeLists.txt b/src/dawn/scene/components/CMakeLists.txt index 1084ec7f..3622cb01 100644 --- a/src/dawn/scene/components/CMakeLists.txt +++ b/src/dawn/scene/components/CMakeLists.txt @@ -4,6 +4,7 @@ # https://opensource.org/licenses/MIT # Subdirs +add_subdirectory(debug) add_subdirectory(display) add_subdirectory(example) add_subdirectory(physics) diff --git a/src/dawn/scene/components/debug/CMakeLists.txt b/src/dawn/scene/components/debug/CMakeLists.txt new file mode 100644 index 00000000..7fa2b055 --- /dev/null +++ b/src/dawn/scene/components/debug/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DAWN_TARGET_NAME} + PRIVATE + FPSLabelComponent.cpp +) \ No newline at end of file diff --git a/src/dawn/scene/components/debug/FPSLabelComponent.cpp b/src/dawn/scene/components/debug/FPSLabelComponent.cpp new file mode 100644 index 00000000..9b882ff8 --- /dev/null +++ b/src/dawn/scene/components/debug/FPSLabelComponent.cpp @@ -0,0 +1,23 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "FPSLabelComponent.hpp" + +using namespace Dawn; + +FPSLabelComponent::FPSLabelComponent(SceneItem *item) : + SceneItemComponent(item) +{ + +} + +void FPSLabelComponent::onStart() { + useEvent([&](float_t delta){ + if(this->label == nullptr) return; + std::string strFps = std::to_string((int32_t)(1.0f / delta)); + std::string strTick = std::to_string((int32_t)(delta * 1000.0f)); + label->text = strFps + "FPS (" + strTick + "ms)"; + }, this->item->scene->eventSceneUnpausedUpdate); +} \ No newline at end of file diff --git a/src/dawn/scene/components/debug/FPSLabelComponent.hpp b/src/dawn/scene/components/debug/FPSLabelComponent.hpp new file mode 100644 index 00000000..04ef2825 --- /dev/null +++ b/src/dawn/scene/components/debug/FPSLabelComponent.hpp @@ -0,0 +1,16 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "scene/components/ui/UILabel.hpp" + +namespace Dawn { + class FPSLabelComponent : public SceneItemComponent { + public: + UILabel *label; + FPSLabelComponent(SceneItem *item); + void onStart() override; + }; +} \ No newline at end of file diff --git a/src/dawn/scene/components/ui/UILabel.hpp b/src/dawn/scene/components/ui/UILabel.hpp index 5964dc64..3d7fff4a 100644 --- a/src/dawn/scene/components/ui/UILabel.hpp +++ b/src/dawn/scene/components/ui/UILabel.hpp @@ -29,11 +29,17 @@ namespace Dawn { void updateMesh(); public: + //@optional StateProperty text; + // @optional StateProperty fontSize; + /* @optional */ StateProperty font; + /* @optional */ StateProperty maxWidth; + /* @optional */ struct Color textColor = COLOR_WHITE; + struct FontMeasure measure; int32_t startQuad = 0; int32_t quadCount = -1; diff --git a/src/dawnhelloworld/scenes/HelloWorldScene.hpp b/src/dawnhelloworld/scenes/HelloWorldScene.hpp index 8e26574e..29505ffd 100644 --- a/src/dawnhelloworld/scenes/HelloWorldScene.hpp +++ b/src/dawnhelloworld/scenes/HelloWorldScene.hpp @@ -6,7 +6,7 @@ #pragma once #include "scene/Scene.hpp" #include "prefabs/SimpleSpinningCubePrefab.hpp" -#include "prefabs/FPSLabel.hpp" +#include "prefabs/ui/debug/FPSLabel.hpp" #include "scene/components/ui/UIImage.hpp" #include "display/font/BitmapFont.hpp" diff --git a/src/dawnrose/CMakeLists.txt b/src/dawnrose/CMakeLists.txt index 41c7387b..cb218c1f 100644 --- a/src/dawnrose/CMakeLists.txt +++ b/src/dawnrose/CMakeLists.txt @@ -17,4 +17,6 @@ add_subdirectory(game) add_subdirectory(save) add_subdirectory(scene) -tool_prefab("example-prefab.xml") \ No newline at end of file +# Assets +set(ROSE_ASSETS_DIR ${DAWN_ASSETS_DIR}/games/rose) +tool_prefab(${ROSE_ASSETS_DIR}/prefabs/PlayerPrefab.xml) \ No newline at end of file diff --git a/src/dawnrose/prefabs/PlayerPrefab.hpp b/src/dawnrose/prefabs/PlayerPrefab_old.hpp similarity index 100% rename from src/dawnrose/prefabs/PlayerPrefab.hpp rename to src/dawnrose/prefabs/PlayerPrefab_old.hpp diff --git a/src/dawnrose/scenes/HelloWorldScene.hpp b/src/dawnrose/scenes/HelloWorldScene.hpp index aacab6ff..690a7665 100644 --- a/src/dawnrose/scenes/HelloWorldScene.hpp +++ b/src/dawnrose/scenes/HelloWorldScene.hpp @@ -7,15 +7,25 @@ #include "scene/Scene.hpp" #include "scene/components/GameCamera.hpp" #include "prefabs/PlayerPrefab.hpp" +#include "prefabs/ui/debug/FPSLabel.hpp" namespace Dawn { class HelloWorldScene : public Scene { protected: Camera *camera; + UICanvas *canvas; void stage() override { auto player = PlayerPrefab::create(this); + canvas = UICanvas::create(this); + + auto labelItem = FPSLabel::create(this); + labelItem->transform.setParent(canvas->transform); + labelItem->label->alignX = UI_COMPONENT_ALIGN_END; + labelItem->label->alignment = glm::vec4(0, 0, 0, 0); + labelItem->label->fontSize = 16; + auto wallBox = this->createSceneItem()->addComponent(); wallBox->min = glm::vec2(-4, -3); wallBox->max = glm::vec2(-3, 3); diff --git a/src/dawntools/prefabtool/CMakeLists.txt b/src/dawntools/prefabtool/CMakeLists.txt index 77fc2b25..ee025b7d 100644 --- a/src/dawntools/prefabtool/CMakeLists.txt +++ b/src/dawntools/prefabtool/CMakeLists.txt @@ -43,10 +43,15 @@ function(tool_prefab in) set(DEPS prefabtool) endif() - add_custom_target(prefab_${in} - COMMAND prefabtool --input="${DAWN_ASSETS_SOURCE_DIR}/${in}" --output="${DAWN_TEMP_DIR}" + STRING(REGEX REPLACE "[\.|\\|\/]" "-" prefab_name ${in}) + add_custom_target(prefab_${prefab_name} + COMMAND prefabtool --input="${DAWN_ASSETS_SOURCE_DIR}/${in}" --output="${DAWN_GENERATED_DIR}/generatedprefabs" --sources="${DAWN_SOURCES_DIR}" COMMENT "Generating prefab from ${in}" DEPENDS ${DEPS} ) - add_dependencies(${DAWN_TARGET_NAME} prefab_${in}) + target_include_directories(${DAWN_TARGET_NAME} + PUBLIC + ${DAWN_GENERATED_DIR}/generatedprefabs + ) + add_dependencies(${DAWN_TARGET_NAME} prefab_${prefab_name}) endfunction() \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabTool.cpp b/src/dawntools/prefabtool/PrefabTool.cpp index 01df510a..8aa70830 100644 --- a/src/dawntools/prefabtool/PrefabTool.cpp +++ b/src/dawntools/prefabtool/PrefabTool.cpp @@ -7,8 +7,67 @@ using namespace Dawn; + +struct PrefabComponentParserRuleset PrefabRegistry::getRuleset(std::string type) { + std::vector pathsToScan; + pathsToScan.push_back(this->sources); + + auto it = pathsToScan.begin(); + while(it != pathsToScan.end()) { + auto str = *it; + pathsToScan.erase(it); + + Directory dir = Directory(str); + auto children = dir.readDirectory(); + + auto itChildren = children.begin(); + while(itChildren != children.end()) { + if(itChildren->second == DIRECTORY_CHILD_TYPE_DIRECTORY) { + pathsToScan.push_back(str + "/" + itChildren->first); + } else { + if(itChildren->first == type+".hpp") { + // Load ruleset + std::string data; + File file(str + "/" + itChildren->first); + if(!file.readString(&data)) { + std::cout << "Failed to read ruleset file!" << file.filename << std::endl; + } else { + std::cout << "EPIC!" << file.filename << std::endl; + + // Begin scanning contentsr + // std::string include = this->sources; + auto toRemove = File::normalizeSlashes(this->sources + "/"); + auto includePath = file.filename.substr(toRemove.size(), file.filename.size() - toRemove.size()); + + // Now locate the first subdir since we don't want to include the root path (e.g. dawn, dawnrose, etc) + auto firstSlash = includePath.find("/"); + if(firstSlash != std::string::npos) { + includePath = includePath.substr(firstSlash + 1, includePath.size() - firstSlash - 1); + } + + struct PrefabComponentParserRuleset ruleset; + ruleset.include = includePath; + ruleset.name = type; + + + + // return; + assertUnreachable(); + } + } + } + ++itChildren; + } + it = pathsToScan.begin(); + }; + + return { .name = "" }; +} + +// + std::vector PrefabTool::getRequiredFlags() { - return { "input", "output" }; + return { "input", "output", "sources" }; } std::map PrefabTool::getOptionalFlags() { @@ -23,13 +82,23 @@ int32_t PrefabTool::start() { } std::string data; - if(!input.readString(&data)) return 1; + if(!input.readString(&data)) { + std::cout << "Failed to read input file!" << std::endl; + return 1; + } + + struct PrefabRegistry registry; + registry.sources = flags["sources"]; auto xml = Xml::load(data); std::string error; struct Prefab prefab; + prefab.registry = ®istry; auto result = ((PrefabParser()).parse(&xml, &prefab, &error)); - if(result != 0) return result; + if(result != 0) { + std::cout << "Failed to parse prefab: " << error << std::endl; + return result; + } // Generate output std::vector outputData; @@ -81,6 +150,8 @@ int32_t PrefabParser::onParse( while(itChildren != node->children.end()) { // Parse children as components struct PrefabComponent component; + component.registry = out->registry; + auto ret = (PrefabComponentParser()).parse(*itChildren, &component, error); if(ret != 0) return ret; out->components.push_back(component); @@ -111,44 +182,27 @@ int32_t PrefabComponentParser::onParse( out->ref = values["ref"]; } - std::function stringParser = [&](std::string str) { - return "\"" + str + "\""; - }; - - // Handle different node types! - std::map attributesForTypes = { - { "UILabel", { - .include = "scene/components/ui/UILabel.hpp", - .optional = { - { "text", stringParser } - } - } } - }; - - // Check if the node type is in the map - if(attributesForTypes.find(node->node) != attributesForTypes.end()) { - // Get the ruleset for this node type - auto ruleset = attributesForTypes[node->node]; - out->include = ruleset.include; - out->type = node->node; - - // Iterate all the optional attributes and store within the out if present - auto itOptional = ruleset.optional.begin(); - while(itOptional != ruleset.optional.end()) { - if(node->attributes.find(itOptional->first) != node->attributes.end()) { - auto raw = node->attributes[itOptional->first]; - auto parsed = itOptional->second(raw); - out->values[itOptional->first] = parsed; - } - ++itOptional; - } - - // TODO: Handle required attributes - } else { - *error = "Unknown node type: " + node->node; + // Get the ruleset. + auto ruleset = out->registry->getRuleset(node->node); + if(ruleset.name.size() == 0) { + *error = "Unknown prefab node type: " + node->node; return 1; } + out->include = ruleset.include; + out->type = node->node; + + // Iterate all the optional attributes and store within the out if present + auto itOptional = ruleset.optional.begin(); + while(itOptional != ruleset.optional.end()) { + if(node->attributes.find(itOptional->first) != node->attributes.end()) { + auto raw = node->attributes[itOptional->first]; + auto parsed = itOptional->second(raw); + out->values[itOptional->first] = parsed; + } + ++itOptional; + } + return 0; } @@ -162,7 +216,7 @@ void PrefabGen::generate( struct ClassGenInfo classInfo; classInfo.clazz = info->name; classInfo.extend = "SceneItemPrefab<" + info->name + ">"; - classInfo.constructorArgs = "Scene *scene, sceneid_t id"; + classInfo.constructorArgs = "Scene *scene, sceneitemid_t id"; classInfo.extendArgs = "scene, id"; struct MethodGenInfo methodAssets; diff --git a/src/dawntools/prefabtool/PrefabTool.hpp b/src/dawntools/prefabtool/PrefabTool.hpp index 46a8dbf2..f65880e3 100644 --- a/src/dawntools/prefabtool/PrefabTool.hpp +++ b/src/dawntools/prefabtool/PrefabTool.hpp @@ -5,17 +5,27 @@ #pragma once #include "util/DawnTool.hpp" -#include "util/File.hpp" +#include "util/Directory.hpp" #include "util/XmlParser.hpp" #include "util/CodeGen.hpp" +#include namespace Dawn { struct PrefabComponentParserRuleset { + std::string name; std::string include; std::map> optional; }; + struct PrefabRegistry { + std::string sources; + + struct PrefabComponentParserRuleset getRuleset(std::string type); + }; + struct PrefabComponent { + struct PrefabRegistry *registry; + std::string include; std::string type; std::map values; @@ -23,6 +33,8 @@ namespace Dawn { }; struct Prefab { + struct PrefabRegistry *registry; + std::string name; std::string type; std::vector components; diff --git a/src/dawntools/util/CMakeLists.txt b/src/dawntools/util/CMakeLists.txt index e324774a..3447f60e 100644 --- a/src/dawntools/util/CMakeLists.txt +++ b/src/dawntools/util/CMakeLists.txt @@ -11,6 +11,7 @@ set( ${D}/File.cpp ${D}/Language.cpp ${D}/CodeGen.cpp + ${D}/Directory.cpp CACHE INTERNAL ${DAWN_CACHE_TARGET} diff --git a/src/dawntools/util/Directory.cpp b/src/dawntools/util/Directory.cpp new file mode 100644 index 00000000..8bbc2bdd --- /dev/null +++ b/src/dawntools/util/Directory.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "Directory.hpp" + +using namespace Dawn; + +Directory::Directory(std::string dirname) { + this->filename = File::normalizeSlashes(dirname); +} + +bool_t Directory::open() { + if(this->handle) return true; + this->handle = opendir(this->filename.c_str()); + return this->handle != nullptr; +} + +bool_t Directory::isOpen() { + return this->handle != nullptr; +} + +void Directory::close() { + if(this->handle) { + closedir(this->handle); + this->handle = nullptr; + } +} + +bool_t Directory::exists() { + return this->open(); +} + +void Directory::mkdirp() { + File::mkdirp(this->filename); +} + +std::map Directory::readDirectory() { + if(!this->open()) return {}; + std::map children; + + struct dirent *dp; + while((dp = readdir(this->handle)) != NULL) { + if(!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) { + continue; + } + + //Skip anything that isn't a file or directory (symlinks, etc.) + if(dp->d_type != DT_DIR && dp->d_type != DT_REG) continue; + std::string fn = std::string(dp->d_name); + children[fn] = dp->d_type == DT_DIR ? DIRECTORY_CHILD_TYPE_DIRECTORY : DIRECTORY_CHILD_TYPE_FILE; + } + this->close(); + return children; +} + +Directory::~Directory() { + this->close(); +} \ No newline at end of file diff --git a/src/dawntools/util/Directory.hpp b/src/dawntools/util/Directory.hpp new file mode 100644 index 00000000..fcf686d3 --- /dev/null +++ b/src/dawntools/util/Directory.hpp @@ -0,0 +1,59 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "util/File.hpp" + +namespace Dawn { + enum DirectoryChildType { + DIRECTORY_CHILD_TYPE_FILE, + DIRECTORY_CHILD_TYPE_DIRECTORY + }; + + class Directory { + public: + std::string filename; + DIR *handle = nullptr; + + Directory(std::string dir); + + /** + * Opens a connection to the directory. + * @return True if success, otherwise for failure. + */ + bool_t open(); + + /** + * Returns if the directory is open. + * @return True if open, otherwise false. + */ + bool_t isOpen(); + + /** + * Closes the directory. + */ + void close(); + + /** + * Returns if the directory exists. + * @return True if exists, otherwise false. + */ + bool_t exists(); + + /** + * Creates the directory and all parent directories. + */ + void mkdirp(); + + /** + * Reads the directory and returns a list of files. + * + * @return List of filenames/directories within this directory. + */ + std::map readDirectory(); + + ~Directory(); + }; +} \ No newline at end of file diff --git a/src/dawntools/util/file.cpp b/src/dawntools/util/file.cpp deleted file mode 100644 index ee5a9834..00000000 --- a/src/dawntools/util/file.cpp +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2023 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -#include "File.hpp" - -using namespace Dawn; - -std::string File::normalizeSlashes(std::string str) { - size_t i = 0; - while(i < str.size()) { - auto c = str[i]; - if(c == '\\' || c == '/') str[i] = FILE_PATH_SEP; - ++i; - } - return str; -} - -void File::mkdirp(std::string path) { - std::string buffer; - char c; - size_t i = 0; - bool inFile; - bool hasMore; - - inFile = false; - hasMore = false; - while(c = path[i]) { - if((c == '\\' || c == '/') && i > 0) { - fileMkdir(buffer.c_str(), 0755); - inFile = false; - hasMore = false; - buffer += FILE_PATH_SEP; - i++; - continue; - } - - if(c == '.') inFile = true; - hasMore = true; - buffer += c; - i++; - } - - if(!inFile && hasMore) { - fileMkdir(buffer.c_str(), 0755); - } -} - -// - -File::File(std::string filename) { - this->filename = File::normalizeSlashes(filename); -} - -bool_t File::open(enum FileMode mode) { - assertNull(this->file); - - this->mode = mode; - this->file = fopen( - this->filename.c_str(), - mode == FILE_MODE_READ ? "rb" : "wb" - ); - - if(this->file == NULL) return false; - - if(mode == FILE_MODE_READ) { - fseek(this->file, 0, SEEK_END); - this->length = ftell(this->file); - fseek(this->file, 0, SEEK_SET); - - if(this->length <= 0) { - this->close(); - return false; - } - } else { - this->length = 0; - } - - return true; -} - -bool_t File::isOpen() { - return this->file != nullptr; -} - -bool_t File::exists() { - if(this->file != nullptr) return true; - FILE *f = fopen(this->filename.c_str(), "rb"); - if(f == NULL || f == nullptr) return false; - fclose(f); - return true; -} - -void File::close() { - assertNotNull(this->file); - fclose(this->file); - this->file = nullptr; -} - -bool_t File::mkdirp() { - File::mkdirp(this->filename); - return true; -} - -bool_t File::readString(std::string *out) { - assertNotNull(out); - - if(!this->isOpen()) { - if(!this->open(FILE_MODE_READ)) return false; - } - assertTrue(this->mode == FILE_MODE_READ); - out->clear(); - - size_t i = 0; - char buffer[FILE_BUFFER_SIZE + 1];// +1 for null term - while(i != this->length) { - size_t amt = mathMin(FILE_BUFFER_SIZE, (this->length - i)); - auto amtRead = fread(buffer, sizeof(char), amt, this->file); - if(amtRead != amt) return false; - i += amtRead; - buffer[amtRead] = '\0'; - out->append(buffer); - } - - return true; -} - -size_t File::readAhead(char *buffer, size_t max, char needle) { - assertNotNull(buffer); - assertTrue(max > 0); - - if(!this->isOpen()) { - if(!this->open(FILE_MODE_READ)) return 0; - } - assertTrue(this->mode == FILE_MODE_READ); - - // Buffer - size_t pos = ftell(this->file); - size_t amountLeftToRead = mathMin(max, this->length - pos); - char temporary[FILE_BUFFER_SIZE]; - size_t n = 0; - - while(amountLeftToRead > 0) { - size_t toRead = mathMin(amountLeftToRead, FILE_BUFFER_SIZE); - amountLeftToRead -= toRead; - // Read bytes - size_t read = fread(temporary, sizeof(char), toRead, this->file); - - // Read error? - if(toRead != read) return 0; - - // Did we read the needle? - size_t i = 0; - while(i < read) { - char c = temporary[i++]; - if(c == needle) { - return n; - } else { - buffer[n++] = c; - } - } - } - - // Needle was not found. - return -1; -} - -bool_t File::writeString(std::string in) { - if(!this->isOpen()) { - if(!this->open(FILE_MODE_WRITE)) return false; - } - assertTrue(this->mode == FILE_MODE_WRITE); - return this->writeRaw((char *)in.c_str(), in.size()) && this->length == in.size(); -} - -bool_t File::writeRaw(char *data, size_t len) { - if(!this->isOpen()) { - if(!this->open(FILE_MODE_WRITE)) return false; - } - assertTrue(this->mode == FILE_MODE_WRITE); - this->length = fwrite(data, sizeof(char_t), len, this->file); - return true; -} - -void File::setPosition(size_t n) { - fseek(this->file, 0, SEEK_SET); - fseek(this->file, n, SEEK_CUR); -} - -File::~File() { - if(this->file != nullptr) this->close(); -} \ No newline at end of file diff --git a/src/dawntools/util/file.hpp b/src/dawntools/util/file.hpp deleted file mode 100644 index e687eb62..00000000 --- a/src/dawntools/util/file.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2023 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -#pragma once -#include "assert/assert.hpp" -#include "util/mathutils.hpp" - -#if defined(_MSC_VER) - #include - #include - #define getcwd _getcwd - #define FILE_PATH_SEP '\\' - #define fileMkdir(path, perms) _mkdir(path) -#elif defined(__GNUC__) - #include - #include - #include - #define FILE_PATH_SEP '/' - #define fileMkdir(path, perms) mkdir(path, perms) -#endif -#include - -#define FILE_BUFFER_SIZE 512 - -namespace Dawn { - enum FileMode { - FILE_MODE_READ, - FILE_MODE_WRITE - }; - - class File { - private: - enum FileMode mode; - - public: - static std::string normalizeSlashes(std::string str); - static void mkdirp(std::string path); - - std::string filename; - size_t length; - FILE *file = nullptr; - - /** - * Constructs a new File interface class. - * - * @param filename Filename that you want to interface with. - */ - File(std::string filename); - - /** - * Opens a connection to the file. - * - * @param mode File mode to use for this interface. - * @return True if success, otherwise for failure. - */ - bool_t open(enum FileMode mode); - - /** - * Returns whether or not the file connection is currently opened. - * - * @return True if the connection is open, otherwise if it's not. - */ - bool_t isOpen(); - - /** - * Returns whether or not the file exists. Will open the connection if it - * does exist. - * - * @return True if exists, otherwsie if it doesn't. - */ - bool_t exists(); - - /** - * Closes the currently open interface to the file. Done automatically - * when this object is disposed. - */ - void close(); - - /** - * Makes all directories above this file's filename. - * - * @return True if successful, otherwise false. - */ - bool_t mkdirp(); - - /** - * Reads the entire contents of a file to the given output string buffer. - * This is a bit dangerous since the length of the file isn't checked - * against the memory to be consumed. - * - * @param out Pointer to a string where the output data will be stored. - * @return True if the read was successful, otherwise false. - */ - bool_t readString(std::string *out); - - /** - * Reads ahead from the current position to a specific needle (character). - * - * @param buffer Buffer to output read chars to. - * @param max Max length of the buffer / amount of chars to read ahead. - * @param needle The character (needle) to look for. - * @return Amount of chars read, or <= 0 on error. - */ - size_t readAhead( - char *buffer, - size_t max, - char needle - ); - - /** - * Writes the entire contents of a string to a file. - * - * @param in String to write to this file. - * @return True if written successfully, otherwise false. - */ - bool_t writeString(std::string in); - - /** - * Write raw bytes to the file. - * - * @param data Data to write. - * @return True if written successfully, otherwise false. - */ - bool_t writeRaw(char *data, size_t ); - - /** - * Set the position of the cursor of the file reader. - * - * @param pos Position to set. - */ - void setPosition(size_t pos); - - /** - * Destruct the File manager. - */ - ~File(); - }; -} \ No newline at end of file