From ae5f9a0342c18cb5241453d3565a07c08e9ae10e Mon Sep 17 00:00:00 2001 From: Tomas Jakobsson Date: Wed, 15 Nov 2017 16:59:39 +0100 Subject: [PATCH] Move StringUtil to utils subfolder Added utils/FileSystemUtils which will replace some boost::filesystem functions in the future --- es-core/CMakeLists.txt | 8 + es-core/src/StringUtil.h | 136 --------------- es-core/src/components/TextComponent.cpp | 4 +- es-core/src/components/TextEditComponent.cpp | 6 +- es-core/src/resources/Font.cpp | 12 +- es-core/src/utils/FileSystemUtil.cpp | 168 +++++++++++++++++++ es-core/src/utils/FileSystemUtil.h | 23 +++ es-core/src/utils/StringUtil.cpp | 156 +++++++++++++++++ es-core/src/utils/StringUtil.h | 22 +++ 9 files changed, 388 insertions(+), 147 deletions(-) delete mode 100644 es-core/src/StringUtil.h create mode 100644 es-core/src/utils/FileSystemUtil.cpp create mode 100644 es-core/src/utils/FileSystemUtil.h create mode 100644 es-core/src/utils/StringUtil.cpp create mode 100644 es-core/src/utils/StringUtil.h diff --git a/es-core/CMakeLists.txt b/es-core/CMakeLists.txt index fabae068f..37d1ab9ee 100644 --- a/es-core/CMakeLists.txt +++ b/es-core/CMakeLists.txt @@ -61,6 +61,10 @@ set(CORE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/resources/TextureData.h ${CMAKE_CURRENT_SOURCE_DIR}/src/resources/TextureDataManager.h + # Utils + ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/FileSystemUtil.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/StringUtil.h + # Embedded assets (needed by ResourceManager) ${emulationstation-all_SOURCE_DIR}/data/Resources.h ) @@ -120,6 +124,10 @@ set(CORE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/resources/TextureResource.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/resources/TextureData.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/resources/TextureDataManager.cpp + + # Utils + ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/FileSystemUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/StringUtil.cpp ) set(EMBEDDED_ASSET_SOURCES diff --git a/es-core/src/StringUtil.h b/es-core/src/StringUtil.h deleted file mode 100644 index a7f8f84e3..000000000 --- a/es-core/src/StringUtil.h +++ /dev/null @@ -1,136 +0,0 @@ -#pragma once -#ifndef ES_CORE_STRING_UTIL_H -#define ES_CORE_STRING_UTIL_H - -namespace StringUtil -{ - inline unsigned int chars2Unicode(const std::string& _string, size_t& _cursor) - { - const char& c = _string[_cursor]; - unsigned int result = '?'; - - if((c & 0x80) == 0) // 0xxxxxxx, one byte character - { - // 0xxxxxxx - result = ((_string[_cursor++] ) ); - } - else if((c & 0xE0) == 0xC0) // 110xxxxx, two byte character - { - // 110xxxxx 10xxxxxx - result = ((_string[_cursor++] & 0x1F) << 6) | - ((_string[_cursor++] & 0x3F) ); - } - else if((c & 0xF0) == 0xE0) // 1110xxxx, three byte character - { - // 1110xxxx 10xxxxxx 10xxxxxx - result = ((_string[_cursor++] & 0x0F) << 12) | - ((_string[_cursor++] & 0x3F) << 6) | - ((_string[_cursor++] & 0x3F) ); - } - else if((c & 0xF8) == 0xF0) // 11110xxx, four byte character - { - // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - result = ((_string[_cursor++] & 0x07) << 18) | - ((_string[_cursor++] & 0x3F) << 12) | - ((_string[_cursor++] & 0x3F) << 6) | - ((_string[_cursor++] & 0x3F) ); - } - else - { - // error, invalid unicode - ++_cursor; - } - - return result; - - } // chars2Unicode - - inline std::string unicode2Chars(const unsigned int _unicode) - { - std::string result; - - if(_unicode < 0x80) // one byte character - { - result += ((_unicode ) ); - } - else if(_unicode < 0x800) // two byte character - { - result += ((_unicode >> 6) ) | 0xC0; - result += ((_unicode ) & 0x3F) | 0x80; - } - else if(_unicode < 0xFFFF) // three byte character - { - result += ((_unicode >> 12) ) | 0xE0; - result += ((_unicode >> 6) & 0x3F) | 0x80; - result += ((_unicode ) & 0x3F) | 0x80; - } - else if(_unicode <= 0x1fffff) // four byte character - { - result += ((_unicode >> 18) ) | 0xF0; - result += ((_unicode >> 12) & 0x3F) | 0x80; - result += ((_unicode >> 6) & 0x3F) | 0x80; - result += ((_unicode ) & 0x3F) | 0x80; - } - else - { - // error, invalid unicode - result += '?'; - } - - return result; - - } // unicode2Chars - - inline size_t nextCursor(const std::string& _string, const size_t _cursor) - { - size_t result = _cursor; - - while(result < _string.length()) - { - ++result; - - if((_string[result] & 0xC0) != 0x80) // break if current character is not 10xxxxxx - break; - } - - return result; - - } // nextCursor - - inline size_t prevCursor(const std::string& _string, const size_t _cursor) - { - size_t result = _cursor; - - while(result > 0) - { - --result; - - if((_string[result] & 0xC0) != 0x80) // break if current character is not 10xxxxxx - break; - } - - return result; - - } // prevCursor - - inline size_t moveCursor(const std::string& _string, const size_t _cursor, const int _amount) - { - size_t result = _cursor; - - if(_amount > 0) - { - for(int i = 0; i < _amount; ++i) - result = nextCursor(_string, result); - } - else if(_amount < 0) - { - for(int i = _amount; i < 0; ++i) - result = prevCursor(_string, result); - } - - return result; - - } // moveCursor -} - -#endif // ES_CORE_STRING_UTIL_H diff --git a/es-core/src/components/TextComponent.cpp b/es-core/src/components/TextComponent.cpp index f7885139e..0e451912e 100644 --- a/es-core/src/components/TextComponent.cpp +++ b/es-core/src/components/TextComponent.cpp @@ -1,9 +1,9 @@ #include "components/TextComponent.h" +#include "utils/StringUtil.h" #include "Log.h" #include "Renderer.h" #include "Settings.h" -#include "StringUtil.h" #include "Util.h" TextComponent::TextComponent(Window* window) : GuiComponent(window), @@ -198,7 +198,7 @@ void TextComponent::onTextChanged() while(text.size() && size.x() + abbrevSize.x() > mSize.x()) { - size_t newSize = StringUtil::prevCursor(text, text.size()); + size_t newSize = Utils::String::prevCursor(text, text.size()); text.erase(newSize, text.size() - newSize); size = f->sizeText(text); } diff --git a/es-core/src/components/TextEditComponent.cpp b/es-core/src/components/TextEditComponent.cpp index 758b1aef9..5cb7fb2dc 100644 --- a/es-core/src/components/TextEditComponent.cpp +++ b/es-core/src/components/TextEditComponent.cpp @@ -1,8 +1,8 @@ #include "components/TextEditComponent.h" #include "resources/Font.h" +#include "utils/StringUtil.h" #include "Renderer.h" -#include "StringUtil.h" #define TEXT_PADDING_HORIZ 10 #define TEXT_PADDING_VERT 2 @@ -60,7 +60,7 @@ void TextEditComponent::textInput(const char* text) { if(mCursor > 0) { - size_t newCursor = StringUtil::prevCursor(mText, mCursor); + size_t newCursor = Utils::String::prevCursor(mText, mCursor); mText.erase(mText.begin() + newCursor, mText.begin() + mCursor); mCursor = newCursor; } @@ -191,7 +191,7 @@ void TextEditComponent::updateCursorRepeat(int deltaTime) void TextEditComponent::moveCursor(int amt) { - mCursor = StringUtil::moveCursor(mText, mCursor, amt); + mCursor = Utils::String::moveCursor(mText, mCursor, amt); onCursorChanged(); } diff --git a/es-core/src/resources/Font.cpp b/es-core/src/resources/Font.cpp index a5ecd3c23..299267fd6 100644 --- a/es-core/src/resources/Font.cpp +++ b/es-core/src/resources/Font.cpp @@ -1,8 +1,8 @@ #include "resources/Font.h" +#include "utils/StringUtil.h" #include "Log.h" #include "Renderer.h" -#include "StringUtil.h" #include "Util.h" FT_Library Font::sLibrary = NULL; @@ -448,7 +448,7 @@ Vector2f Font::sizeText(std::string text, float lineSpacing) size_t i = 0; while(i < text.length()) { - unsigned int character = StringUtil::chars2Unicode(text, i); // advances i + unsigned int character = Utils::String::chars2Unicode(text, i); // advances i if(character == '\n') { @@ -541,8 +541,8 @@ Vector2f Font::getWrappedTextCursorOffset(std::string text, float xLen, size_t s size_t cursor = 0; while(cursor < stop) { - unsigned int wrappedCharacter = StringUtil::chars2Unicode(wrappedText, wrapCursor); - unsigned int character = StringUtil::chars2Unicode(text, cursor); + unsigned int wrappedCharacter = Utils::String::chars2Unicode(wrappedText, wrapCursor); + unsigned int character = Utils::String::chars2Unicode(text, cursor); if(wrappedCharacter == '\n' && character != '\n') { @@ -551,7 +551,7 @@ Vector2f Font::getWrappedTextCursorOffset(std::string text, float xLen, size_t s lineWidth = 0.0f; y += getHeight(lineSpacing); - cursor = StringUtil::prevCursor(text, cursor); // unconsume + cursor = Utils::String::prevCursor(text, cursor); // unconsume continue; } @@ -614,7 +614,7 @@ TextCache* Font::buildTextCache(const std::string& text, Vector2f offset, unsign size_t cursor = 0; while(cursor < text.length()) { - unsigned int character = StringUtil::chars2Unicode(text, cursor); // also advances cursor + unsigned int character = Utils::String::chars2Unicode(text, cursor); // also advances cursor Glyph* glyph; // invalid character diff --git a/es-core/src/utils/FileSystemUtil.cpp b/es-core/src/utils/FileSystemUtil.cpp new file mode 100644 index 000000000..54e49d88c --- /dev/null +++ b/es-core/src/utils/FileSystemUtil.cpp @@ -0,0 +1,168 @@ +#include "utils/FileSystemUtil.h" + +#include +#include + +#if defined(WIN32) +// because windows... +#include +#define snprintf _snprintf +#define mkdir(x,y) _mkdir(x) +#endif // WIN32 + +namespace Utils +{ + namespace FileSystem + { + bool createDirectory(const std::string& path) + { + // don't create if it already exists + if(exists(path)) + return true; + + // convert '\\' to '/' + fixSeparators(path); + + // try to create directory + if(mkdir(path.c_str(), 0755) == 0) + return true; + + // failed to create directory, try to create the parent + std::string parent = getParent(path); + + // only try to create parent if it's not identical to path + if(parent != path) + createDirectory(parent); + + // try to create directory again now that the parent should exist + return (mkdir(path.c_str(), 0755) == 0); + + } // createDirectory + + void fixSeparators(const std::string& path) + { + char* p = nullptr; + + // convert '\\' to '/' + for(p = (char*)path.c_str() + 1; *p; ++p) + { + if(*p == '\\') + *p = '/'; + } + + } // fixSeparators + + std::string escapePath(const std::string& path) + { + +#ifdef WIN32 + // windows escapes stuff by just putting everything in quotes + return '"' + path + '"'; +#else // WIN32 + // insert a backslash before most characters that would mess up a bash path + std::string escapedPath = path; + const char* invalidChars = "\\ '\"!$^&*(){}[]?;<>"; + const char* invalidChar = invalidChars; + + while(*invalidChar) + { + for(size_t i = 0; i < escapedPath.length(); ++i) + { + if(escapedPath[i] == *invalidChar) + { + escapedPath.insert(i, 1, '\\'); + ++i; + } + } + + ++invalidChar; + } + + return escapedPath; +#endif // WIN32 + + } // escapePath + + std::string getParent(const std::string& path) + { + // convert '\\' to '/' + fixSeparators(path); + + // make a copy of the path + char temp[512]; + size_t len = snprintf(temp, sizeof(temp), "%s", path.c_str()); + + // find last '/' and end the new path + while(len > 1) + { + if(temp[--len] == '/') + { + temp[len] = 0; + return temp; + } + } + + // no parent found + return path; + + } // getParent + + std::string getFileName(const std::string& path) + { + // convert '\\' to '/' + fixSeparators(path); + + // make a copy of the path + char temp[512]; + size_t len = snprintf(temp, sizeof(temp), "%s", path.c_str()); + + // find last '/' and return the filename + while(len > 1) + { + // return "." if this is the end of the path, otherwise return filename + if(temp[--len] == '/') + return ((temp[len + 1] == 0) ? "." : (temp + len + 1)); + } + + // no '/' found, entire path is a filename + return path; + + } // getFileName + + std::string getStem(const std::string& path) + { + std::string fileName = getFileName(path); + + // empty fileName + if(fileName == ".") + return fileName; + + // make a copy of the filename + char temp[512]; + size_t len = snprintf(temp, sizeof(temp), "%s", fileName.c_str()); + + // find last '.' and remove the extension + while(len > 1) + { + if(temp[--len] == '.') + { + temp[len] = 0; + return temp; + } + } + + // no '.' found, filename has no extension + return fileName; + + } // getStem + + bool exists(const std::string& path) + { + struct stat info; + return (stat(path.c_str(), &info) == 0); + + } // exists + + } // FileSystem:: + +} // Utils:: diff --git a/es-core/src/utils/FileSystemUtil.h b/es-core/src/utils/FileSystemUtil.h new file mode 100644 index 000000000..fe6929654 --- /dev/null +++ b/es-core/src/utils/FileSystemUtil.h @@ -0,0 +1,23 @@ +#pragma once +#ifndef ES_CORE_FILE_SYSTEM_UTIL_H +#define ES_CORE_FILE_SYSTEM_UTIL_H + +#include + +namespace Utils +{ + namespace FileSystem + { + bool createDirectory(const std::string& path); + void fixSeparators(const std::string& path); + std::string escapePath(const std::string& path); + std::string getParent(const std::string& path); + std::string getFileName(const std::string& path); + std::string getStem(const std::string& path); + bool exists(const std::string& path); + + } // FileSystem:: + +} // Utils:: + +#endif // ES_CORE_FILE_SYSTEM_UTIL_H diff --git a/es-core/src/utils/StringUtil.cpp b/es-core/src/utils/StringUtil.cpp new file mode 100644 index 000000000..684ec3c4a --- /dev/null +++ b/es-core/src/utils/StringUtil.cpp @@ -0,0 +1,156 @@ +#include "utils/StringUtil.h" + +namespace Utils +{ + namespace String + { + unsigned int chars2Unicode(const std::string& _string, size_t& _cursor) + { + const char& c = _string[_cursor]; + unsigned int result = '?'; + + if((c & 0x80) == 0) // 0xxxxxxx, one byte character + { + // 0xxxxxxx + result = ((_string[_cursor++] ) ); + } + else if((c & 0xE0) == 0xC0) // 110xxxxx, two byte character + { + // 110xxxxx 10xxxxxx + result = ((_string[_cursor++] & 0x1F) << 6) | + ((_string[_cursor++] & 0x3F) ); + } + else if((c & 0xF0) == 0xE0) // 1110xxxx, three byte character + { + // 1110xxxx 10xxxxxx 10xxxxxx + result = ((_string[_cursor++] & 0x0F) << 12) | + ((_string[_cursor++] & 0x3F) << 6) | + ((_string[_cursor++] & 0x3F) ); + } + else if((c & 0xF8) == 0xF0) // 11110xxx, four byte character + { + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + result = ((_string[_cursor++] & 0x07) << 18) | + ((_string[_cursor++] & 0x3F) << 12) | + ((_string[_cursor++] & 0x3F) << 6) | + ((_string[_cursor++] & 0x3F) ); + } + else + { + // error, invalid unicode + ++_cursor; + } + + return result; + + } // chars2Unicode + + std::string unicode2Chars(const unsigned int _unicode) + { + std::string result; + + if(_unicode < 0x80) // one byte character + { + result += ((_unicode ) ); + } + else if(_unicode < 0x800) // two byte character + { + result += ((_unicode >> 6) ) | 0xC0; + result += ((_unicode ) & 0x3F) | 0x80; + } + else if(_unicode < 0xFFFF) // three byte character + { + result += ((_unicode >> 12) ) | 0xE0; + result += ((_unicode >> 6) & 0x3F) | 0x80; + result += ((_unicode ) & 0x3F) | 0x80; + } + else if(_unicode <= 0x1fffff) // four byte character + { + result += ((_unicode >> 18) ) | 0xF0; + result += ((_unicode >> 12) & 0x3F) | 0x80; + result += ((_unicode >> 6) & 0x3F) | 0x80; + result += ((_unicode ) & 0x3F) | 0x80; + } + else + { + // error, invalid unicode + result += '?'; + } + + return result; + + } // unicode2Chars + + size_t nextCursor(const std::string& _string, const size_t _cursor) + { + size_t result = _cursor; + + while(result < _string.length()) + { + ++result; + + if((_string[result] & 0xC0) != 0x80) // break if current character is not 10xxxxxx + break; + } + + return result; + + } // nextCursor + + size_t prevCursor(const std::string& _string, const size_t _cursor) + { + size_t result = _cursor; + + while(result > 0) + { + --result; + + if((_string[result] & 0xC0) != 0x80) // break if current character is not 10xxxxxx + break; + } + + return result; + + } // prevCursor + + size_t moveCursor(const std::string& _string, const size_t _cursor, const int _amount) + { + size_t result = _cursor; + + if(_amount > 0) + { + for(int i = 0; i < _amount; ++i) + result = nextCursor(_string, result); + } + else if(_amount < 0) + { + for(int i = _amount; i < 0; ++i) + result = prevCursor(_string, result); + } + + return result; + + } // moveCursor + + void trim(std::string& _string) + { + if(_string.size()) + { + size_t cursorB = 0; + size_t cursorE = _string.size(); + + while((cursorB < _string.size()) && _string[cursorB] == ' ') + ++cursorB; + + while((cursorE > 0) && _string[cursorE - 1] == ' ') + --cursorE; + + _string.erase(_string.begin() + cursorE, _string.end()); + _string.erase(_string.begin(), _string.begin() + cursorB); + } + + } // trim + + } // String:: + +} // Utils:: diff --git a/es-core/src/utils/StringUtil.h b/es-core/src/utils/StringUtil.h new file mode 100644 index 000000000..29d82c338 --- /dev/null +++ b/es-core/src/utils/StringUtil.h @@ -0,0 +1,22 @@ +#pragma once +#ifndef ES_CORE_STRING_UTIL_H +#define ES_CORE_STRING_UTIL_H + +#include + +namespace Utils +{ + namespace String + { + unsigned int chars2Unicode(const std::string& _string, size_t& _cursor); + std::string unicode2Chars(const unsigned int _unicode); + size_t nextCursor(const std::string& _string, const size_t _cursor); + size_t prevCursor(const std::string& _string, const size_t _cursor); + size_t moveCursor(const std::string& _string, const size_t _cursor, const int _amount); + void trim(std::string& _string); + + } // String:: + +} // Utils:: + +#endif // ES_CORE_STRING_UTIL_H