findwindow/Utility.cpp

132 lines
4.3 KiB
C++

/*
* MIT License
*
* Copyright (c) 2025 Vanessa T. <nessa@neko-tools.de>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "Utility.h"
#include <windows.h>
#include <string>
#include <stdexcept>
std::wstring stringToWString(const std::string& str) {
if (str.empty()) return {};
// Calculate the required buffer size
int size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
std::wstring result(size - 1, 0); // size-1 because MultiByteToWideChar counts null terminator
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &result[0], size);
return result;
}
std::string wstringToString(const std::wstring& wstr) {
// Convert to UTF-8
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
std::string message(size_needed - 1, 0); // -1 because WideCharToMultiByte counts null terminator
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &message[0], size_needed, nullptr, nullptr);
return message;
}
std::string formatBytesString(size_t bytes) {
const char* units[] = {"B", "KB", "MB", "GB", "TB"};
int unitIndex = 0;
auto displayBytes = static_cast<double>(bytes);
while (displayBytes >= 1024 && unitIndex < 4) {
displayBytes /= 1024;
unitIndex++;
}
char buffer[64];
std::snprintf(buffer, sizeof(buffer), "%.2f %s", displayBytes, units[unitIndex]);
return {buffer};
}
std::wstring formatBytesWideString(size_t bytes) {
return stringToWString(formatBytesString(bytes));
}
std::vector<std::string> convertCommandLine(int argc, char **argv) {
std::vector<std::string> args;
for (auto i = 1; i < argc; i++) {
args.emplace_back(argv[i]);
}
return args;
}
std::string getErrorMessage(DWORD errorCode) {
if (errorCode == 0) return {};
LPWSTR messageBuffer = nullptr;
DWORD size = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPWSTR>(&messageBuffer),
0,
nullptr
);
if (size == 0) {
return "Unknown error code: " + std::to_string(errorCode);
}
// Convert to wstring first to handle Unicode properly
std::wstring wmessage(messageBuffer);
// Free the Windows-allocated buffer
LocalFree(messageBuffer);
// Remove potential trailing newline and carriage return
while (!wmessage.empty() && (wmessage.back() == L'\n' || wmessage.back() == L'\r')) {
wmessage.pop_back();
}
return std::to_string(errorCode) + " - " + wstringToString(wmessage);
}
void checkAndThrowLastWindowsError(const std::string& message) {
auto lastError = GetLastError();
if (lastError != ERROR_SUCCESS) {
SetLastError(0);
throw std::runtime_error(message + ": " + getErrorMessage(lastError));
}
}
ConsoleDimensions getConsoleDimensions() {
CONSOLE_SCREEN_BUFFER_INFO csbi;
int columns, rows;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
return { columns, rows};
}