From 06f646aec4dbce64d28bae1be6111bd833f8e79e Mon Sep 17 00:00:00 2001 From: Paul Nettle Date: Fri, 25 Aug 2017 09:30:39 -0500 Subject: Initial version 1.0 --- src/Utils.cpp | 431 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 src/Utils.cpp (limited to 'src/Utils.cpp') diff --git a/src/Utils.cpp b/src/Utils.cpp new file mode 100644 index 0000000..655bd84 --- /dev/null +++ b/src/Utils.cpp @@ -0,0 +1,431 @@ +// Copyright 2017 Paul Nettle. +// +// This file is part of Gobbledegook. +// +// Gobbledegook 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. +// +// Gobbledegook 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 Gobbledegook. If not, see . + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// >> +// >>> INSIDE THIS FILE +// >> +// +// This file contains various general utilitarian functions used throught. It is in some ways, the 'junk drawer' of the appliation, +// though better organized than most physical junk drawers. +// +// >> +// >>> DISCUSSION +// >> +// +// This file contains: +// +// - String helper functions (trimming methods) +// - Hexidecimal helper functions for +// + Producing hex values of various types (8-bit, 16-bit, 32-bit) +// + Standardied Hex/ASCII dumps to the log file of chunks of binary data +// + Properly formatted Bluetooth addresses) +// - GVariant helper funcions of various forms to convert values to/from GVariants +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#include +#include + +#include "Utils.h" + +// --------------------------------------------------------------------------------------------------------------------------------- +// Handy string functions +// --------------------------------------------------------------------------------------------------------------------------------- + +// Trim from start (in place) +void Utils::trimBeginInPlace(std::string &str) +{ + str.erase(str.begin(), std::find_if(str.begin(), str.end(), + [](int ch) + { + return !std::isspace(ch); + })); +} + +// Trim from end (in place) +void Utils::trimEndInPlace(std::string &str) +{ + str.erase(std::find_if(str.rbegin(), str.rend(), + [](int ch) + { + return !std::isspace(ch); + }).base(), str.end()); +} + +// Trim from both ends (in place) +void Utils::trimInPlace(std::string &str) +{ + trimBeginInPlace(str); + trimEndInPlace(str); +} + +// Trim from start (copying) +std::string Utils::trimBegin(const std::string &str) +{ + std::string out = str; + trimBeginInPlace(out); + return out; +} + +// Trim from end (copying) +std::string Utils::trimEnd(const std::string &str) +{ + std::string out = str; + trimEndInPlace(out); + return out; +} + +// Trim from both ends (copying) +std::string Utils::trim(const std::string &str) +{ + std::string out = str; + trimInPlace(out); + return out; +} + +// --------------------------------------------------------------------------------------------------------------------------------- +// Hex output functions +// --------------------------------------------------------------------------------------------------------------------------------- + +// Returns a zero-padded 8-bit hex value in the format: 0xA +std::string Utils::hex(uint8_t value) +{ + char hex[16]; + sprintf(hex, "0x%02X", value); + return hex; +} + +// Returns a zero-padded 8-bit hex value in the format: 0xAB +std::string Utils::hex(uint16_t value) +{ + char hex[16]; + sprintf(hex, "0x%04X", value); + return hex; +} + +// Returns a zero-padded 8-bit hex value in the format: 0xABCD +std::string Utils::hex(uint32_t value) +{ + char hex[16]; + sprintf(hex, "0x%08X", value); + return hex; +} + +// A full hex-dump of binary data (with accompanying ASCII output) +std::string Utils::hex(const uint8_t *pData, int count) +{ + char hex[16]; + + // Hex data output + std::string line; + std::vector hexData; + for (int i = 0; i < count; ++i) + { + sprintf(hex, "%02X ", pData[i]); + line += hex; + + if (line.length() >= 16 * 3) + { + hexData.push_back(line); + line = ""; + } + } + + if (!line.empty()) + { + hexData.push_back(line); + line = ""; + } + + // ASCII data output + std::vector asciiData; + for (int i = 0; i < count; ++i) + { + // Unprintable? + if (pData[i] < 0x20 || pData[i] > 0x7e) + { + line += "."; + } + else + { + line += pData[i]; + } + + if (line.length() >= 16) + { + asciiData.push_back(line); + line = ""; + } + } + + if (!line.empty()) + { + asciiData.push_back(line); + } + + std::string result = "\n"; + size_t dataSize = hexData.size(); + for (size_t i = 0; i < dataSize; ++i) + { + std::string hexPart = hexData[i]; + hexPart.insert(hexPart.length(), 48-hexPart.length(), ' '); + + std::string asciiPart = asciiData[i]; + asciiPart.insert(asciiPart.length(), 16-asciiPart.length(), ' '); + + result += std::string(" > ") + hexPart + " [" + asciiPart + "]"; + + if (i < dataSize - 1) { result += "\n"; } + } + + return result; +} + +// Returns a peoperly formatted Bluetooth address from a set of six octets stored at `pAddress` +// +// USE WITH CAUTION: It is expected that pAddress point to an array of 6 bytes. The length of the array cannot be validated and +// incorrect lengths will produce undefined, likely unwanted and potentially fatal results. Or it will return the address of the +// train at platform 9 3/4. You decide. +// +// This method returns a set of six zero-padded 8-bit hex values 8-bit in the format: 12:34:56:78:9A:BC +std::string Utils::bluetoothAddressString(uint8_t *pAddress) +{ + char hex[32]; + snprintf(hex, sizeof(hex), "%02X:%02X:%02X:%02X:%02X:%02X", + pAddress[0], pAddress[1], pAddress[2], pAddress[3], pAddress[4], pAddress[5]); + return hex; +} + +// --------------------------------------------------------------------------------------------------------------------------------- +// GVariant helper functions +// --------------------------------------------------------------------------------------------------------------------------------- + +// Returns a GVariant containing a floating reference to a utf8 string +GVariant *Utils::gvariantFromString(const char *pStr) +{ + return g_variant_new_string(pStr); +} + +// Returns a GVariant containing a floating reference to a utf8 string +GVariant *Utils::gvariantFromString(const std::string &str) +{ + return g_variant_new_string(str.c_str()); +} + +// Returns an array of strings ("as") with one string per variable argument. +// +// The array must be terminated with a nullptr. +// +// This is an extension method to the vararg version, which accepts pass-through variable arguments from other mthods. +GVariant *Utils::gvariantFromStringArray(const char *pStr, va_list args) +{ + // Deal with empty arrays + if (pStr == 0) + { + return g_variant_new("as", nullptr); + } + + g_auto(GVariantBuilder) builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); + + while(nullptr != pStr) + { + g_variant_builder_add(&builder, "s", pStr); + pStr = va_arg(args, const char *); + } + + return g_variant_builder_end(&builder); +} + +// Returns an array of strings ("as") with one string per variable argument. +// +// The array must be terminated with a nullptr. +GVariant *Utils::gvariantFromStringArray(const char *pStr, ...) +{ + // Deal with empty arrays + if (pStr == 0) + { + return g_variant_new("as", nullptr); + } + + g_auto(GVariantBuilder) builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); + + va_list args; + va_start(args, pStr); + + GVariant *pResult = gvariantFromStringArray(pStr, args); + + va_end(args); + + return pResult; +} + +// Returns an array of strings ("as") from an array of strings +GVariant *Utils::gvariantFromStringArray(const std::vector &arr) +{ + // Deal with empty arrays + if (arr.empty()) + { + return g_variant_new("as", nullptr); + } + + g_auto(GVariantBuilder) builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); + + for (std::string str : arr) + { + g_variant_builder_add(&builder, "s", str.c_str()); + } + + return g_variant_builder_end(&builder); +} + +// Returns an array of strings ("as") from an array of C strings +GVariant *Utils::gvariantFromStringArray(const std::vector &arr) +{ + // Deal with empty arrays + if (arr.empty()) + { + return g_variant_new("as", nullptr); + } + + g_auto(GVariantBuilder) builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); + + for (const char *pStr : arr) + { + g_variant_builder_add(&builder, "s", pStr); + } + + return g_variant_builder_end(&builder); +} + +// Returns an GVariant* containing an object path ("o") from an DBusObjectPath +GVariant *Utils::gvariantFromObject(const DBusObjectPath &path) +{ + return g_variant_new_object_path(path.c_str()); +} + +// Returns an GVariant* containing a boolean +GVariant *Utils::gvariantFromBoolean(bool b) +{ + return g_variant_new_boolean(b); +} + +// Returns an GVariant* containing a 16-bit integer +GVariant *Utils::gvariantFromInt(gint16 value) +{ + return g_variant_new_int16(value); +} + +// Returns an GVariant* containing a 32-bit integer +GVariant *Utils::gvariantFromInt(gint32 value) +{ + return g_variant_new_int32(value); +} + +// Returns an array of bytes ("ay") with the contents of the input C string +GVariant *Utils::gvariantFromByteArray(const char *pStr) +{ + // Deal with empty arrays + if (*pStr == 0) + { + return g_variant_new("ay", nullptr); + } + + return g_variant_new_bytestring(pStr); +} + +// Returns an array of bytes ("ay") with the contents of the input string +GVariant *Utils::gvariantFromByteArray(const std::string &str) +{ + return gvariantFromByteArray(str.c_str()); +} + +// Returns an array of bytes ("ay") with the contents of the input array of unsigned 8-bit values +GVariant *Utils::gvariantFromByteArray(const guint8 *pBytes, int count) +{ + GBytes *pGbytes = g_bytes_new(pBytes, count); + return g_variant_new_from_bytes(G_VARIANT_TYPE_BYTESTRING, pGbytes, count); +} + +// Returns an array of bytes ("ay") with the contents of the input array of unsigned 8-bit values +GVariant *Utils::gvariantFromByteArray(const std::vector bytes) +{ + GBytes *pGbytes = g_bytes_new(bytes.data(), bytes.size()); + return g_variant_new_from_bytes(G_VARIANT_TYPE_BYTESTRING, pGbytes, bytes.size()); +} + +// Returns an array of bytes ("ay") containing a single unsigned 8-bit value +GVariant *Utils::gvariantFromByteArray(const guint8 data) +{ + return gvariantFromByteArray((const guint8 *) &data, sizeof(data)); +} + +// Returns an array of bytes ("ay") containing a single signed 8-bit value +GVariant *Utils::gvariantFromByteArray(const gint8 data) +{ + return gvariantFromByteArray((const guint8 *) &data, sizeof(data)); +} + +// Returns an array of bytes ("ay") containing a single unsigned 16-bit value +GVariant *Utils::gvariantFromByteArray(const guint16 data) +{ + return gvariantFromByteArray((const guint8 *) &data, sizeof(data)); +} + +// Returns an array of bytes ("ay") containing a single signed 16-bit value +GVariant *Utils::gvariantFromByteArray(const gint16 data) +{ + return gvariantFromByteArray((const guint8 *) &data, sizeof(data)); +} + +// Returns an array of bytes ("ay") containing a single unsigned 32-bit value +GVariant *Utils::gvariantFromByteArray(const guint32 data) +{ + return gvariantFromByteArray((const guint8 *) &data, sizeof(data)); +} + +// Returns an array of bytes ("ay") containing a single signed 32-bit value +GVariant *Utils::gvariantFromByteArray(const gint32 data) +{ + return gvariantFromByteArray((const guint8 *) &data, sizeof(data)); +} + +// Returns an array of bytes ("ay") containing a single unsigned 64-bit value +GVariant *Utils::gvariantFromByteArray(const guint64 data) +{ + return gvariantFromByteArray((const guint8 *) &data, sizeof(data)); +} + +// Returns an array of bytes ("ay") containing a single signed 64-bit value +GVariant *Utils::gvariantFromByteArray(const gint64 data) +{ + return gvariantFromByteArray((const guint8 *) &data, sizeof(data)); +} + +// Extracts a string from an array of bytes ("ay") +std::string Utils::stringFromGVariantByteArray(const GVariant *pVariant) +{ + gsize size; + gconstpointer pPtr = g_variant_get_fixed_array(const_cast(pVariant), &size, 1); + std::vector array(size + 1, 0); + memcpy(array.data(), pPtr, size); + return array.data(); +} -- cgit v1.2.3