/*
Userspace Virtual Filesystem
Copyright (C) 2015 Sebastian Herbord. All rights reserved.
This file is part of usvfs.
usvfs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
usvfs 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with usvfs. If not, see .
*/
#include "stringutils.h"
#include "windows_sane.h"
namespace usvfs::shared
{
void strncpy_sz(char* dest, const char* src, size_t destSize)
{
if (destSize > 0) {
strncpy(dest, src, destSize - 1);
dest[destSize - 1] = '\0';
}
}
void wcsncpy_sz(wchar_t* dest, const wchar_t* src, size_t destSize)
{
if ((destSize > 0) && (dest != nullptr)) {
wcsncpy(dest, src, destSize - 1);
dest[destSize - 1] = L'\0';
}
}
bool startswith(const wchar_t* string, const wchar_t* subString)
{
while ((*string != '\0') && (*subString != '\0')) {
if (towlower(*string) != towlower(*subString)) {
return false;
}
++string;
++subString;
}
return *subString == '\0';
}
static fs::path normalize(const fs::path& path)
{
fs::path result;
boost::locale::generator gen;
auto loc = gen("en_US.UTF-8");
for (fs::path::iterator iter = path.begin(); iter != path.end(); ++iter) {
if (*iter == "..") {
result = result.parent_path();
} else if (*iter != ".") {
result /= boost::to_lower_copy(iter->string(), loc);
} // single dot is ignored
}
return result;
}
fs::path make_relative(const fs::path& fromIn, const fs::path& toIn)
{
// converting path to lower case to make iterator comparison work correctly
// on case-insenstive filesystems
fs::path from(fs::absolute(fromIn));
fs::path to(fs::absolute(toIn));
// find common base
fs::path::const_iterator fromIter(from.begin());
fs::path::const_iterator toIter(to.begin());
// TODO the following equivalent test is probably quite expensive as new
// paths are created for each iteration but the case sensitivity depends on
// the fs
while ((fromIter != from.end()) && (toIter != to.end()) &&
(boost::iequals(fromIter->string(), toIter->string()))) {
++fromIter;
++toIter;
}
// Navigate backwards in directory to reach previously found base
fs::path result;
for (; fromIter != from.end(); ++fromIter) {
if (*fromIter != ".") {
result /= "..";
}
}
// Now navigate down the directory branch
for (; toIter != to.end(); ++toIter) {
result /= *toIter;
}
return result;
}
std::string to_hex(void* bufferIn, size_t bufferSize)
{
unsigned char* buffer = static_cast(bufferIn);
std::ostringstream temp;
temp << std::hex;
for (size_t i = 0; i < bufferSize; ++i) {
temp << std::setfill('0') << std::setw(2) << (unsigned int)buffer[i];
if ((i % 16) == 15) {
temp << "\n";
} else {
temp << " ";
}
}
return temp.str();
}
std::wstring to_upper(const std::wstring& input)
{
std::wstring result;
result.resize(input.size());
::LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, input.c_str(),
static_cast(input.size()), &result[0],
static_cast(result.size()));
return result;
}
std::string byte_string(std::size_t n)
{
auto s = std::to_string(n);
auto p = s.size();
while (p > 3) {
p -= 3;
s.insert(p, 1, ',');
}
return s + " B";
}
} // namespace usvfs::shared