/*! * * Copyright (c) 2023 Diality Inc. - All Rights Reserved. * * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * \file PackageItem.cpp * \author (last) Phil Braica * \date (last) 23-Jan-2023 * \author (original) Phil Braica * \date (original) 23-Jan-2023 */ #include "PackageItem.h" #include #include #include /*! * \brief Constructor. */ PackageItem::PackageItem(): _fileType(""), _destPath(""), _desc(""), _security(0), _version(0), _size(0), _rawFilename(""), _isScript(false), _byteOffset(0) { } /*! * \brief Destructor. */ PackageItem::~PackageItem() { ; // NOP. } /*! * \brief Unwrap xml for the next tag occurance. * * Doesn't work for recursion but in this case that's not an issue. * * Static function. * * \param xml_str The XML to look within. * \param tag The tag to look for. * \param offset The offset to look from. * * \return The unwrapped text. */ std::string PackageItem::unwrap(const std::string & xml_str, const std::string & tag, std::size_t & offset) { std::string stag = "<" + tag + ">"; std::string etag = ""; std::size_t stag_ii = xml_str.find(stag, offset); if (stag_ii == std::string::npos) { return ""; } stag_ii += stag.length(); std::size_t etag_ii = xml_str.find(etag, stag_ii); if (etag_ii == std::string::npos) { return ""; } offset = etag_ii + etag.length(); return trim_text(xml_str.substr(stag_ii, etag_ii - stag_ii)); } /*! * \brief Unwrap xml for the next tag occurance. * * Doesn't work for recursion but in this case that's not an issue. * * Static function, no offset is needed for this is looking for the one and only child. * * \param xml_str The XML to look within. * \param tag The tag to look for. * * \return The unwrapped text. */ std::string PackageItem::unwrap(const std::string& xml_str, const std::string& tag) { std::size_t dontcare = 0; return unwrap(xml_str, tag, dontcare); } /*! * \brief Wrap content in XML tag. * * \param tag Tag to use. * \param content Content. * \return XML fragment. */ std::string PackageItem::wrap(const std::string& tag, const std::string& content) { return " <" + tag + ">" + content + "\n"; } /*! * \brief An array of items. * * \param xml_str The XML to look within. * * \return The array of items that are intact if any. */ std::vector PackageItem::fromXml(const std::string& xml_str) { std::vector rv; std::size_t offset = 0; for (std::size_t ii = 0; ii < xml_str.size(); ii++) { PackageItem item; bool ok = false; try { std::string item_xml = unwrap(xml_str, "item", ii); if (item_xml.size() == 0) { break; } // Try to get the essentials to at least know enough about this thing to drop if it needed. item._fileType = unwrap(item_xml, "filetype"); item._size = static_cast(std::stoul(unwrap(item_xml, "size"))); item._byteOffset = offset; offset += item._size; ok = true; // These if they error only disable this piece of the file (for now). item._destPath = unwrap(item_xml, "path"); item._desc = unwrap(item_xml, "desc"); item._rawFilename = unwrap(item_xml, "raw"); item._security = static_cast(std::stoul(unwrap(item_xml, "security"))); item._version = static_cast(std::stoul(unwrap(item_xml, "version"))); std::string scriptFlag = unwrap(item_xml, "script"); item._isScript = scriptFlag.size() == 0 ? false : (scriptFlag[0] == 't' || scriptFlag[0] == 'T'); } catch (...) { continue; } if (ok && (item._size > 0) && (item._fileType != "")) { rv.push_back(item); } else { // Not ok? Then file too corrupt to proceed with any of this. rv.clear(); break; } } // Return the list. return rv; } /*! * \brief Turn this item into an XML fragment. * * \return XML fragment. */ std::string PackageItem::to_xml() const { return "\n" + wrap("filetype", _fileType) + wrap("path", _destPath) + wrap("desc", _desc) + wrap("security", std::to_string(_security)) + wrap("version", std::to_string(_version)) + wrap("size", std::to_string(_size)) + wrap("script", (_isScript ? "True" : "False")) + wrap("raw", _rawFilename) + "\n"; } /*! * \brief Turn a set into XML * * \param catalog Vector to run through. * * \return String (xml). */ std::string PackageItem::to_xml(const std::vector& catalog) { std::string rv; for (const PackageItem& item : catalog) { rv += item.to_xml(); } return rv; } /*! * \brief Trim whitespace before and after. * * \param txt Input text. * * \return Trimmed text. */ std::string PackageItem::trim_text(const std::string& txt) { // This is relatively quick, easy to test. std::string rv = txt; // Front. rv.erase( rv.begin(), std::find_if(rv.begin(), rv.end(), [](unsigned char c) { return !std::isspace(c); })); // Tail. rv.erase( std::find_if(rv.rbegin(), rv.rend(), [](unsigned char c) { return !std::isspace(c); }).base(), rv.end()); return rv; }