New mon rr GDB command for reading target registers
This commit is contained in:
@@ -10,6 +10,7 @@ target_sources(
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/Services/PathService.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Services/PathService.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Services/ProcessService.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Services/ProcessService.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Services/StringService.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Services/StringService.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/Services/IntegerService.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Services/Avr8InstructionService.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Services/Avr8InstructionService.cpp
|
||||||
|
|
||||||
# Helpers & other
|
# Helpers & other
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ target_sources(
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/BloomVersion.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/BloomVersion.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/BloomVersionMachine.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/BloomVersionMachine.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/Detach.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/Detach.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/ReadRegistersMonitor.cpp
|
||||||
|
|
||||||
# AVR GDB RSP Server
|
# AVR GDB RSP Server
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Gdb/AvrGdb/AvrGdbRsp.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Gdb/AvrGdb/AvrGdbRsp.cpp
|
||||||
|
|||||||
225
src/DebugServer/Gdb/CommandPackets/ReadRegistersMonitor.cpp
Normal file
225
src/DebugServer/Gdb/CommandPackets/ReadRegistersMonitor.cpp
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
#include "ReadRegistersMonitor.hpp"
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
#include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp"
|
||||||
|
#include "src/DebugServer/Gdb/ResponsePackets/PartialResponsePacket.hpp"
|
||||||
|
#include "src/DebugServer/Gdb/ResponsePackets/ResponsePacket.hpp"
|
||||||
|
|
||||||
|
#include "src/Services/StringService.hpp"
|
||||||
|
#include "src/Services/IntegerService.hpp"
|
||||||
|
#include "src/Logger/Logger.hpp"
|
||||||
|
|
||||||
|
#include "src/Exceptions/Exception.hpp"
|
||||||
|
|
||||||
|
namespace DebugServer::Gdb::CommandPackets
|
||||||
|
{
|
||||||
|
using Services::TargetControllerService;
|
||||||
|
using Services::StringService;
|
||||||
|
using Services::IntegerService;
|
||||||
|
|
||||||
|
using ResponsePackets::ErrorResponsePacket;
|
||||||
|
using ResponsePackets::PartialResponsePacket;
|
||||||
|
using ResponsePackets::ResponsePacket;
|
||||||
|
|
||||||
|
using ::Exceptions::Exception;
|
||||||
|
|
||||||
|
ReadRegistersMonitor::ReadRegistersMonitor(Monitor&& monitorPacket)
|
||||||
|
: Monitor(std::move(monitorPacket))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void ReadRegistersMonitor::handle(
|
||||||
|
DebugSession& debugSession,
|
||||||
|
const TargetDescriptor& gdbTargetDescriptor,
|
||||||
|
const Targets::TargetDescriptor& targetDescriptor,
|
||||||
|
TargetControllerService& targetControllerService
|
||||||
|
) {
|
||||||
|
Logger::info("Handling ReadRegisterMonitor packet");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const auto argCount = this->commandArguments.size();
|
||||||
|
if (argCount < 2) {
|
||||||
|
throw Exception{"Peripheral key required"};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& peripheralKey = this->commandArguments[1];
|
||||||
|
const auto peripheralDescriptorOpt = targetDescriptor.tryGetPeripheralDescriptor(peripheralKey);
|
||||||
|
|
||||||
|
if (!peripheralDescriptorOpt.has_value()) {
|
||||||
|
throw Exception{"Unknown peripheral key \"" + peripheralKey + "\""};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& peripheralDescriptor = peripheralDescriptorOpt->get();
|
||||||
|
|
||||||
|
if (argCount < 3) {
|
||||||
|
// Register details were not provided - read all registers in the peripheral
|
||||||
|
this->handlePeripheralOutput(peripheralDescriptor, debugSession, targetControllerService);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& registerGroupKey = this->commandArguments[2];
|
||||||
|
auto registerKey = argCount >= 4 ? std::optional{this->commandArguments[3]} : std::nullopt;
|
||||||
|
|
||||||
|
auto registerGroupDescriptorOpt = peripheralDescriptor.tryGetRegisterGroupDescriptor(
|
||||||
|
registerGroupKey
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!registerGroupDescriptorOpt.has_value()) {
|
||||||
|
if (peripheralDescriptor.registerGroupDescriptorsByKey.size() != 1 || argCount >= 4) {
|
||||||
|
throw Exception{"Unknown register group key \"" + registerGroupKey + "\""};
|
||||||
|
}
|
||||||
|
|
||||||
|
registerGroupDescriptorOpt = peripheralDescriptor.registerGroupDescriptorsByKey.begin()->second;
|
||||||
|
registerKey = registerGroupKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& registerGroupDescriptor = registerGroupDescriptorOpt->get();
|
||||||
|
|
||||||
|
if (!registerKey.has_value()) {
|
||||||
|
debugSession.connection.writePacket(PartialResponsePacket{StringService::toHex(
|
||||||
|
"Reading all registers in " + registerGroupDescriptor.name + " register group, from "
|
||||||
|
+ peripheralDescriptor.name + " peripheral...\n\n"
|
||||||
|
)});
|
||||||
|
this->handleRegisterGroupOutput(registerGroupDescriptor, debugSession, targetControllerService);
|
||||||
|
debugSession.connection.writePacket(ResponsePacket{StringService::toHex("\n")});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto registerDescriptorOpt = registerGroupDescriptor.tryGetRegisterDescriptor(*registerKey);
|
||||||
|
|
||||||
|
if (!registerDescriptorOpt.has_value()) {
|
||||||
|
throw Exception{"Unknown register key \"" + *registerKey + "\""};
|
||||||
|
}
|
||||||
|
|
||||||
|
this->handleSingleRegisterOutput(registerDescriptorOpt->get(), debugSession, targetControllerService);
|
||||||
|
|
||||||
|
} catch (const Exception& exception) {
|
||||||
|
debugSession.connection.writePacket(ResponsePacket{
|
||||||
|
StringService::toHex(
|
||||||
|
StringService::applyTerminalColor(
|
||||||
|
"Error: " + exception.getMessage() + "\n",
|
||||||
|
StringService::TerminalColor::DARK_RED
|
||||||
|
)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadRegistersMonitor::handleSingleRegisterOutput(
|
||||||
|
const Targets::TargetRegisterDescriptor& registerDescriptor,
|
||||||
|
DebugSession& debugSession,
|
||||||
|
TargetControllerService& targetControllerService
|
||||||
|
) {
|
||||||
|
auto output = std::string{"\nName: " + registerDescriptor.name + "\n"};
|
||||||
|
output += "Address: " + StringService::applyTerminalColor(
|
||||||
|
"0x" + StringService::asciiToUpper(StringService::toHex(registerDescriptor.startAddress)),
|
||||||
|
StringService::TerminalColor::DARK_BLUE
|
||||||
|
) + "\n";
|
||||||
|
output += "Size: " + std::to_string(registerDescriptor.size) + " byte(s)\n\n";
|
||||||
|
|
||||||
|
output += "----------- Value -----------\n";
|
||||||
|
|
||||||
|
if (registerDescriptor.access.readable) {
|
||||||
|
const auto value = IntegerService::toUint64(
|
||||||
|
targetControllerService.readRegister(registerDescriptor)
|
||||||
|
);
|
||||||
|
|
||||||
|
output += StringService::applyTerminalColor(
|
||||||
|
"0x" + StringService::asciiToUpper(StringService::toHex(value)).substr(16 - (registerDescriptor.size * 2)),
|
||||||
|
StringService::TerminalColor::DARK_YELLOW
|
||||||
|
);
|
||||||
|
output += " (" + StringService::applyTerminalColor(
|
||||||
|
std::to_string(value),
|
||||||
|
StringService::TerminalColor::DARK_YELLOW
|
||||||
|
);
|
||||||
|
output += ", " + StringService::applyTerminalColor(
|
||||||
|
"0b" + std::bitset<64>{value}.to_string().substr(64 - (registerDescriptor.size * 8)),
|
||||||
|
StringService::TerminalColor::DARK_YELLOW
|
||||||
|
) + ")\n";
|
||||||
|
|
||||||
|
for (const auto& [bitFieldKey, bitFieldDescriptor] : registerDescriptor.bitFieldDescriptorsByKey) {
|
||||||
|
output += bitFieldDescriptor.name + ": " + StringService::applyTerminalColor(
|
||||||
|
"0b" + StringService::toBinaryStringWithMask(value, bitFieldDescriptor.mask),
|
||||||
|
StringService::TerminalColor::DARK_YELLOW
|
||||||
|
) + " ";
|
||||||
|
|
||||||
|
// TODO: Warn about bit field value being meaningless if the bit field isn't readable
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
output += StringService::applyTerminalColor("inaccessible\n", StringService::TerminalColor::DARK_RED);
|
||||||
|
}
|
||||||
|
|
||||||
|
output += "\n";
|
||||||
|
debugSession.connection.writePacket(ResponsePacket{StringService::toHex(output)});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadRegistersMonitor::handlePeripheralOutput(
|
||||||
|
const Targets::TargetPeripheralDescriptor& peripheralDescriptor,
|
||||||
|
DebugSession& debugSession,
|
||||||
|
TargetControllerService& targetControllerService
|
||||||
|
) {
|
||||||
|
debugSession.connection.writePacket(PartialResponsePacket{StringService::toHex(
|
||||||
|
"Reading " + peripheralDescriptor.name + " peripheral registers...\n\n"
|
||||||
|
)});
|
||||||
|
|
||||||
|
for (const auto& [groupKey, groupDescriptor] : peripheralDescriptor.registerGroupDescriptorsByKey) {
|
||||||
|
this->handleRegisterGroupOutput(groupDescriptor, debugSession, targetControllerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
debugSession.connection.writePacket(ResponsePacket{StringService::toHex("\n")});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadRegistersMonitor::handleRegisterGroupOutput(
|
||||||
|
const Targets::TargetRegisterGroupDescriptor& groupDescriptor,
|
||||||
|
DebugSession& debugSession,
|
||||||
|
TargetControllerService& targetControllerService
|
||||||
|
) {
|
||||||
|
for (const auto& [registerKey, registerDescriptor] : groupDescriptor.registerDescriptorsByKey) {
|
||||||
|
auto output = std::string{registerDescriptor.absoluteGroupKey + ", "};
|
||||||
|
output += registerDescriptor.key + ", ";
|
||||||
|
output += registerDescriptor.name + ", ";
|
||||||
|
output += StringService::applyTerminalColor(
|
||||||
|
"0x" + StringService::asciiToUpper(StringService::toHex(registerDescriptor.startAddress)),
|
||||||
|
StringService::TerminalColor::DARK_BLUE
|
||||||
|
) + ", ";
|
||||||
|
output += std::to_string(registerDescriptor.size) + " byte(s) | ";
|
||||||
|
|
||||||
|
if (registerDescriptor.access.readable) {
|
||||||
|
const auto value = IntegerService::toUint64(
|
||||||
|
targetControllerService.readRegister(registerDescriptor)
|
||||||
|
);
|
||||||
|
|
||||||
|
output += StringService::applyTerminalColor(
|
||||||
|
"0x" + StringService::asciiToUpper(StringService::toHex(value)).substr(16 - (registerDescriptor.size * 2)),
|
||||||
|
StringService::TerminalColor::DARK_YELLOW
|
||||||
|
);
|
||||||
|
output += " (" + StringService::applyTerminalColor(
|
||||||
|
std::to_string(value),
|
||||||
|
StringService::TerminalColor::DARK_YELLOW
|
||||||
|
);
|
||||||
|
output += ", " + StringService::applyTerminalColor(
|
||||||
|
"0b" + std::bitset<64>{value}.to_string().substr(64 - (registerDescriptor.size * 8)),
|
||||||
|
StringService::TerminalColor::DARK_YELLOW
|
||||||
|
) + ")";
|
||||||
|
|
||||||
|
for (const auto& [bitFieldKey, bitFieldDescriptor] : registerDescriptor.bitFieldDescriptorsByKey) {
|
||||||
|
output += ", " + bitFieldDescriptor.name + ": " + StringService::applyTerminalColor(
|
||||||
|
"0b" + StringService::toBinaryStringWithMask(value, bitFieldDescriptor.mask),
|
||||||
|
StringService::TerminalColor::DARK_YELLOW
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
output += StringService::applyTerminalColor("inaccessible", StringService::TerminalColor::DARK_RED);
|
||||||
|
}
|
||||||
|
|
||||||
|
output += "\n";
|
||||||
|
debugSession.connection.writePacket(PartialResponsePacket{StringService::toHex(output)});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [subGroupKey, subGroupDescriptor] : groupDescriptor.subgroupDescriptorsByKey) {
|
||||||
|
this->handleRegisterGroupOutput(subGroupDescriptor, debugSession, targetControllerService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/DebugServer/Gdb/CommandPackets/ReadRegistersMonitor.hpp
Normal file
44
src/DebugServer/Gdb/CommandPackets/ReadRegistersMonitor.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "Monitor.hpp"
|
||||||
|
|
||||||
|
#include "src/Targets/TargetRegisterDescriptor.hpp"
|
||||||
|
#include "src/Targets/TargetRegisterGroupDescriptor.hpp"
|
||||||
|
#include "src/Targets/TargetPeripheralDescriptor.hpp"
|
||||||
|
|
||||||
|
namespace DebugServer::Gdb::CommandPackets
|
||||||
|
{
|
||||||
|
class ReadRegistersMonitor: public Monitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ReadRegistersMonitor(Monitor&& monitorPacket);
|
||||||
|
|
||||||
|
void handle(
|
||||||
|
DebugSession& debugSession,
|
||||||
|
const TargetDescriptor& gdbTargetDescriptor,
|
||||||
|
const Targets::TargetDescriptor& targetDescriptor,
|
||||||
|
Services::TargetControllerService& targetControllerService
|
||||||
|
) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void handleSingleRegisterOutput(
|
||||||
|
const Targets::TargetRegisterDescriptor& registerDescriptor,
|
||||||
|
DebugSession& debugSession,
|
||||||
|
Services::TargetControllerService& targetControllerService
|
||||||
|
);
|
||||||
|
|
||||||
|
void handlePeripheralOutput(
|
||||||
|
const Targets::TargetPeripheralDescriptor& peripheralDescriptor,
|
||||||
|
DebugSession& debugSession,
|
||||||
|
Services::TargetControllerService& targetControllerService
|
||||||
|
);
|
||||||
|
|
||||||
|
void handleRegisterGroupOutput(
|
||||||
|
const Targets::TargetRegisterGroupDescriptor& groupDescriptor,
|
||||||
|
DebugSession& debugSession,
|
||||||
|
Services::TargetControllerService& targetControllerService
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "CommandPackets/BloomVersion.hpp"
|
#include "CommandPackets/BloomVersion.hpp"
|
||||||
#include "CommandPackets/BloomVersionMachine.hpp"
|
#include "CommandPackets/BloomVersionMachine.hpp"
|
||||||
#include "CommandPackets/Detach.hpp"
|
#include "CommandPackets/Detach.hpp"
|
||||||
|
#include "CommandPackets/ReadRegistersMonitor.hpp"
|
||||||
|
|
||||||
#ifndef EXCLUDE_INSIGHT
|
#ifndef EXCLUDE_INSIGHT
|
||||||
#include "CommandPackets/ActivateInsight.hpp"
|
#include "CommandPackets/ActivateInsight.hpp"
|
||||||
@@ -291,6 +292,10 @@ namespace DebugServer::Gdb
|
|||||||
return std::make_unique<CommandPackets::ResetTarget>(std::move(*(monitorCommand.release())));
|
return std::make_unique<CommandPackets::ResetTarget>(std::move(*(monitorCommand.release())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (monitorCommand->command.find("rr") == 0) {
|
||||||
|
return std::make_unique<CommandPackets::ReadRegistersMonitor>(std::move(*(monitorCommand.release())));
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef EXCLUDE_INSIGHT
|
#ifndef EXCLUDE_INSIGHT
|
||||||
if (monitorCommand->command.find("insight") == 0) {
|
if (monitorCommand->command.find("insight") == 0) {
|
||||||
return std::make_unique<CommandPackets::ActivateInsight>(std::move(*(monitorCommand.release())));
|
return std::make_unique<CommandPackets::ActivateInsight>(std::move(*(monitorCommand.release())));
|
||||||
|
|||||||
17
src/Services/IntegerService.cpp
Normal file
17
src/Services/IntegerService.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include "IntegerService.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace Services
|
||||||
|
{
|
||||||
|
std::uint64_t IntegerService::toUint64(const std::vector<unsigned char>& data) {
|
||||||
|
assert(data.size() <= 8);
|
||||||
|
auto output = std::uint64_t{0};
|
||||||
|
|
||||||
|
for (const auto& byte : data) {
|
||||||
|
output = (output << 8) | byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/Services/IntegerService.hpp
Normal file
13
src/Services/IntegerService.hpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Services
|
||||||
|
{
|
||||||
|
class IntegerService
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::uint64_t toUint64(const std::vector<unsigned char>& data);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
namespace Services
|
namespace Services
|
||||||
{
|
{
|
||||||
@@ -41,6 +42,12 @@ namespace Services
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string StringService::toHex(std::uint64_t value) {
|
||||||
|
auto stream = std::stringstream{};
|
||||||
|
stream << std::hex << std::setfill('0') << std::setw(16) << static_cast<unsigned int>(value);
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string StringService::toHex(std::uint32_t value) {
|
std::string StringService::toHex(std::uint32_t value) {
|
||||||
auto stream = std::stringstream{};
|
auto stream = std::stringstream{};
|
||||||
stream << std::hex << std::setfill('0') << std::setw(8) << static_cast<unsigned int>(value);
|
stream << std::hex << std::setfill('0') << std::setw(8) << static_cast<unsigned int>(value);
|
||||||
@@ -75,6 +82,20 @@ namespace Services
|
|||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string StringService::toBinaryStringWithMask(std::uint64_t value, std::uint64_t mask) {
|
||||||
|
auto output = std::string{};
|
||||||
|
|
||||||
|
const auto maskBitset = std::bitset<64>{mask};
|
||||||
|
for (auto i = std::size_t{0}; i < maskBitset.size(); ++i) {
|
||||||
|
const auto& bit = maskBitset[i];
|
||||||
|
if (bit) {
|
||||||
|
output.insert(output.begin(), (value & (0x01 << i)) != 0 ? '1' : '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> StringService::dataFromHex(const std::string& hexData) {
|
std::vector<unsigned char> StringService::dataFromHex(const std::string& hexData) {
|
||||||
auto output = std::vector<unsigned char>{};
|
auto output = std::vector<unsigned char>{};
|
||||||
|
|
||||||
@@ -126,4 +147,77 @@ namespace Services
|
|||||||
|
|
||||||
return {std::ranges::begin(range), std::ranges::end(range)};
|
return {std::ranges::begin(range), std::ranges::end(range)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string StringService::applyTerminalColor(const std::string& string, TerminalColor color) {
|
||||||
|
auto colorCode = std::string{};
|
||||||
|
|
||||||
|
switch (color) {
|
||||||
|
case TerminalColor::BLACK: {
|
||||||
|
colorCode = "\033[30m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::DARK_RED: {
|
||||||
|
colorCode = "\033[31m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::DARK_GREEN: {
|
||||||
|
colorCode = "\033[32m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::DARK_YELLOW: {
|
||||||
|
colorCode = "\033[33m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::DARK_BLUE: {
|
||||||
|
colorCode = "\033[34m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::DARK_MAGENTA: {
|
||||||
|
colorCode = "\033[35m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::DARK_CYAN: {
|
||||||
|
colorCode = "\033[36m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::LIGHT_GRAY: {
|
||||||
|
colorCode = "\033[37m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::DARK_GRAY: {
|
||||||
|
colorCode = "\033[90m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::RED: {
|
||||||
|
colorCode = "\033[91m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::GREEN: {
|
||||||
|
colorCode = "\033[92m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::ORANGE: {
|
||||||
|
colorCode = "\033[93m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::BLUE: {
|
||||||
|
colorCode = "\033[94m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::MAGENTA: {
|
||||||
|
colorCode = "\033[95m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::CYAN: {
|
||||||
|
colorCode = "\033[96m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TerminalColor::WHITE: {
|
||||||
|
colorCode = "\033[97m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return colorCode + string + "\033[0m";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,14 @@ namespace Services
|
|||||||
static bool isAscii(const std::string& str);
|
static bool isAscii(const std::string& str);
|
||||||
static std::string replaceUnprintable(std::string str);
|
static std::string replaceUnprintable(std::string str);
|
||||||
|
|
||||||
|
static std::string toHex(std::uint64_t value);
|
||||||
static std::string toHex(std::uint32_t value);
|
static std::string toHex(std::uint32_t value);
|
||||||
static std::string toHex(unsigned char value);
|
static std::string toHex(unsigned char value);
|
||||||
static std::string toHex(const std::vector<unsigned char>& data);
|
static std::string toHex(const std::vector<unsigned char>& data);
|
||||||
static std::string toHex(const std::string& data);
|
static std::string toHex(const std::string& data);
|
||||||
|
|
||||||
|
static std::string toBinaryStringWithMask(std::uint64_t value, std::uint64_t mask);
|
||||||
|
|
||||||
static std::vector<unsigned char> dataFromHex(const std::string& hexData);
|
static std::vector<unsigned char> dataFromHex(const std::string& hexData);
|
||||||
|
|
||||||
static std::uint64_t toUint64(const std::string& str, int base = 0);
|
static std::uint64_t toUint64(const std::string& str, int base = 0);
|
||||||
@@ -54,5 +57,27 @@ namespace Services
|
|||||||
static std::size_t generateUniqueInteger(const std::string& str);
|
static std::size_t generateUniqueInteger(const std::string& str);
|
||||||
|
|
||||||
static std::vector<std::string_view> split(std::string_view str, char delimiter);
|
static std::vector<std::string_view> split(std::string_view str, char delimiter);
|
||||||
|
|
||||||
|
enum class TerminalColor: std::uint8_t
|
||||||
|
{
|
||||||
|
BLACK,
|
||||||
|
DARK_RED,
|
||||||
|
DARK_GREEN,
|
||||||
|
DARK_YELLOW,
|
||||||
|
DARK_BLUE,
|
||||||
|
DARK_MAGENTA,
|
||||||
|
DARK_CYAN,
|
||||||
|
LIGHT_GRAY,
|
||||||
|
DARK_GRAY,
|
||||||
|
RED,
|
||||||
|
GREEN,
|
||||||
|
ORANGE,
|
||||||
|
BLUE,
|
||||||
|
MAGENTA,
|
||||||
|
CYAN,
|
||||||
|
WHITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::string applyTerminalColor(const std::string& string, TerminalColor color);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user