diff options
author | Stefan Radomski <github@mintwerk.de> | 2017-01-08 21:59:18 (GMT) |
---|---|---|
committer | Stefan Radomski <github@mintwerk.de> | 2017-01-08 21:59:18 (GMT) |
commit | 030f3b483f54dbef6e164194a1771ef5b346312b (patch) | |
tree | 3f5b949b5ffed83d0b41a95d9fd3cfafd17cab2d /src/uscxml/util | |
parent | 1ab8b9a0dcaa131b8cccc735a1794ce39b351715 (diff) | |
download | uscxml-030f3b483f54dbef6e164194a1771ef5b346312b.zip uscxml-030f3b483f54dbef6e164194a1771ef5b346312b.tar.gz uscxml-030f3b483f54dbef6e164194a1771ef5b346312b.tar.bz2 |
Support for caching values on filesystem
Use USCXML_NOCACHE_FILES=YES to prevent, I will make this a build flag
Diffstat (limited to 'src/uscxml/util')
-rw-r--r-- | src/uscxml/util/Base64.hpp | 4 | ||||
-rw-r--r-- | src/uscxml/util/Convenience.cpp | 32 | ||||
-rw-r--r-- | src/uscxml/util/Convenience.h | 2 | ||||
-rw-r--r-- | src/uscxml/util/URL.cpp | 168 | ||||
-rw-r--r-- | src/uscxml/util/URL.h | 16 | ||||
-rw-r--r-- | src/uscxml/util/URL.mm | 62 |
6 files changed, 263 insertions, 21 deletions
diff --git a/src/uscxml/util/Base64.hpp b/src/uscxml/util/Base64.hpp index e3cbe03..d9f9ac1 100644 --- a/src/uscxml/util/Base64.hpp +++ b/src/uscxml/util/Base64.hpp @@ -40,9 +40,9 @@ USCXML_API inline std::string base64Decode(const std::string& data) { base64_init_decodestate(ctx); char* out = (char*)malloc(data.size()); - base64_decode_block(data.data(), data.size(), out, ctx); + size_t size = base64_decode_block(data.data(), data.size(), out, ctx); free(ctx); - std::string result(out); + std::string result(out, size); free(out); return result; } diff --git a/src/uscxml/util/Convenience.cpp b/src/uscxml/util/Convenience.cpp index a0263d2..4f47449 100644 --- a/src/uscxml/util/Convenience.cpp +++ b/src/uscxml/util/Convenience.cpp @@ -24,22 +24,22 @@ namespace uscxml { NumAttr::NumAttr(const std::string& str) { - size_t valueStart = str.find_first_of("0123456789."); - if (valueStart != std::string::npos) { - size_t valueEnd = str.find_last_of("0123456789."); - if (valueEnd != std::string::npos) { - value = str.substr(valueStart, (valueEnd - valueStart) + 1); - size_t unitStart = str.find_first_not_of(" \t", valueEnd + 1); - if (unitStart != std::string::npos) { - size_t unitEnd = str.find_last_of(" \t"); - if (unitEnd != std::string::npos && unitEnd > unitStart) { - unit = str.substr(unitStart, unitEnd - unitStart); - } else { - unit = str.substr(unitStart, str.length() - unitStart); - } - } - } - } + size_t valueStart = str.find_first_of("0123456789."); + if (valueStart != std::string::npos) { + size_t valueEnd = str.find_last_of("0123456789."); + if (valueEnd != std::string::npos) { + value = str.substr(valueStart, (valueEnd - valueStart) + 1); + size_t unitStart = str.find_first_not_of(" \t", valueEnd + 1); + if (unitStart != std::string::npos) { + size_t unitEnd = str.find_last_of(" \t"); + if (unitEnd != std::string::npos && unitEnd > unitStart) { + unit = str.substr(unitStart, unitEnd - unitStart); + } else { + unit = str.substr(unitStart, str.length() - unitStart); + } + } + } + } } diff --git a/src/uscxml/util/Convenience.h b/src/uscxml/util/Convenience.h index cb4416d..c12e0e4 100644 --- a/src/uscxml/util/Convenience.h +++ b/src/uscxml/util/Convenience.h @@ -45,7 +45,7 @@ template <typename T> T strTo(std::string tmp) { class USCXML_API NumAttr { public: - NumAttr(const std::string& str); + NumAttr(const std::string& str); std::string value; std::string unit; }; diff --git a/src/uscxml/util/URL.cpp b/src/uscxml/util/URL.cpp index 0885b47..845a972 100644 --- a/src/uscxml/util/URL.cpp +++ b/src/uscxml/util/URL.cpp @@ -29,14 +29,17 @@ #include <curl/curl.h> #include <uriparser/Uri.h> +#include <sys/types.h> +#include <sys/stat.h> #ifdef _WIN32 #include <direct.h> +#include <Shlobj.h> #define getcwd _getcwd #else #include <unistd.h> // getcwd -//#include <pwd.h> +#include <pwd.h> // getpwuid #endif #define DOWNLOAD_IF_NECESSARY if (!_isDownloaded) { download(true); } @@ -44,6 +47,157 @@ namespace uscxml { +std::string URL::currTmpDir; + +std::string URL::getTempDir(bool shared) { + +#ifdef _WIN32 + struct stat st = { 0 }; + TCHAR tmpPrefix [MAX_PATH]; + + // retrieve and optionally create temporary directory + if (!GetTempPath(MAX_PATH, tmpPrefix)) { + ERROR_EXECUTION_THROW(std::string("Cannot retrieve temporary directory")); + } + if (stat(tmpPrefix, &st) == -1) { + CreateDirectory(tmpPrefix, NULL); + if (GetLastError() == ERROR_PATH_NOT_FOUND) { + ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory at '") + tmpPrefix + "'"); + } + } + + if (shared) { + // create uscxml folder in temporary directory + std::string sharedTmpDir = std::string(tmpPrefix) + PATH_SEPERATOR + "uscxml"; + + if (stat(sharedTmpDir.c_str(), &st) == -1) { + CreateDirectory (sharedTmpDir.c_str(), NULL); + if (GetLastError() == ERROR_PATH_NOT_FOUND) { + ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory at '") + sharedTmpDir + "'"); + } + } + return sharedTmpDir; + + } else { + if (currTmpDir.size() == 0) { + // create random folder in temporary directory + // http://stackoverflow.com/questions/6287475/creating-a-unique-temporary-directory-from-pure-c-in-windows + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363875(v=vs.85).aspx + TCHAR tempFileName[MAX_PATH]; + if (GetTempFileName(tmpPrefix, // directory for tmp files + TEXT("uscxml."), // temp file name prefix + 0, // create unique name + tempFileName)) { + DeleteFile(tempFileName); + + if (stat(tempFileName, &st) == -1) { + CreateDirectory(tempFileName, NULL); + if (GetLastError() == ERROR_PATH_NOT_FOUND) { + ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory at '") + tempFileName + "'"); + } + } + + currTmpDir = tempFileName; + } else { + ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory at '") + tmpPrefix + "'"); + } + } + return currTmpDir; + } + +#else + std::string tmpPrefix = "/tmp"; + const char* tmpEnv = getenv("TMPDIR"); + if (tmpEnv != NULL) + tmpPrefix = tmpEnv; + + if (tmpPrefix[tmpPrefix.size() - 1] != PATH_SEPERATOR) + tmpPrefix += PATH_SEPERATOR; + + if (shared) { + struct stat st = {0}; + + std::string sharedTmpDir = tmpPrefix + "uscxml"; + if (stat(sharedTmpDir.c_str(), &st) == -1) { + int err = mkdir(sharedTmpDir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); // 777 + if (err) + ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory at '") + sharedTmpDir + "':" + strerror(errno)); + + } + return sharedTmpDir; + + } else { + if (currTmpDir.size() == 0) { + std::string tmpPrefix = "/tmp"; + const char* tmpEnv = getenv("TMPDIR"); + if (tmpEnv != NULL) + tmpPrefix = tmpEnv; + const char* tmpName = mkdtemp((char*)std::string(tmpPrefix + "uscxml.XXXXXX").c_str()); // can we merely drop the constness? + if (tmpName != NULL) { + currTmpDir = tmpName; + } else { + ERROR_EXECUTION_THROW(std::string("Cannot create a temporary directory:") + strerror(errno)); + } + } + return currTmpDir; + } +#endif +} + +// Version for MacOSX in URL.mm +#if (!defined APPLE && !defined IOS) +std::string URL::getResourceDir() { +#ifdef _WIN32 + TCHAR szPath[MAX_PATH]; + std::string resourceDir; + if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, szPath) == S_OK) { + resourceDir = std::string(szPath) + PATH_SEPERATOR + "uscxml"; + } else { + char* envData = getenv("APPDATA"); + if (envData) { + resourceDir = std::string(envData) + PATH_SEPERATOR + "uscxml"; + } else { + ERROR_EXECUTION_THROW("Could not get resource directory"); + } + } + + struct stat st = { 0 }; + + if (stat(resourceDir.c_str(), &st) == -1) { + CreateDirectory(resourceDir.c_str(), NULL); + if (GetLastError() == ERROR_PATH_NOT_FOUND) { + ERROR_EXECUTION_THROW(std::string("Cannot create a resource directory at '") + resourceDir + "'"); + } + } + return resourceDir; + +#else + struct passwd* pw = getpwuid(getuid()); + std::string homedir(pw->pw_dir); + struct stat dirStat; + int err = 0; + + err = stat(std::string(homedir + PATH_SEPERATOR + ".config").c_str(), &dirStat); + if (err == ENOENT) { + err = mkdir(std::string(homedir + PATH_SEPERATOR + ".config").c_str(), S_IWUSR | S_IRUSR | S_IROTH); + } + + err = stat(std::string(homedir + PATH_SEPERATOR + ".config" + PATH_SEPERATOR + "uscxml").c_str(), &dirStat); + if (err != 0) { + // std::cout << std::string(homedir + PATH_SEPERATOR + ".config" + PATH_SEPERATOR + "uscxml") << std::endl; + err = mkdir(std::string(homedir + PATH_SEPERATOR + ".config" + PATH_SEPERATOR + "uscxml").c_str(), + S_IWUSR | S_IRUSR | S_IROTH | S_IRGRP | S_IXUSR | S_IXOTH | S_IXGRP); + } + + err = stat(std::string(homedir + PATH_SEPERATOR + ".config" + PATH_SEPERATOR + "uscxml").c_str(), &dirStat); + if (err == 0) { + return homedir + PATH_SEPERATOR + ".config" + PATH_SEPERATOR + "uscxml"; + } + return ""; +#endif +} +#endif + void URLImpl::prepareException(ErrorEvent& exception, int errorCode, const std::string& origUri, void* parser) { exception.data.compound["uri"].atom = origUri; @@ -808,9 +962,19 @@ void URLFetcher::perform() { rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); switch(rc) { - case -1: + case -1: { /* select error */ +#ifdef _WIN32 + char *s = NULL; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, WSAGetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&s, 0, NULL); + LOGD(USCXML_WARN) << "select: " << s; + LocalFree(s); +#endif break; + } case 0: /* timeout */ default: { /* action */ std::lock_guard<std::recursive_mutex> lock(_mutex); diff --git a/src/uscxml/util/URL.h b/src/uscxml/util/URL.h index c83e3b1..9ad2f8e 100644 --- a/src/uscxml/util/URL.h +++ b/src/uscxml/util/URL.h @@ -136,6 +136,19 @@ public: URL(const std::string url) : _impl(new URLImpl(url)) {} + /** + * Get a persistant, shared directory for resources + * @return A path to an existing directory for resources. + */ + static std::string getResourceDir(); + + /** + * Get a temporary, shared or private directory for resources + * @param shared Whether the temporary directory is shared among instances. + * @return A path to an existing directory for temporary files. + */ + static std::string getTempDir(bool shared = true); + bool isAbsolute() { return _impl->isAbsolute(); } @@ -241,6 +254,8 @@ public: protected: std::shared_ptr<URLImpl> _impl; friend class URLFetcher; + static std::string currTmpDir; + }; class USCXML_API URLFetcher { @@ -270,6 +285,7 @@ protected: std::map<void*, void*> _handlesToHeaders; void* _multiHandle = NULL; char* _envProxy = NULL; + }; } diff --git a/src/uscxml/util/URL.mm b/src/uscxml/util/URL.mm new file mode 100644 index 0000000..881b3e2 --- /dev/null +++ b/src/uscxml/util/URL.mm @@ -0,0 +1,62 @@ +/** + * @file + * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#include "URL.h" +#include "Foundation/Foundation.h" + +#ifdef __has_feature +# if __has_feature(objc_arc) +# define(HAS_AUTORELEASE_POOL) +# endif +#endif + +namespace uscxml { + +std::string URL::getResourceDir() { + std::string path; +#if HAS_AUTORELEASE_POOL + @autoreleasepool { +#else + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +#endif + NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier]; + if (bundleId != nil) { + NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; + path = [resourcePath cStringUsingEncoding:NSUTF8StringEncoding]; + } else { + // we are not actually in a bundle, fall back to /tmp + NSFileManager *fm = [NSFileManager defaultManager]; + NSURL* resURL = [[fm homeDirectoryForCurrentUser] URLByAppendingPathComponent:@".uscxml"]; + NSString* resPath = [NSString stringWithUTF8String:[resURL fileSystemRepresentation]]; + + if (![fm fileExistsAtPath:resPath]) { + [fm createDirectoryAtPath:resPath withIntermediateDirectories:YES attributes:nil error:nil]; + } + path = [resPath cStringUsingEncoding:NSUTF8StringEncoding]; + } + +#if HAS_AUTORELEASE_POOL + } +#else + [pool drain]; +#endif + return path; +} + +} |