feat(slam): add rtabmap_ros

This commit is contained in:
X-lanni
2025-07-14 11:34:38 +08:00
parent 3b6641c1fb
commit 943ce5b06f
1635 changed files with 603092 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
SET(SRC_FILES
UEventsManager.cpp
UEventsHandler.cpp
UEventsSender.cpp
UFile.cpp
UDirectory.cpp
UConversion.cpp
ULogger.cpp
UThread.cpp
UTimer.cpp
UProcessInfo.cpp
UVariant.cpp
)
ADD_LIBRARY(rtabmap_utilite ${SRC_FILES})
ADD_LIBRARY(rtabmap::utilite ALIAS rtabmap_utilite)
generate_export_header(rtabmap_utilite
BASE_NAME utilite)
target_include_directories(rtabmap_utilite PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include;${CMAKE_CURRENT_BINARY_DIR}/include;${PTHREADS_INCLUDE_DIR}>"
"$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR};${PTHREADS_INCLUDE_DIR}>")
IF(MINGW)
TARGET_LINK_LIBRARIES(rtabmap_utilite PRIVATE ${PTHREADS_LIBRARY} "-lpsapi")
ELSEIF(WIN32 OR MSVC)
FIND_LIBRARY(PSAPI_LIBRARIES NAMES psapi libpsapi.dll.a libpsapi.a libpsapi.lib )
TARGET_LINK_LIBRARIES(rtabmap_utilite PRIVATE ${PSAPI_LIBRARIES})
ELSE()
TARGET_LINK_LIBRARIES(rtabmap_utilite PRIVATE ${PTHREADS_LIBRARY})
ENDIF()
SET_TARGET_PROPERTIES(
rtabmap_utilite
PROPERTIES
VERSION ${RTABMAP_VERSION}
SOVERSION ${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}
EXPORT_NAME "utilite"
)
INSTALL(TARGETS rtabmap_utilite EXPORT rtabmap_utiliteTargets
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel)
configure_file(
${CMAKE_CURRENT_BINARY_DIR}/utilite_export.h
${CMAKE_CURRENT_BINARY_DIR}/include/${PROJECT_PREFIX}/utilite/utilite_export.h
COPYONLY)
install(
DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/../include/${PROJECT_PREFIX}
${CMAKE_CURRENT_BINARY_DIR}/include/${PROJECT_PREFIX}
DESTINATION
"${INSTALL_INCLUDE_DIR}"
COMPONENT
devel
FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp")
export(EXPORT rtabmap_utiliteTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/../../${PROJECT_NAME}_utiliteTargets.cmake"
NAMESPACE rtabmap::
)
install(EXPORT rtabmap_utiliteTargets
FILE
${PROJECT_NAME}_utiliteTargets.cmake
DESTINATION
${INSTALL_CMAKE_DIR}
NAMESPACE rtabmap::
COMPONENT
devel
)
+392
View File
@@ -0,0 +1,392 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UConversion.h"
#include "rtabmap/utilite/UStl.h"
#include <sstream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <iomanip>
#ifdef _WIN32
#include <windows.h>
#endif
std::string uReplaceChar(const std::string & str, char before, char after)
{
std::string result = str;
for(unsigned int i=0; i<result.size(); ++i)
{
if(result[i] == before)
{
result[i] = after;
}
}
return result;
}
std::string uReplaceChar(const std::string & str, char before, const std::string & after)
{
std::string s;
for(unsigned int i=0; i<str.size(); ++i)
{
if(str.at(i) != before)
{
s.push_back(str.at(i));
}
else
{
s.append(after);
}
}
return s;
}
std::string uToUpperCase(const std::string & str)
{
std::string result = str;
for(unsigned int i=0; i<result.size(); ++i)
{
// only change case of ascii characters ('a' to 'z')
if(result[i] >= 'a' && result[i]<='z')
{
result[i] = result[i] - 'a' + 'A';
}
}
return result;
}
std::string uToLowerCase(const std::string & str)
{
std::string result = str;
for(unsigned int i=0; i<result.size(); ++i)
{
// only change case of ascii characters ('A' to 'Z')
if(result[i] >= 'A' && result[i]<='Z')
{
result[i] = result[i] - 'A' + 'a';
}
}
return result;
}
std::string uNumber2Str(unsigned int number)
{
std::stringstream s;
s << number;
return s.str();
}
std::string uNumber2Str(int number)
{
std::stringstream s;
s << number;
return s.str();
}
std::string uNumber2Str(float number, int precision, bool fixed)
{
std::stringstream s;
s << std::setprecision(precision);
if(fixed)
s << std::fixed;
s << number;
return s.str();
}
std::string uNumber2Str(double number, int precision, bool fixed)
{
std::stringstream s;
s << std::setprecision(precision);
if(fixed)
s << std::fixed;
s << number;
return s.str();
}
int uStr2Int(const std::string & str)
{
if(uStrContains(uToLowerCase(str), "true"))
{
return 1;
}
else if(uStrContains(uToLowerCase(str), "false"))
{
return 0;
}
return atoi(str.c_str());
}
float uStr2Float(const std::string & str)
{
float value = 0.0f;
std::istringstream istr(uReplaceChar(str, ',', '.').c_str());
istr.imbue(std::locale("C"));
istr >> value;
return value;
}
double uStr2Double(const std::string & str)
{
double value = 0.0;
std::istringstream istr(uReplaceChar(str, ',', '.').c_str());
istr.imbue(std::locale("C"));
istr >> value;
return value;
}
std::string uBool2Str(bool boolean)
{
std::string s;
if(boolean)
{
s = "true";
}
else
{
s = "false";
}
return s;
}
bool uStr2Bool(const char * str)
{
return !(str && (uStrContains(uToLowerCase(str), "false") || strcmp(str, "0") == 0));
}
bool uStr2Bool(const std::string & str)
{
return !(uStrContains(uToLowerCase(str), "false") || str.compare("0") == 0);
}
std::vector<unsigned char> uStr2Bytes(const std::string & str)
{
std::vector<unsigned char> bytes(str.size()+1);
memcpy(bytes.data(), str.data(), str.size());
bytes[bytes.size()-1] = '\0'; // null character
return bytes;
}
std::string uBytes2Str(const std::vector<unsigned char> & bytes)
{
if(bytes.size())
{
if(bytes[bytes.size()-1] != '\0')
{
std::vector<unsigned char> tmp = bytes;
tmp.push_back('\0');
return std::string((const char *)tmp.data());
}
return std::string((const char *)bytes.data());
}
return std::string();
}
std::string uBytes2Hex(const char * bytes, unsigned int bytesLen)
{
std::string hex;
if(!bytes || bytesLen == 0)
{
return hex;
}
const unsigned char * bytes_u = (const unsigned char*)(bytes);
hex.resize(bytesLen*2);
char * pHex = &hex[0];
const unsigned char * pEnd = (bytes_u + bytesLen);
for(const unsigned char * pChar = bytes_u; pChar != pEnd; ++pChar, pHex += 2)
{
pHex[0] = uHex2Ascii(*pChar, 0);
pHex[1] = uHex2Ascii(*pChar, 1);
}
return hex;
}
std::vector<char> uHex2Bytes(const std::string & hex)
{
return uHex2Bytes(&hex[0], (int)hex.length());
}
std::vector<char> uHex2Bytes(const char * hex, int hexLen)
{
std::vector<char> bytes;
if(!hex || hexLen % 2 || hexLen == 0)
{
return bytes; // must be pair
}
unsigned int bytesLen = hexLen / 2;
bytes.resize(bytesLen);
unsigned char * pBytes = (unsigned char *)&bytes[0];
const unsigned char * pHex = (const unsigned char *)hex;
unsigned char * pEnd = (pBytes + bytesLen);
for(unsigned char * pChar = pBytes; pChar != pEnd; pChar++, pHex += 2)
{
*pChar = (uAscii2Hex(pHex[0]) << 4) | uAscii2Hex(pHex[1]);
}
return bytes;
}
// The hex str MUST not contains any null values (0x00)
std::string uHex2Str(const std::string & hex)
{
std::vector<char> bytes = uHex2Bytes(hex);
return std::string(&bytes[0], bytes.size());
}
static const char HEX2ASCII[256][2] =
{
{'0','0'},{'0','1'},{'0','2'},{'0','3'},{'0','4'},{'0','5'},{'0','6'},{'0','7'},{'0','8'},{'0','9'},{'0','A'},{'0','B'},{'0','C'},{'0','D'},{'0','E'},{'0','F'},
{'1','0'},{'1','1'},{'1','2'},{'1','3'},{'1','4'},{'1','5'},{'1','6'},{'1','7'},{'1','8'},{'1','9'},{'1','A'},{'1','B'},{'1','C'},{'1','D'},{'1','E'},{'1','F'},
{'2','0'},{'2','1'},{'2','2'},{'2','3'},{'2','4'},{'2','5'},{'2','6'},{'2','7'},{'2','8'},{'2','9'},{'2','A'},{'2','B'},{'2','C'},{'2','D'},{'2','E'},{'2','F'},
{'3','0'},{'3','1'},{'3','2'},{'3','3'},{'3','4'},{'3','5'},{'3','6'},{'3','7'},{'3','8'},{'3','9'},{'3','A'},{'3','B'},{'3','C'},{'3','D'},{'3','E'},{'3','F'},
{'4','0'},{'4','1'},{'4','2'},{'4','3'},{'4','4'},{'4','5'},{'4','6'},{'4','7'},{'4','8'},{'4','9'},{'4','A'},{'4','B'},{'4','C'},{'4','D'},{'4','E'},{'4','F'},
{'5','0'},{'5','1'},{'5','2'},{'5','3'},{'5','4'},{'5','5'},{'5','6'},{'5','7'},{'5','8'},{'5','9'},{'5','A'},{'5','B'},{'5','C'},{'5','D'},{'5','E'},{'5','F'},
{'6','0'},{'6','1'},{'6','2'},{'6','3'},{'6','4'},{'6','5'},{'6','6'},{'6','7'},{'6','8'},{'6','9'},{'6','A'},{'6','B'},{'6','C'},{'6','D'},{'6','E'},{'6','F'},
{'7','0'},{'7','1'},{'7','2'},{'7','3'},{'7','4'},{'7','5'},{'7','6'},{'7','7'},{'7','8'},{'7','9'},{'7','A'},{'7','B'},{'7','C'},{'7','D'},{'7','E'},{'7','F'},
{'8','0'},{'8','1'},{'8','2'},{'8','3'},{'8','4'},{'8','5'},{'8','6'},{'8','7'},{'8','8'},{'8','9'},{'8','A'},{'8','B'},{'8','C'},{'8','D'},{'8','E'},{'8','F'},
{'9','0'},{'9','1'},{'9','2'},{'9','3'},{'9','4'},{'9','5'},{'9','6'},{'9','7'},{'9','8'},{'9','9'},{'9','A'},{'9','B'},{'9','C'},{'9','D'},{'9','E'},{'9','F'},
{'A','0'},{'A','1'},{'A','2'},{'A','3'},{'A','4'},{'A','5'},{'A','6'},{'A','7'},{'A','8'},{'A','9'},{'A','A'},{'A','B'},{'A','C'},{'A','D'},{'A','E'},{'A','F'},
{'B','0'},{'B','1'},{'B','2'},{'B','3'},{'B','4'},{'B','5'},{'B','6'},{'B','7'},{'B','8'},{'B','9'},{'B','A'},{'B','B'},{'B','C'},{'B','D'},{'B','E'},{'B','F'},
{'C','0'},{'C','1'},{'C','2'},{'C','3'},{'C','4'},{'C','5'},{'C','6'},{'C','7'},{'C','8'},{'C','9'},{'C','A'},{'C','B'},{'C','C'},{'C','D'},{'C','E'},{'C','F'},
{'D','0'},{'D','1'},{'D','2'},{'D','3'},{'D','4'},{'D','5'},{'D','6'},{'D','7'},{'D','8'},{'D','9'},{'D','A'},{'D','B'},{'D','C'},{'D','D'},{'D','E'},{'D','F'},
{'E','0'},{'E','1'},{'E','2'},{'E','3'},{'E','4'},{'E','5'},{'E','6'},{'E','7'},{'E','8'},{'E','9'},{'E','A'},{'E','B'},{'E','C'},{'E','D'},{'E','E'},{'E','F'},
{'F','0'},{'F','1'},{'F','2'},{'F','3'},{'F','4'},{'F','5'},{'F','6'},{'F','7'},{'F','8'},{'F','9'},{'F','A'},{'F','B'},{'F','C'},{'F','D'},{'F','E'},{'F','F'}
};
unsigned char uHex2Ascii(const unsigned char & c, bool rightPart)
{
if(rightPart)
{
return HEX2ASCII[c][1];
}
else
{
return HEX2ASCII[c][0];
}
}
unsigned char uAscii2Hex(const unsigned char & c)
{
switch(c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return c-'0';
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
return c-'A'+10;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
return c-'a'+10;
default:
return 0x00;
}
}
std::string uFormatv (const char *fmt, va_list args)
{
// Allocate a buffer on the stack that's big enough for us almost
// all the time. Be prepared to allocate dynamically if it doesn't fit.
size_t size = 1024;
std::vector<char> dynamicbuf(size);
char *buf = &dynamicbuf[0];
va_list argsTmp;
while (1) {
#if defined(_WIN32) && !defined(__MINGW32__)
argsTmp = args;
#else
va_copy(argsTmp, args);
#endif
// Try to vsnprintf into our buffer.
#ifdef _MSC_VER
int needed = vsnprintf_s(buf, size, size, fmt, argsTmp);
#else
int needed = vsnprintf (buf, size, fmt, argsTmp);
#endif
va_end(argsTmp);
// NB. C99 (which modern Linux and OS X follow) says vsnprintf
// failure returns the length it would have needed. But older
// glibc and current Windows return -1 for failure, i.e., not
// telling us how much was needed.
if (needed < (int)size-1 && needed >= 0) {
// It fit fine so we're done.
return std::string (buf, (size_t) needed);
}
// vsnprintf reported that it wanted to write more characters
// than we allotted. So try again using a dynamic buffer. This
// doesn't happen very often if we chose our initial size well.
size = needed>=0?needed+2:size*2;
dynamicbuf.resize (size);
buf = &dynamicbuf[0];
}
return std::string(); // would not reach this, but for compiler complaints...
}
std::string uFormat (const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
std::string buf = uFormatv(fmt, args);
va_end(args);
return buf;
}
#ifdef _WIN32
// returned whar_t * must be deleted : delete [] wText;
wchar_t * createWCharFromChar(const char * text)
{
DWORD length = MultiByteToWideChar (CP_ACP, 0, text, -1, NULL, 0);
wchar_t * wText = new wchar_t[length];
MultiByteToWideChar (CP_ACP, 0, text, -1, wText, length );
return wText;
}
// returned char * must be deleted : delete [] text;
char * createCharFromWChar(const wchar_t * wText)
{
DWORD length = WideCharToMultiByte (CP_ACP, 0, wText, -1, NULL, 0, NULL, NULL);
char * text = new char[length];
WideCharToMultiByte (CP_ACP, 0, wText, -1, text, length, NULL, NULL);
return text;
}
#endif
+398
View File
@@ -0,0 +1,398 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UDirectory.h"
#ifdef _WIN32
#include <Windows.h>
#include <direct.h>
#include <algorithm>
#include <conio.h>
#else
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/param.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#endif
#include "rtabmap/utilite/UStl.h"
#include "rtabmap/utilite/UFile.h"
#include "rtabmap/utilite/UDirectory.h"
#include "rtabmap/utilite/UConversion.h"
#include "rtabmap/utilite/ULogger.h"
#ifdef _WIN32
bool sortCallback(const std::string & a, const std::string & b)
{
return uStrNumCmp(a,b) < 0;
}
#elif __APPLE__
int sortCallback(const struct dirent ** a, const struct dirent ** b)
{
return uStrNumCmp((*a)->d_name, (*b)->d_name);
}
#else
int sortCallback( const dirent ** a, const dirent ** b)
{
return uStrNumCmp((*a)->d_name, (*b)->d_name);
}
#endif
UDirectory::UDirectory(const std::string & path, const std::string & extensions)
{
extensions_ = uListToVector(uSplit(extensions, ' '));
path_ = path;
iFileName_ = fileNames_.begin();
this->update();
}
UDirectory::UDirectory(const UDirectory & dir)
{
*this = dir;
}
UDirectory & UDirectory::operator=(const UDirectory & dir)
{
extensions_ = dir.extensions_;
path_ = dir.path_;
fileNames_ = dir.fileNames_;
for(iFileName_=fileNames_.begin(); iFileName_!=fileNames_.end(); ++iFileName_)
{
if(iFileName_->compare(*dir.iFileName_) == 0)
{
break;
}
}
return *this;
}
UDirectory::~UDirectory()
{
}
void UDirectory::setPath(const std::string & path, const std::string & extensions)
{
extensions_ = uListToVector(uSplit(extensions, ' '));
path_ = path;
fileNames_.clear();
iFileName_ = fileNames_.begin();
this->update();
}
void UDirectory::update()
{
if(exists(path_))
{
std::string lastName;
bool endOfDir = false;
if(iFileName_ != fileNames_.end())
{
//Record the last file name
lastName = *iFileName_;
}
else if(fileNames_.size())
{
lastName = *fileNames_.rbegin();
endOfDir = true;
}
fileNames_.clear();
#ifdef _WIN32
WIN32_FIND_DATA fileInformation;
#ifdef UNICODE
wchar_t * pathAll = createWCharFromChar((path_+"\\*").c_str());
HANDLE hFile = ::FindFirstFile(pathAll, &fileInformation);
delete [] pathAll;
#else
HANDLE hFile = ::FindFirstFile((path_+"\\*").c_str(), &fileInformation);
#endif
if(hFile != INVALID_HANDLE_VALUE)
{
do
{
#ifdef UNICODE
char * fileName = createCharFromWChar(fileInformation.cFileName);
fileNames_.push_back(fileName);
delete [] fileName;
#else
fileNames_.push_back(fileInformation.cFileName);
#endif
} while(::FindNextFile(hFile, &fileInformation) == TRUE);
::FindClose(hFile);
std::vector<std::string> vFileNames = uListToVector(fileNames_);
std::sort(vFileNames.begin(), vFileNames.end(), sortCallback);
fileNames_ = uVectorToList(vFileNames);
}
#else
int nameListSize;
struct dirent ** nameList = 0;
nameListSize = scandir(path_.c_str(), &nameList, 0, sortCallback);
if(nameList && nameListSize>0)
{
for (int i=0;i<nameListSize;++i)
{
fileNames_.push_back(nameList[i]->d_name);
free(nameList[i]);
}
free(nameList);
}
#endif
//filter extensions...
std::list<std::string>::iterator iter = fileNames_.begin();
bool valid;
while(iter!=fileNames_.end())
{
valid = false;
if(extensions_.size() == 0 &&
iter->compare(".") != 0 &&
iter->compare("..") != 0)
{
valid = true;
}
for(unsigned int i=0; i<extensions_.size(); ++i)
{
if(UFile::getExtension(*iter).compare(extensions_[i]) == 0)
{
valid = true;
break;
}
}
if(!valid)
{
iter = fileNames_.erase(iter);
}
else
{
++iter;
}
}
iFileName_ = fileNames_.begin();
if(!lastName.empty())
{
bool found = false;
for(std::list<std::string>::iterator iter=fileNames_.begin(); iter!=fileNames_.end(); ++iter)
{
if(lastName.compare(*iter) == 0)
{
found = true;
iFileName_ = iter;
break;
}
}
if(endOfDir && found)
{
++iFileName_;
}
else if(endOfDir && fileNames_.size())
{
iFileName_ = --fileNames_.end();
}
}
}
}
bool UDirectory::isValid()
{
return exists(path_);
}
std::string UDirectory::getNextFileName()
{
std::string fileName;
if(iFileName_ != fileNames_.end())
{
fileName = *iFileName_;
++iFileName_;
}
return fileName;
}
std::string UDirectory::getNextFilePath()
{
std::string filePath;
if(iFileName_ != fileNames_.end())
{
filePath = path_+separator()+*iFileName_;
++iFileName_;
}
return filePath;
}
void UDirectory::rewind()
{
iFileName_ = fileNames_.begin();
}
bool UDirectory::exists(const std::string & dirPath)
{
bool r = false;
#ifdef _WIN32
#ifdef UNICODE
wchar_t * wDirPath = createWCharFromChar(dirPath.c_str());
DWORD dwAttrib = GetFileAttributes(wDirPath);
delete [] wDirPath;
#else
DWORD dwAttrib = GetFileAttributes(dirPath.c_str());
#endif
r = (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
#else
DIR *dp;
if((dp = opendir(dirPath.c_str())) != NULL)
{
r = true;
closedir(dp);
}
#endif
return r;
}
// return the directory path of the file
std::string UDirectory::getDir(const std::string & filePath)
{
std::string dir = filePath;
int i=(int)dir.size()-1;
for(; i>=0; --i)
{
if(dir[i] == '/' || dir[i] == '\\')
{
//remove separators...
dir[i] = 0;
--i;
while(i>=0 && (dir[i] == '/' || dir[i] == '\\'))
{
dir[i] = 0;
--i;
}
break;
}
else
{
dir[i] = 0;
}
}
if(i<0)
{
dir = ".";
}
else
{
dir.resize(i+1);
}
return dir;
}
std::string UDirectory::currentDir(bool trailingSeparator)
{
std::string dir;
char * buffer;
#ifdef _WIN32
buffer = _getcwd(NULL, 0);
#else
buffer = getcwd(NULL, MAXPATHLEN);
#endif
if( buffer != NULL )
{
dir = buffer;
free(buffer);
if(trailingSeparator)
{
dir += separator();
}
}
return dir;
}
bool UDirectory::makeDir(const std::string & dirPath)
{
int status;
#ifdef _WIN32
status = _mkdir(dirPath.c_str());
#else
status = mkdir(dirPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
return status==0;
}
bool UDirectory::removeDir(const std::string & dirPath)
{
int status;
#ifdef _WIN32
status = _rmdir(dirPath.c_str());
#else
status = rmdir(dirPath.c_str());
#endif
return status==0;
}
std::string UDirectory::homeDir()
{
std::string path;
#ifdef _WIN32
#ifdef UNICODE
wchar_t wProfilePath[250];
ExpandEnvironmentStrings(L"%userprofile%",wProfilePath,250);
char * profilePath = createCharFromWChar(wProfilePath);
path = profilePath;
delete [] profilePath;
#else
char profilePath[250];
ExpandEnvironmentStrings("%userprofile%",profilePath,250);
path = profilePath;
#endif
#else
char * pathstr = getenv("HOME");
if(pathstr)
{
path = pathstr;
}
if(path.empty())
{
struct passwd *pw = getpwuid(getuid());
if(pw) {
path = pw->pw_dir;
}
if(path.empty())
{
UFATAL("Environment variable HOME is not set, cannot get home directory! Please set HOME environment variable to a valid directory.");
}
}
#endif
return path;
}
std::string UDirectory::separator()
{
#ifdef _WIN32
return "\\";
#else
return "/";
#endif
}
+36
View File
@@ -0,0 +1,36 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UEventsHandler.h"
#include "rtabmap/utilite/UEventsManager.h"
UEventsHandler::~UEventsHandler()
{
unregisterFromEventsManager();
}
void UEventsHandler::registerToEventsManager()
{
UEventsManager::addHandler(this);
}
void UEventsHandler::unregisterFromEventsManager()
{
UEventsManager::removeHandler(this);
}
+476
View File
@@ -0,0 +1,476 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UEventsManager.h"
#include "rtabmap/utilite/UEvent.h"
#include <list>
#include "rtabmap/utilite/UStl.h"
UEventsManager* UEventsManager::instance_ = 0;
UDestroyer<UEventsManager> UEventsManager::destroyer_;
void UEventsManager::addHandler(UEventsHandler* handler)
{
if(!handler)
{
UERROR("Handler is null!");
return;
}
else
{
UEventsManager::getInstance()->_addHandler(handler);
}
}
void UEventsManager::removeHandler(UEventsHandler* handler)
{
if(!handler)
{
UERROR("Handler is null!");
return;
}
else
{
UEventsManager::getInstance()->_removeHandler(handler);
}
}
void UEventsManager::post(UEvent * event, bool async, const UEventsSender * sender)
{
if(!event)
{
UERROR("Event is null!");
return;
}
else
{
UEventsManager::getInstance()->_postEvent(event, async, sender);
}
}
void UEventsManager::createPipe(
const UEventsSender * sender,
const UEventsHandler * receiver,
const std::string & eventName)
{
if(!sender || !receiver)
{
UERROR("Sender and/or receiver is null!");
return;
}
else
{
UEventsManager::getInstance()->_createPipe(sender, receiver, eventName);
}
}
void UEventsManager::removePipe(
const UEventsSender * sender,
const UEventsHandler * receiver,
const std::string & eventName)
{
if(!sender || !receiver)
{
UERROR("Sender and/or receiver is null!");
return;
}
else
{
UEventsManager::getInstance()->_removePipe(sender, receiver, eventName);
}
}
void UEventsManager::removeAllPipes(const UEventsSender * sender)
{
if(!sender)
{
UERROR("Sender is null!");
return;
}
else
{
UEventsManager::getInstance()->_removeAllPipes(sender);
}
}
void UEventsManager::removeNullPipes(const UEventsSender * sender)
{
if(!sender)
{
UERROR("Sender is null!");
return;
}
else
{
UEventsManager::getInstance()->_removeNullPipes(sender);
}
}
UEventsManager* UEventsManager::getInstance()
{
if(!instance_)
{
instance_ = new UEventsManager();
destroyer_.setDoomed(instance_);
instance_->start(); // Start the thread
}
return instance_;
}
UEventsManager::UEventsManager()
{
}
UEventsManager::~UEventsManager()
{
join(true);
// Free memory
for(std::list<std::pair<UEvent*, const UEventsSender*> >::iterator it=events_.begin(); it!=events_.end(); ++it)
{
delete it->first;
}
events_.clear();
handlers_.clear();
instance_ = 0;
}
void UEventsManager::mainLoop()
{
postEventSem_.acquire();
if(!this->isKilled())
{
dispatchEvents();
}
}
void UEventsManager::mainLoopKill()
{
postEventSem_.release();
}
void UEventsManager::dispatchEvents()
{
if(events_.size() == 0)
{
return;
}
std::list<std::pair<UEvent*, const UEventsSender*> >::iterator it;
std::list<std::pair<UEvent*, const UEventsSender*> > eventsBuf;
// Copy events in a buffer :
// Other threads can post events
// while events are handled.
eventsMutex_.lock();
{
eventsBuf = events_;
events_.clear();
}
eventsMutex_.unlock();
// Past events to handlers
for(it=eventsBuf.begin(); it!=eventsBuf.end(); ++it)
{
if(!dispatchEvent(it->first, it->second))
{
delete it->first;
}
}
eventsBuf.clear();
}
bool UEventsManager::dispatchEvent(UEvent * event, const UEventsSender * sender)
{
std::list<UEventsHandler*> handlers;
// Verify if there are pipes with the sender for his type of event
if(sender)
{
handlers = getPipes(sender, event->getClassName());
}
handlersMutex_.lock();
if(handlers.size() == 0)
{
//No pipes, send to all handlers
handlers = handlers_;
}
bool handled = false;
for(std::list<UEventsHandler*>::iterator it=handlers.begin(); it!=handlers.end() && !handled; ++it)
{
// Check if the handler is still in the
// handlers_ list (may be changed if addHandler() or
// removeHandler() is called in EventsHandler::handleEvent())
if(std::find(handlers_.begin(), handlers_.end(), *it) != handlers_.end())
{
UEventsHandler * handler = *it;
handlersMutex_.unlock();
// Don't process event if the handler is the same as the sender
if(handler != sender)
{
// To be able to add/remove an handler in a handleEvent call (without a deadlock)
// @see _addHandler(), _removeHandler()
handled = handler->handleEvent(event);
}
handlersMutex_.lock();
}
}
handlersMutex_.unlock();
return handled;
}
void UEventsManager::_addHandler(UEventsHandler* handler)
{
if(!this->isKilled())
{
handlersMutex_.lock();
{
//make sure it is not already in the list
bool handlerFound = false;
for(std::list<UEventsHandler*>::iterator it=handlers_.begin(); it!=handlers_.end(); ++it)
{
if(*it == handler)
{
handlerFound = true;
}
}
if(!handlerFound)
{
handlers_.push_back(handler);
}
}
handlersMutex_.unlock();
}
}
void UEventsManager::_removeHandler(UEventsHandler* handler)
{
if(!this->isKilled())
{
handlersMutex_.lock();
{
for (std::list<UEventsHandler*>::iterator it = handlers_.begin(); it!=handlers_.end(); ++it)
{
if(*it == handler)
{
handlers_.erase(it);
break;
}
}
}
handlersMutex_.unlock();
pipesMutex_.lock();
{
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!= pipes_.end(); ++iter)
{
if(iter->receiver_ == handler)
{
iter->receiver_ = 0; // set to null
}
}
}
pipesMutex_.unlock();
}
}
void UEventsManager::_postEvent(UEvent * event, bool async, const UEventsSender * sender)
{
if(!this->isKilled())
{
if(async)
{
eventsMutex_.lock();
{
events_.push_back(std::make_pair(event, sender));
}
eventsMutex_.unlock();
// Signal the EventsManager that an Event is added
postEventSem_.release();
}
else
{
if(!dispatchEvent(event, sender))
{
delete event;
}
}
}
else
{
delete event;
}
}
std::list<UEventsHandler*> UEventsManager::getPipes(
const UEventsSender * sender,
const std::string & eventName)
{
std::list<UEventsHandler*> pipes;
pipesMutex_.lock();
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!= pipes_.end(); ++iter)
{
if(iter->sender_ == sender && iter->eventName_.compare(eventName) == 0)
{
bool added = false;
if(iter->receiver_)
{
handlersMutex_.lock();
for(std::list<UEventsHandler*>::iterator jter=handlers_.begin(); jter!=handlers_.end(); ++jter)
{
if(*jter == iter->receiver_)
{
pipes.push_back(*jter);
added = true;
break;
}
}
handlersMutex_.unlock();
}
if(!added)
{
// Add nulls
pipes.push_back(0);
}
}
}
pipesMutex_.unlock();
return pipes;
}
void UEventsManager::_createPipe(
const UEventsSender * sender,
const UEventsHandler * receiver,
const std::string & eventName)
{
pipesMutex_.lock();
bool exist = false;
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!= pipes_.end();++iter)
{
if(iter->sender_ == sender && iter->receiver_ == receiver && iter->eventName_.compare(eventName) == 0)
{
exist = true;
break;
}
}
if(!exist)
{
bool handlerFound = false;
handlersMutex_.lock();
for(std::list<UEventsHandler*>::iterator iter=handlers_.begin(); iter!=handlers_.end(); ++iter)
{
if(*iter == receiver)
{
handlerFound = true;
break;
}
}
handlersMutex_.unlock();
if(handlerFound)
{
pipes_.push_back(Pipe(sender, receiver, eventName));
}
else
{
UERROR("Cannot create the pipe because the receiver is not yet "
"added to UEventsManager's handlers list.");
}
}
else
{
UWARN("Pipe between sender %p and receiver %p with event %s was already created.",
sender, receiver, eventName.c_str());
}
pipesMutex_.unlock();
}
void UEventsManager::_removePipe(
const UEventsSender * sender,
const UEventsHandler * receiver,
const std::string & eventName)
{
pipesMutex_.lock();
bool removed = false;
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!= pipes_.end();)
{
if(iter->sender_ == sender && iter->receiver_ == receiver && iter->eventName_.compare(eventName) == 0)
{
iter = pipes_.erase(iter);
removed = true;
}
else
{
++iter;
}
}
if(!removed)
{
UWARN("Pipe between sender %p and receiver %p with event %s didn't exist.",
sender, receiver, eventName.c_str());
}
pipesMutex_.unlock();
}
void UEventsManager::_removeAllPipes(const UEventsSender * sender)
{
pipesMutex_.lock();
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!=pipes_.end();)
{
if(iter->sender_ == sender)
{
iter = pipes_.erase(iter);
}
else
{
++iter;
}
}
pipesMutex_.unlock();
}
void UEventsManager::_removeNullPipes(const UEventsSender * sender)
{
pipesMutex_.lock();
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!=pipes_.end();)
{
if(iter->receiver_ == 0)
{
iter = pipes_.erase(iter);
}
else
{
++iter;
}
}
pipesMutex_.unlock();
}
+31
View File
@@ -0,0 +1,31 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UEventsSender.h"
#include "rtabmap/utilite/UEventsManager.h"
UEventsSender::~UEventsSender()
{
UEventsManager::removeAllPipes(this);
}
void UEventsSender::post(UEvent * event, bool async) const
{
UEventsManager::post(event, async, this);
}
+103
View File
@@ -0,0 +1,103 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UFile.h"
#include <fstream>
#include "rtabmap/utilite/UStl.h"
bool UFile::exists(const std::string &filePath)
{
bool fileExists = false;
std::ifstream in(filePath.c_str(), std::ios::in);
if (in.is_open())
{
fileExists = true;
in.close();
}
return fileExists;
}
long UFile::length(const std::string &filePath)
{
long fileSize = 0;
FILE* fp = 0;
#ifdef _MSC_VER
fopen_s(&fp, filePath.c_str(), "rb");
#else
fp = fopen(filePath.c_str(), "rb");
#endif
if(fp == NULL)
{
return 0;
}
fseek(fp , 0 , SEEK_END);
fileSize = ftell(fp);
fclose(fp);
return fileSize;
}
int UFile::erase(const std::string &filePath)
{
return std::remove(filePath.c_str());
}
int UFile::rename(const std::string &oldFilePath,
const std::string &newFilePath)
{
return std::rename(oldFilePath.c_str(), newFilePath.c_str());
}
std::string UFile::getName(const std::string & filePath)
{
std::string fullPath = filePath;
std::string name;
for(int i=(int)fullPath.size()-1; i>=0; --i)
{
if(fullPath[i] == '/' || fullPath[i] == '\\')
{
break;
}
else
{
name.insert(name.begin(), fullPath[i]);
}
}
return name;
}
std::string UFile::getExtension(const std::string &filePath)
{
std::list<std::string> list = uSplit(filePath, '.');
if(list.size())
{
return list.back();
}
return "";
}
void UFile::copy(const std::string & from, const std::string & to)
{
std::ifstream src(from.c_str());
std::ofstream dst(to.c_str());
dst << src.rdbuf();
}
+669
View File
@@ -0,0 +1,669 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/ULogger.h"
#include "rtabmap/utilite/UConversion.h"
#include "rtabmap/utilite/UFile.h"
#include "rtabmap/utilite/UStl.h"
#include "rtabmap/utilite/UEventsManager.h"
#include <fstream>
#include <string>
#include <string.h>
#ifndef _WIN32
#include <sys/time.h>
#endif
#ifdef _WIN32
#include <Windows.h>
#define COLOR_NORMAL FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
#define COLOR_RED FOREGROUND_RED | FOREGROUND_INTENSITY
#define COLOR_GREEN FOREGROUND_GREEN
#define COLOR_YELLOW FOREGROUND_GREEN | FOREGROUND_RED
#else
#define COLOR_NORMAL "\033[0m"
#define COLOR_RED "\033[31m"
#define COLOR_GREEN "\033[32m"
#define COLOR_YELLOW "\033[33m"
#endif
bool ULogger::append_ = true;
bool ULogger::printTime_ = true;
bool ULogger::printLevel_ = true;
bool ULogger::printEndline_ = true;
bool ULogger::printColored_ = true;
bool ULogger::printWhere_ = true;
bool ULogger::printWhereFullPath_ = false;
bool ULogger::printThreadID_ = false;
bool ULogger::limitWhereLength_ = false;
bool ULogger::buffered_ = false;
ULogger::Level ULogger::level_ = kInfo; // By default, we show all info msgs + upper level (Warning, Error)
ULogger::Level ULogger::eventLevel_ = kFatal;
const char * ULogger::levelName_[5] = {"DEBUG", " INFO", " WARN", "ERROR", "FATAL"};
ULogger* ULogger::instance_ = 0;
UDestroyer<ULogger> ULogger::destroyer_;
ULogger::Type ULogger::type_ = ULogger::kTypeNoLog; // Default nothing
UMutex ULogger::loggerMutex_;
const std::string ULogger::kDefaultLogFileName = "./ULog.txt";
std::string ULogger::logFileName_;
std::string ULogger::bufferedMsgs_;
std::set<unsigned long> ULogger::threadIdFilter_;
std::map<std::string, unsigned long> ULogger::registeredThreads_;
/**
* This class is used to write logs in the console. This class cannot
* be directly used, use ULogger::setType() to console type to print in
* console and use macro UDEBUG(), UINFO()... to print messages.
* @see ULogger
*/
class UConsoleLogger : public ULogger
{
public :
virtual ~UConsoleLogger() {this->_flush();}
protected:
/**
* Only the Logger can create inherited
* loggers according to the Abstract factory patterns.
*/
friend class ULogger;
UConsoleLogger() {}
private:
virtual void _write(const char* msg, va_list arg)
{
vprintf(msg, arg);
}
virtual void _writeStr(const char* msg)
{
printf("%s", msg);
}
};
/**
* This class is used to write logs in a file. This class cannot
* be directly used, use ULogger::setType() to file type to print in
* a file and use macro UDEBUG(), UINFO()... to print messages.
* @see ULogger
*/
class UFileLogger : public ULogger
{
public:
virtual ~UFileLogger()
{
this->_flush();
if(fout_)
{
fclose(fout_);
}
}
protected:
/**
* Only the Logger can create inherited
* loggers according to the Abstract factory patterns.
*/
friend class ULogger;
/**
* The UFileLogger constructor.
* @param fileName the file name
* @param append if true append logs in the file,
* ortherwise it overrides the file.
*
*/
UFileLogger(const std::string &fileName, bool append)
{
fileName_ = fileName;
if(!append) {
std::ofstream fileToClear(fileName_.c_str(), std::ios::out);
fileToClear.clear();
fileToClear.close();
}
#ifdef _MSC_VER
fopen_s(&fout_, fileName_.c_str(), "a");
#else
fout_ = fopen(fileName_.c_str(), "a");
#endif
if(!fout_) {
printf("FileLogger : Cannot open file : %s\n", fileName_.c_str()); // TODO send Event instead, or return error code
return;
}
}
private:
virtual void _write(const char* msg, va_list arg)
{
if(fout_)
{
vfprintf(fout_, msg, arg);
}
}
virtual void _writeStr(const char* msg)
{
if(fout_)
{
fprintf(fout_, "%s", msg);
}
}
private:
std::string fileName_; ///< the file name
FILE* fout_;
std::string bufferedMsgs_;
};
void ULogger::setType(Type type, const std::string &fileName, bool append)
{
ULogger::flush();
loggerMutex_.lock();
{
// instance not yet created
if(!instance_)
{
type_ = type;
logFileName_ = fileName;
append_ = append;
instance_ = createInstance();
}
// type changed
else if(type_ != type || (type_ == kTypeFile && logFileName_.compare(fileName)!=0))
{
destroyer_.setDoomed(0);
delete instance_;
instance_ = 0;
type_ = type;
logFileName_ = fileName;
append_ = append;
instance_ = createInstance();
}
}
loggerMutex_.unlock();
}
void ULogger::setTreadIdFilter(const std::vector<std::string> & ids)
{
loggerMutex_.lock();
threadIdFilter_.clear();
for(unsigned int i=0;i<ids.size();++i)
{
if(registeredThreads_.find(ids[i]) != registeredThreads_.end())
{
threadIdFilter_.insert(registeredThreads_.at(ids[i]));
}
}
loggerMutex_.unlock();
}
void ULogger::registerCurrentThread(const std::string & name)
{
loggerMutex_.lock();
UASSERT(!name.empty());
uInsert(registeredThreads_, std::make_pair(name, UThread::currentThreadId()));
loggerMutex_.unlock();
}
void ULogger::unregisterCurrentThread()
{
loggerMutex_.lock();
unsigned long id = UThread::currentThreadId();
for(std::map<std::string, unsigned long>::iterator iter=registeredThreads_.begin(); iter!=registeredThreads_.end();)
{
if(iter->second == id)
{
registeredThreads_.erase(iter++);
threadIdFilter_.erase(id);
}
else
{
++iter;
}
}
loggerMutex_.unlock();
}
std::map<std::string, unsigned long> ULogger::getRegisteredThreads()
{
loggerMutex_.lock();
std::map<std::string, unsigned long> out = registeredThreads_;
loggerMutex_.unlock();
return out;
}
void ULogger::reset()
{
ULogger::setType(ULogger::kTypeNoLog);
append_ = true;
printTime_ = true;
printLevel_ = true;
printEndline_ = true;
printColored_ = true;
printWhere_ = true;
printWhereFullPath_ = false;
printThreadID_ = false;
limitWhereLength_ = false;
level_ = kInfo; // By default, we show all info msgs + upper level (Warning, Error)
logFileName_ = ULogger::kDefaultLogFileName;
}
void ULogger::setBuffered(bool buffered)
{
if(!buffered)
{
ULogger::flush();
}
buffered_ = buffered;
}
void ULogger::flush()
{
loggerMutex_.lock();
if(!instance_ || bufferedMsgs_.size()==0)
{
loggerMutex_.unlock();
return;
}
instance_->_flush();
loggerMutex_.unlock();
}
void ULogger::_flush()
{
ULogger::getInstance()->_writeStr(bufferedMsgs_.c_str());
bufferedMsgs_.clear();
}
void ULogger::write(const char* msg, ...)
{
loggerMutex_.lock();
if(!instance_)
{
loggerMutex_.unlock();
return;
}
std::string endline = "";
if(printEndline_) {
endline = "\r\n";
}
std::string time = "";
if(printTime_)
{
getTime(time);
time.append(" - ");
}
if(printTime_)
{
if(buffered_)
{
bufferedMsgs_.append(time.c_str());
}
else
{
ULogger::getInstance()->_writeStr(time.c_str());
}
}
va_list args;
va_start(args, msg);
if(buffered_)
{
bufferedMsgs_.append(uFormatv(msg, args));
}
else
{
ULogger::getInstance()->_write(msg, args);
}
va_end(args);
if(printEndline_)
{
if(buffered_)
{
bufferedMsgs_.append(endline.c_str());
}
else
{
ULogger::getInstance()->_writeStr(endline.c_str());
}
}
loggerMutex_.unlock();
}
void ULogger::write(ULogger::Level level,
const char * file,
int line,
const char * function,
const char* msg,
...)
{
loggerMutex_.lock();
if(type_ == kTypeNoLog && level < kFatal && level < eventLevel_)
{
loggerMutex_.unlock();
return;
}
if(strlen(msg) == 0 && !printWhere_ && level < kFatal)
{
loggerMutex_.unlock();
// No need to show an empty message if we don't print where.
return;
}
if(level < kFatal &&
threadIdFilter_.size() &&
threadIdFilter_.find(UThread::currentThreadId()) == threadIdFilter_.end())
{
loggerMutex_.unlock();
return;
}
if(level >= level_ || level >= eventLevel_)
{
#ifdef _WIN32
int color = 0;
#else
const char* color = NULL;
#endif
switch(level)
{
case kDebug:
color = COLOR_GREEN;
break;
case kInfo:
color = COLOR_NORMAL;
break;
case kWarning:
color = COLOR_YELLOW;
break;
case kError:
case kFatal:
color = COLOR_RED;
break;
default:
break;
}
std::string endline = "";
if(printEndline_) {
endline = "\r\n";
}
std::string time = "";
if(printTime_ || level == kFatal)
{
time.append("(");
getTime(time);
time.append(") ");
}
std::string levelStr = "";
if(printLevel_ || level == kFatal)
{
const int bufSize = 30;
char buf[bufSize] = {0};
#ifdef _MSC_VER
sprintf_s(buf, bufSize, "[%s]", levelName_[level]);
#else
snprintf(buf, bufSize, "[%s]", levelName_[level]);
#endif
levelStr = buf;
levelStr.append(" ");
}
std::string pidStr;
if(printThreadID_)
{
pidStr = uFormat("{%lu} ", UThread::currentThreadId());
}
std::string whereStr = "";
if(printWhere_ || level == kFatal)
{
whereStr.append("");
//File
if(printWhereFullPath_)
{
whereStr.append(file);
}
else
{
std::string fileName = UFile::getName(file);
if(limitWhereLength_ && fileName.size() > 8)
{
fileName.erase(8);
fileName.append("~");
}
whereStr.append(fileName);
}
//Line
whereStr.append(":");
std::string lineStr = uNumber2Str(line);
whereStr.append(lineStr);
//Function
whereStr.append("::");
std::string funcStr = function;
if(!printWhereFullPath_ && limitWhereLength_ && funcStr.size() > 8)
{
funcStr.erase(8);
funcStr.append("~");
}
funcStr.append("()");
whereStr.append(funcStr);
whereStr.append(" ");
}
va_list args;
if(type_ != kTypeNoLog)
{
va_start(args, msg);
#ifdef _WIN32
HANDLE H = GetStdHandle(STD_OUTPUT_HANDLE);
#endif
if(type_ == ULogger::kTypeConsole && printColored_)
{
#ifdef _WIN32
SetConsoleTextAttribute(H,color);
#else
if(buffered_)
{
bufferedMsgs_.append(color);
}
else
{
ULogger::getInstance()->_writeStr(color);
}
#endif
}
if(buffered_)
{
bufferedMsgs_.append(levelStr.c_str());
bufferedMsgs_.append(pidStr.c_str());
bufferedMsgs_.append(time.c_str());
bufferedMsgs_.append(whereStr.c_str());
bufferedMsgs_.append(uFormatv(msg, args));
}
else
{
ULogger::getInstance()->_writeStr(levelStr.c_str());
ULogger::getInstance()->_writeStr(pidStr.c_str());
ULogger::getInstance()->_writeStr(time.c_str());
ULogger::getInstance()->_writeStr(whereStr.c_str());
ULogger::getInstance()->_write(msg, args);
}
if(type_ == ULogger::kTypeConsole && printColored_)
{
#ifdef _WIN32
SetConsoleTextAttribute(H,COLOR_NORMAL);
#else
if(buffered_)
{
bufferedMsgs_.append(COLOR_NORMAL);
}
else
{
ULogger::getInstance()->_writeStr(COLOR_NORMAL);
}
#endif
}
if(buffered_)
{
bufferedMsgs_.append(endline.c_str());
}
else
{
ULogger::getInstance()->_writeStr(endline.c_str());
}
va_end (args);
}
if(level >= eventLevel_)
{
std::string fullMsg = uFormat("%s%s%s%s", levelStr.c_str(), pidStr.c_str(), time.c_str(), whereStr.c_str());
va_start(args, msg);
fullMsg.append(uFormatv(msg, args));
va_end(args);
if(level >= kFatal)
{
// Send it synchronously, then receivers
// can do something before the code (exiting) below is executed.
UEventsManager::post(new ULogEvent(fullMsg, kFatal), false);
}
else
{
UEventsManager::post(new ULogEvent(fullMsg, level));
}
}
if(level >= kFatal)
{
std::string fullMsg = uFormat("%s%s%s%s", levelStr.c_str(), pidStr.c_str(), time.c_str(), whereStr.c_str());
va_start(args, msg);
fullMsg.append(uFormatv(msg, args));
va_end(args);
if(instance_)
{
destroyer_.setDoomed(0);
delete instance_; // If a FileLogger is used, this will close the file.
instance_ = 0;
}
//========================================================================
// Throw exception
loggerMutex_.unlock();
throw UException(fullMsg);
//========================================================================
}
}
loggerMutex_.unlock();
}
int ULogger::getTime(std::string &timeStr)
{
struct tm timeinfo;
const int bufSize = 30;
char buf[bufSize] = {0};
#if _MSC_VER
time_t rawtime;
time(&rawtime);
localtime_s (&timeinfo, &rawtime );
int result = sprintf_s(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d",
timeinfo.tm_year+1900,
(timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1,
(timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday,
(timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour,
(timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min,
(timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec);
#elif WIN32
time_t rawtime;
time(&rawtime);
timeinfo = *localtime (&rawtime);
int result = snprintf(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d",
timeinfo.tm_year+1900,
(timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1,
(timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday,
(timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour,
(timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min,
(timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec);
#else
struct timeval rawtime;
gettimeofday(&rawtime, NULL);
localtime_r (&rawtime.tv_sec, &timeinfo);
int result = snprintf(buf, bufSize, "%d-%s%d-%s%d %s%d:%s%d:%s%d.%s%d",
timeinfo.tm_year+1900,
(timeinfo.tm_mon+1) < 10 ? "0":"", timeinfo.tm_mon+1,
(timeinfo.tm_mday) < 10 ? "0":"", timeinfo.tm_mday,
(timeinfo.tm_hour) < 10 ? "0":"", timeinfo.tm_hour,
(timeinfo.tm_min) < 10 ? "0":"", timeinfo.tm_min,
(timeinfo.tm_sec) < 10 ? "0":"", timeinfo.tm_sec,
(rawtime.tv_usec/1000) < 10 ? "00":(rawtime.tv_usec/1000) < 100?"0":"", int(rawtime.tv_usec/1000));
#endif
if(result)
{
timeStr.append(buf);
}
return result;
}
ULogger* ULogger::getInstance()
{
if(!instance_)
{
instance_ = createInstance();
}
return instance_;
}
ULogger* ULogger::createInstance()
{
ULogger* instance = 0;
if(type_ == ULogger::kTypeConsole)
{
instance = new UConsoleLogger();
}
else if(type_ == ULogger::kTypeFile)
{
instance = new UFileLogger(logFileName_, append_);
}
destroyer_.setDoomed(instance);
return instance;
}
ULogger::~ULogger()
{
instance_ = 0;
//printf("Logger is destroyed...\n\r");
}
+78
View File
@@ -0,0 +1,78 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UProcessInfo.h"
#ifdef _WIN32
#include "Windows.h"
#include "Psapi.h"
#elif __APPLE__
#include <sys/resource.h>
#else
#include <fstream>
#include <stdlib.h>
#include "rtabmap/utilite/UStl.h"
#endif
UProcessInfo::UProcessInfo() {}
UProcessInfo::~UProcessInfo() {}
// return in bytes
long int UProcessInfo::getMemoryUsage()
{
long int memoryUsage = -1;
#ifdef _WIN32
HANDLE hProc = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS info;
BOOL okay = GetProcessMemoryInfo(hProc, &info, sizeof(info));
if(okay)
{
memoryUsage = info.WorkingSetSize;
}
#elif __APPLE__
rusage u;
if(getrusage(RUSAGE_SELF, &u) == 0)
{
memoryUsage = u.ru_maxrss;
}
#else
std::fstream file("/proc/self/status", std::fstream::in);
if(file.is_open())
{
std::string bytes;
while(std::getline(file, bytes))
{
if(bytes.find("VmRSS") != bytes.npos)
{
std::list<std::string> strs = uSplit(bytes, ' ');
if(strs.size()>1)
{
memoryUsage = atol(uValueAt(strs,1).c_str()) * 1024;
}
break;
}
}
file.close();
}
#endif
return memoryUsage;
}
+301
View File
@@ -0,0 +1,301 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UThread.h"
#include "rtabmap/utilite/ULogger.h"
#ifdef __APPLE__
#include <mach/thread_policy.h>
#include <mach/mach.h>
#endif
#define PRINT_DEBUG 0
////////////////////////////
// public:
////////////////////////////
UThread::UThread(Priority priority) :
state_(kSIdle),
priority_(priority),
handle_(0),
threadId_(0),
cpuAffinity_(-1)
{}
UThread::~UThread()
{
#if PRINT_DEBUG
ULOGGER_DEBUG("");
#endif
}
void UThread::kill()
{
#if PRINT_DEBUG
ULOGGER_DEBUG("");
#endif
killSafelyMutex_.lock();
{
if(this->isRunning())
{
// Thread is creating
while(state_ == kSCreating)
{
uSleep(1);
}
if(state_ == kSRunning)
{
state_ = kSKilled;
// Call function to do something before wait
mainLoopKill();
}
else
{
UERROR("thread (%d) is supposed to be running...", threadId_);
}
}
else
{
#if PRINT_DEBUG
UDEBUG("thread (%d) is not running...", threadId_);
#endif
}
}
killSafelyMutex_.unlock();
}
void UThread::join(bool killFirst)
{
//make sure the thread is created
while(this->isCreating())
{
uSleep(1);
}
#ifdef _WIN32
#if PRINT_DEBUG
UDEBUG("Thread %d joining %d", UThreadC<void>::Self(), threadId_);
#endif
if(UThreadC<void>::Self() == threadId_)
#else
#if PRINT_DEBUG
UDEBUG("Thread %d joining %d", UThreadC<void>::Self(), handle_);
#endif
if(UThreadC<void>::Self() == handle_)
#endif
{
UERROR("Thread cannot join itself");
return;
}
if(killFirst)
{
this->kill();
}
runningMutex_.lock();
runningMutex_.unlock();
#if PRINT_DEBUG
UDEBUG("Join ended for %d", UThreadC<void>::Self());
#endif
}
void UThread::start()
{
#if PRINT_DEBUG
ULOGGER_DEBUG("");
#endif
if(state_ == kSIdle || state_ == kSKilled)
{
if(state_ == kSKilled)
{
// make sure it is finished
runningMutex_.lock();
runningMutex_.unlock();
}
state_ = kSCreating;
int r = UThreadC<void>::Create(threadId_, &handle_, true); // Create detached
if(r)
{
UERROR("Failed to create a thread! errno=%d", r);
threadId_=0;
handle_=0;
state_ = kSIdle;
}
else
{
#if PRINT_DEBUG
ULOGGER_DEBUG("StateThread::startThread() thread id=%d _handle=%d", threadId_, handle_);
#endif
}
}
}
//TODO : Support pThread
void UThread::setPriority(Priority priority)
{
priority_ = priority;
}
//TODO : Support pThread
void UThread::applyPriority()
{
if(handle_)
{
#ifdef _WIN32
int p = THREAD_PRIORITY_NORMAL;
switch(priority_)
{
case kPLow:
p = THREAD_PRIORITY_LOWEST;
break;
case kPBelowNormal:
p = THREAD_PRIORITY_BELOW_NORMAL;
break;
case kPNormal:
p = THREAD_PRIORITY_NORMAL;
break;
case kPAboveNormal:
p = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case kPRealTime:
p = THREAD_PRIORITY_TIME_CRITICAL;
break;
default:
break;
}
SetThreadPriority(handle_, p);
#endif
}
}
void UThread::setAffinity(int cpu)
{
cpuAffinity_ = cpu;
if(cpuAffinity_<0)
{
cpuAffinity_ = 0;
}
}
//TODO : Support Windows and linux
void UThread::applyAffinity()
{
if(cpuAffinity_>0)
{
#ifdef _WIN32
#elif __APPLE__
thread_affinity_policy_data_t affPolicy;
affPolicy.affinity_tag = cpuAffinity_;
kern_return_t ret = thread_policy_set(
mach_thread_self(),
THREAD_AFFINITY_POLICY,
(integer_t*) &affPolicy,
THREAD_AFFINITY_POLICY_COUNT);
if(ret != KERN_SUCCESS)
{
UERROR("thread_policy_set returned %d", ret);
}
#else
/*unsigned long mask = cpuAffinity_;
if (pthread_setaffinity_np(
pthread_self(),
sizeof(mask),
&mask) <0)
{
UERROR("pthread_setaffinity_np failed");
}
}*/
#endif
}
}
bool UThread::isCreating() const
{
return state_ == kSCreating;
}
bool UThread::isRunning() const
{
return state_ == kSRunning || state_ == kSCreating;
}
bool UThread::isIdle() const
{
return state_ == kSIdle;
}
bool UThread::isKilled() const
{
return state_ == kSKilled;
}
////////////////////////////
// private:
////////////////////////////
void UThread::ThreadMain()
{
runningMutex_.lock();
applyPriority();
applyAffinity();
#if PRINT_DEBUG
ULOGGER_DEBUG("before mainLoopBegin()");
#endif
state_ = kSRunning;
mainLoopBegin();
#if PRINT_DEBUG
ULOGGER_DEBUG("before mainLoop()");
#endif
while(state_ == kSRunning)
{
mainLoop();
}
#if PRINT_DEBUG
ULOGGER_DEBUG("before mainLoopEnd()");
#endif
mainLoopEnd();
handle_ = 0;
threadId_ = 0;
state_ = kSIdle;
runningMutex_.unlock();
#if PRINT_DEBUG
ULOGGER_DEBUG("Exiting thread loop");
#endif
}
+122
View File
@@ -0,0 +1,122 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UTimer.h"
#include "rtabmap/utilite/ULogger.h"
///////////////////////
// public:
///////////////////////
UTimer::UTimer()
{
#ifdef _WIN32
QueryPerformanceFrequency(&frequency_);
#endif
start(); // This will initialize the private counters
}
UTimer::~UTimer() {}
#ifdef _WIN32
double UTimer::now()
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
FILETIME ft;
GetSystemTimePreciseAsFileTime(&ft);
__int64* val = (__int64*)&ft;
return static_cast<double>(*val) / 10000000.0 - 11644473600.0; // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970.
#else
LARGE_INTEGER count, freq;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&count);
return double(count.QuadPart) / freq.QuadPart;
#endif
}
void UTimer::start()
{
QueryPerformanceCounter(&startTimeRecorded_);
stopTimeRecorded_ = startTimeRecorded_;
}
void UTimer::stop()
{
QueryPerformanceCounter(&stopTimeRecorded_);
}
double UTimer::getElapsedTime()
{
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return double(now.QuadPart - startTimeRecorded_.QuadPart) / frequency_.QuadPart;
}
double UTimer::getInterval()
{
if(stopTimeRecorded_.QuadPart == startTimeRecorded_.QuadPart)
{
return getElapsedTime();
}
else
{
return double(stopTimeRecorded_.QuadPart - startTimeRecorded_.QuadPart) / frequency_.QuadPart;
}
}
#else
double UTimer::now()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return double(tv.tv_sec) + double(tv.tv_usec) / 1000000.0;
}
void UTimer::start()
{
gettimeofday(&startTimeRecorded_, NULL);
stopTimeRecorded_ = startTimeRecorded_;
}
void UTimer::stop()
{
gettimeofday(&stopTimeRecorded_, NULL);
}
double UTimer::getElapsedTime()
{
return UTimer::now() - (double(startTimeRecorded_.tv_sec) + double(startTimeRecorded_.tv_usec) / 1000000.0);
}
double UTimer::getInterval()
{
if(startTimeRecorded_.tv_sec == stopTimeRecorded_.tv_sec && startTimeRecorded_.tv_usec == stopTimeRecorded_.tv_usec)
{
return getElapsedTime();
}
else
{
double start = double(startTimeRecorded_.tv_sec) + double(startTimeRecorded_.tv_usec) / 1000000.0;
double stop = double(stopTimeRecorded_.tv_sec) + double(stopTimeRecorded_.tv_usec) / 1000000.0;
return stop - start;
}
}
#endif
double UTimer::ticks() // Stop->start and return Interval
{
double inter = elapsed();
start();
return inter;
}
+870
View File
@@ -0,0 +1,870 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite 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. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UVariant.h"
#include "rtabmap/utilite/UConversion.h"
#include <limits>
#include <string.h>
UVariant::UVariant() :
type_(kUndef)
{
}
UVariant::UVariant(const bool & value) :
type_(kBool),
data_(1)
{
data_[0] = value?1:0;
}
UVariant::UVariant(const signed char & value) :
type_(kChar),
data_(sizeof(signed char))
{
memcpy(data_.data(), &value, sizeof(signed char));
}
UVariant::UVariant(const unsigned char & value) :
type_(kUChar),
data_(sizeof(unsigned char))
{
memcpy(data_.data(), &value, sizeof(unsigned char));
}
UVariant::UVariant(const short & value) :
type_(kShort),
data_(sizeof(short))
{
memcpy(data_.data(), &value, sizeof(short));
}
UVariant::UVariant(const unsigned short & value) :
type_(kUShort),
data_(sizeof(unsigned short))
{
memcpy(data_.data(), &value, sizeof(unsigned short));
}
UVariant::UVariant(const int & value) :
type_(kInt),
data_(sizeof(int))
{
memcpy(data_.data(), &value, sizeof(int));
}
UVariant::UVariant(const unsigned int & value) :
type_(kUInt),
data_(sizeof(unsigned int))
{
memcpy(data_.data(), &value, sizeof(unsigned int));
}
UVariant::UVariant(const float & value) :
type_(kFloat),
data_(sizeof(float))
{
memcpy(data_.data(), &value, sizeof(float));
}
UVariant::UVariant(const double & value) :
type_(kDouble),
data_(sizeof(double))
{
memcpy(data_.data(), &value, sizeof(double));
}
UVariant::UVariant(const char * value) :
type_(kStr)
{
std::string str(value);
data_.resize(str.size()+1);
memcpy(data_.data(), str.data(), str.size()+1);
}
UVariant::UVariant(const std::string & value) :
type_(kStr),
data_(value.size()+1) // with null character
{
memcpy(data_.data(), value.data(), value.size()+1);
}
UVariant::UVariant(const std::vector<signed char> & value) :
type_(kCharArray),
data_(sizeof(signed char)*value.size())
{
memcpy(data_.data(), value.data(), sizeof(signed char)*value.size());
}
UVariant::UVariant(const std::vector<unsigned char> & value) :
type_(kUCharArray),
data_(sizeof(unsigned char)*value.size())
{
memcpy(data_.data(), value.data(), sizeof(unsigned char)*value.size());
}
UVariant::UVariant(const std::vector<short> & value) :
type_(kShortArray),
data_(sizeof(short)*value.size())
{
memcpy(data_.data(), value.data(), sizeof(short)*value.size());
}
UVariant::UVariant(const std::vector<unsigned short> & value) :
type_(kUShortArray),
data_(sizeof(unsigned short)*value.size())
{
memcpy(data_.data(), value.data(), sizeof(unsigned short)*value.size());
}
UVariant::UVariant(const std::vector<int> & value) :
type_(kIntArray),
data_(sizeof(int)*value.size())
{
memcpy(data_.data(), value.data(), sizeof(int)*value.size());
}
UVariant::UVariant(const std::vector<unsigned int> & value) :
type_(kUIntArray),
data_(sizeof(unsigned int)*value.size())
{
memcpy(data_.data(), value.data(), sizeof(unsigned int)*value.size());
}
UVariant::UVariant(const std::vector<float> & value) :
type_(kFloatArray),
data_(sizeof(float)*value.size())
{
memcpy(data_.data(), value.data(), sizeof(float)*value.size());
}
UVariant::UVariant(const std::vector<double> & value) :
type_(kDoubleArray),
data_(sizeof(double)*value.size())
{
memcpy(data_.data(), value.data(), sizeof(double)*value.size());
}
bool UVariant::toBool() const
{
if(type_ ==kStr)
{
return uStr2Bool(toStr().c_str());
}
else if(data_.size())
{
return memcmp(data_.data(), std::vector<unsigned char>(data_.size(), 0).data(), data_.size()) != 0;
}
return false;
}
signed char UVariant::toChar(bool * ok) const
{
if(ok)
{
*ok = false;
}
signed char v = 0;
if(type_ == kChar)
{
memcpy(&v, data_.data(), sizeof(signed char));
if(ok)
{
*ok = true;
}
}
else if(type_ == kUChar)
{
unsigned char tmp = toUChar();
if(tmp <= std::numeric_limits<signed char>::max())
{
v = (signed char)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kShort)
{
short tmp = toShort();
if(tmp >= std::numeric_limits<signed char>::min() && tmp <= std::numeric_limits<signed char>::max())
{
v = (signed char)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kUShort)
{
unsigned short tmp = toUShort();
if(tmp <= std::numeric_limits<signed char>::max())
{
v = (signed char)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kInt)
{
int tmp = toInt();
if(tmp >= std::numeric_limits<signed char>::min() && tmp <= std::numeric_limits<signed char>::max())
{
v = (signed char)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kUInt)
{
unsigned int tmp = toUInt();
if(tmp <= (unsigned int)std::numeric_limits<signed char>::max())
{
v = (signed char)tmp;
if(ok)
{
*ok = true;
}
}
}
return v;
}
unsigned char UVariant::toUChar(bool * ok) const
{
if(ok)
{
*ok = false;
}
unsigned char v = 0;
if(type_ == kUChar)
{
memcpy(&v, data_.data(), sizeof(unsigned char));
if(ok)
{
*ok = true;
}
}
else if(type_ == kChar)
{
char tmp = toChar();
if(tmp >= std::numeric_limits<unsigned char>::min())
{
v = (unsigned char)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kShort)
{
short tmp = toShort();
if(tmp >= std::numeric_limits<unsigned char>::min() && tmp <= std::numeric_limits<unsigned char>::max())
{
v = (unsigned char)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kUShort)
{
unsigned short tmp = toUShort();
if(tmp >= std::numeric_limits<unsigned char>::min() && tmp <= std::numeric_limits<unsigned char>::max())
{
v = (unsigned char)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kInt)
{
int tmp = toInt();
if(tmp >= std::numeric_limits<unsigned char>::min() && tmp <= std::numeric_limits<unsigned char>::max())
{
v = (unsigned char)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kUInt)
{
unsigned int tmp = toUInt();
if(tmp <= std::numeric_limits<unsigned char>::max())
{
v = (unsigned char)tmp;
if(ok)
{
*ok = true;
}
}
}
return v;
}
short UVariant::toShort(bool * ok) const
{
if(ok)
{
*ok = false;
}
short v = 0;
if(type_ == kShort)
{
memcpy(&v, data_.data(), sizeof(short));
if(ok)
{
*ok = true;
}
}
else if(type_ == kChar)
{
v = (short)toChar();
if(ok)
{
*ok = true;
}
}
else if(type_ == kUChar)
{
v = (short)toUChar();
if(ok)
{
*ok = true;
}
}
else if(type_ == kUShort)
{
unsigned short tmp = toUShort();
if(tmp <= std::numeric_limits<short>::max())
{
v = (short)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kInt)
{
int tmp = toInt();
if(tmp >= std::numeric_limits<short>::min() && tmp <= std::numeric_limits<short>::max())
{
v = (short)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kUInt)
{
unsigned int tmp = toUInt();
if(tmp <= (unsigned int)std::numeric_limits<short>::max())
{
v = (short)tmp;
if(ok)
{
*ok = true;
}
}
}
return v;
}
unsigned short UVariant::toUShort(bool * ok) const
{
if(ok)
{
*ok = false;
}
unsigned short v = 0;
if(type_ == kUShort)
{
memcpy(&v, data_.data(), sizeof(unsigned short));
if(ok)
{
*ok = true;
}
}
else if(type_ == kChar)
{
signed char tmp = toChar();
if(tmp >= 0)
{
v = (unsigned short)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kUChar)
{
v = (unsigned short)toUChar();
if(ok)
{
*ok = true;
}
}
else if(type_ == kShort)
{
short tmp = toShort();
if(tmp >= std::numeric_limits<unsigned short>::min())
{
v = (unsigned short)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kInt)
{
int tmp = toInt();
if(tmp >= std::numeric_limits<unsigned short>::min() && tmp <= std::numeric_limits<unsigned short>::max())
{
v = (unsigned short)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kUInt)
{
unsigned int tmp = toUInt();
if(tmp <= std::numeric_limits<unsigned short>::max())
{
v = (unsigned short)tmp;
if(ok)
{
*ok = true;
}
}
}
return v;
}
int UVariant::toInt(bool * ok) const
{
if(ok)
{
*ok = false;
}
int v = 0;
if(type_ == kInt)
{
memcpy(&v, data_.data(), sizeof(int));
if(ok)
{
*ok = true;
}
}
else if(type_ == kChar)
{
v = (int)toChar();
if(ok)
{
*ok = true;
}
}
else if(type_ == kUChar)
{
v = (int)toUChar();
if(ok)
{
*ok = true;
}
}
else if(type_ == kShort)
{
v = (int)toShort();
if(ok)
{
*ok = true;
}
}
else if(type_ == kUShort)
{
v = (int)toUShort();
if(ok)
{
*ok = true;
}
}
else if(type_ == kUInt)
{
unsigned int tmp = toUInt();
if(tmp <= (unsigned int)std::numeric_limits<int>::max())
{
v = (int)tmp;
if(ok)
{
*ok = true;
}
}
}
return v;
}
unsigned int UVariant::toUInt(bool * ok) const
{
if(ok)
{
*ok = false;
}
unsigned int v = 0;
if(type_ == kUInt)
{
memcpy(&v, data_.data(), sizeof(unsigned int));
if(ok)
{
*ok = true;
}
}
else if(type_ == kChar)
{
signed char tmp = toChar();
if(tmp >= 0)
{
v = (unsigned int)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kUChar)
{
v = (unsigned int)toUChar();
if(ok)
{
*ok = true;
}
}
else if(type_ == kShort)
{
short tmp = toShort();
if(tmp >= 0)
{
v = (unsigned int)tmp;
if(ok)
{
*ok = true;
}
}
}
else if(type_ == kUShort)
{
v = (unsigned int)toUShort();
if(ok)
{
*ok = true;
}
}
else if(type_ == kInt)
{
int tmp = toInt();
if(tmp >= 0)
{
v = (unsigned int)tmp;
if(ok)
{
*ok = true;
}
}
}
return v;
}
float UVariant::toFloat(bool * ok) const
{
if(ok)
{
*ok = false;
}
float v = 0;
if(type_ == kFloat)
{
memcpy(&v, data_.data(), sizeof(float));
if(ok)
{
*ok = true;
}
}
else if(type_ == kDouble)
{
double tmp = toDouble();
if(tmp >= std::numeric_limits<float>::min() && tmp <= std::numeric_limits<float>::max())
{
v = (float)tmp;
if(ok)
{
*ok = true;
}
}
}
return v;
}
double UVariant::toDouble(bool * ok) const
{
if(ok)
{
*ok = false;
}
double v = 0;
if(type_ == kDouble)
{
memcpy(&v, data_.data(), sizeof(double));
if(ok)
{
*ok = true;
}
}
else if(type_ == kFloat)
{
v = (double)toFloat(ok);
}
return v;
}
std::string UVariant::toStr(bool * ok) const
{
if(ok)
{
*ok = false;
}
std::string v;
if(type_ == kStr)
{
v = std::string((const char *)data_.data());
if(ok)
{
*ok = true;
}
}
else if(type_ == kBool)
{
v = toBool()?"true":"false";
if(ok)
{
*ok = true;
}
}
else if(type_ == kChar)
{
v = " ";
v.at(0) = toChar(ok);
}
else if(type_ == kUChar)
{
v = uNumber2Str(toUChar(ok));
}
else if(type_ == kShort)
{
v = uNumber2Str(toShort(ok));
}
else if(type_ == kUShort)
{
v = uNumber2Str(toUShort(ok));
}
else if(type_ == kInt)
{
v = uNumber2Str(toInt(ok));
}
else if(type_ == kUInt)
{
v = uNumber2Str(toUInt(ok));
}
else if(type_ == kFloat)
{
v = uNumber2Str(toFloat(ok));
}
else if(type_ == kDouble)
{
v = uNumber2Str(toDouble(ok));
}
return v;
}
std::vector<signed char> UVariant::toCharArray(bool * ok) const
{
if(ok)
{
*ok = false;
}
std::vector<signed char> v;
if(type_ == kCharArray)
{
if(ok)
{
*ok = true;
}
if(data_.size())
{
v.resize(data_.size() / sizeof(signed char));
memcpy(v.data(), data_.data(), data_.size());
}
}
return v;
}
std::vector<unsigned char> UVariant::toUCharArray(bool * ok) const
{
if(ok)
{
*ok = false;
}
std::vector<unsigned char> v;
if(type_ == kUCharArray)
{
if(ok)
{
*ok = true;
}
if(data_.size())
{
v.resize(data_.size() / sizeof(unsigned char));
memcpy(v.data(), data_.data(), data_.size());
}
}
return v;
}
std::vector<short> UVariant::toShortArray(bool * ok) const
{
if(ok)
{
*ok = false;
}
std::vector<short> v;
if(type_ == kShortArray)
{
if(ok)
{
*ok = true;
}
if(data_.size())
{
v.resize(data_.size() / sizeof(short));
memcpy(v.data(), data_.data(), data_.size());
}
}
return v;
}
std::vector<unsigned short> UVariant::toUShortArray(bool * ok) const
{
if(ok)
{
*ok = false;
}
std::vector<unsigned short> v;
if(type_ == kUShortArray)
{
if(ok)
{
*ok = true;
}
if(data_.size())
{
v.resize(data_.size() / sizeof(unsigned short));
memcpy(v.data(), data_.data(), data_.size());
}
}
return v;
}
std::vector<int> UVariant::toIntArray(bool * ok) const
{
if(ok)
{
*ok = false;
}
std::vector<int> v;
if(type_ == kIntArray)
{
if(ok)
{
*ok = true;
}
if(data_.size())
{
v.resize(data_.size() / sizeof(int));
memcpy(v.data(), data_.data(), data_.size());
}
}
return v;
}
std::vector<unsigned int> UVariant::toUIntArray(bool * ok) const
{
if(ok)
{
*ok = false;
}
std::vector<unsigned int> v;
if(type_ == kUIntArray)
{
if(ok)
{
*ok = true;
}
if(data_.size())
{
v.resize(data_.size() / sizeof(unsigned int));
memcpy(v.data(), data_.data(), data_.size());
}
}
return v;
}
std::vector<float> UVariant::toFloatArray(bool * ok) const
{
if(ok)
{
*ok = false;
}
std::vector<float> v;
if(type_ == kFloatArray)
{
if(ok)
{
*ok = true;
}
if(data_.size())
{
v.resize(data_.size() / sizeof(float));
memcpy(v.data(), data_.data(), data_.size());
}
}
return v;
}
std::vector<double> UVariant::toDoubleArray(bool * ok) const
{
if(ok)
{
*ok = false;
}
std::vector<double> v;
if(type_ == kDoubleArray)
{
if(ok)
{
*ok = true;
}
if(data_.size())
{
v.resize(data_.size() / sizeof(double));
memcpy(v.data(), data_.data(), data_.size());
}
}
return v;
}