peary/utils/utils.hpp

Utility functions and classes. More…

Namespaces

Name
peary
peary::utils

Detailed Description

Utility functions and classes.

Copyright: Copyright (c) 2016-2025 CERN and the Peary Caribou authors. This software is distributed under the terms of the LGPL-3.0-only License, copied verbatim in the file “LICENSE.md”. SPDX-License-Identifier: LGPL-3.0-only

Source code

  
#pragma once

#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <limits>
#include <sstream>
#include <string>
#include <vector>

#include <unistd.h>

#include "peary/utils/exceptions.hpp"

namespace peary::utils {

    bool check_flock(const std::string& semaphore);

    bool acquire_flock(const std::string& semaphore);

    void release_flock(const std::string& semaphore);

    void make_directories(const std::string& path);

    void inline mDelay(uint32_t ms) {
        // Wait for the given time in milliseconds:
        usleep(ms * 1000);
    }

    std::string trim(const std::string& s);

    uint8_t reverseByte(uint8_t byte);

    template <typename T> inline T from_string(const std::string& x) {
        if(x.empty()) {
            throw InvalidArgumentError(__func__, "Cannot convert empty string");
        }
        T ret = T();
        std::istringstream s(x);
        s >> ret;
        char remain = '\0';
        s >> remain;
        if(remain) {
            throw InvalidArgumentError(__func__, "Remaining characters after conversion of '" + x + "'");
        }
        return ret;
    }

    template <> inline std::string from_string(const std::string& x) {
        if(x.empty()) {
            throw InvalidArgumentError(__func__, "Cannot convert empty string");
        } else {
            return x;
        }
    }

    template <> int64_t from_string(const std::string& x);

    template <> uint64_t from_string(const std::string& x);

    template <> inline int32_t from_string(const std::string& x) {
        return static_cast<int32_t>(from_string<int64_t>(x));
    }

    template <> inline uint32_t from_string(const std::string& x) {
        return static_cast<uint32_t>(from_string<uint64_t>(x));
    }

    template <> inline uint8_t from_string(const std::string& x) {
        return static_cast<uint8_t>(from_string<uint64_t>(x));
    }

    template <typename T> inline std::string to_string(const T& x, int digits = 0) {
        std::ostringstream s;
        s << std::setfill('0') << std::setw(digits) << x;
        return s.str();
    }

    template <typename T> inline std::string to_string(const std::vector<T>& x, const std::string& sep, int digits = 0) {
        std::ostringstream s;
        if(x.size() > 0) {
            s << to_string(x[0], digits);
        }
        for(size_t i = 1; i < x.size(); ++i) {
            s << sep << to_string(x[i], digits);
        }
        return s.str();
    }

    template <typename T> inline std::string to_string(const std::vector<T>& x, int digits = 0) {
        return to_string(x, ",", digits);
    }

    inline std::string to_string(const std::string& x, int /*digits*/ = 0) {
        return x;
    }

    inline std::string to_string(const char* x, int /*digits*/ = 0) {
        return x;
    }

    template <typename T> std::vector<T>& split(const std::string& s, std::vector<T>& elems, char delim) {

        // If the input string is empty, simply return the default elements:
        if(s.empty()) {
            return elems;
        }

        // Else we have data, clear the default elements and chop the string:
        elems.clear();
        std::stringstream ss(s);
        std::string item;
        T def = T();
        while(std::getline(ss, item, delim)) {
            try {
                elems.push_back(from_string<T>(item));
            } catch(InvalidArgumentError&) {
                elems.push_back(def);
            }
        }
        return elems;
    }

    template <typename T> std::string to_bit_string(const T data, int length = -1, bool baseprefix = false) {
        std::ostringstream stream;
        // if length is not defined, use a standard (full) one
        if(length < 0) {
            length = std::numeric_limits<T>::digits;
            // std::numeric_limits<T>::digits does not include sign bits
            if(std::numeric_limits<T>::is_signed) {
                length++;
            }
        }
        if(baseprefix) {
            stream << "0b";
        }
        while(--length >= 0) {
            stream << ((data >> length) & 1);
        }
        return stream.str();
    }

    template <typename T> std::string to_hex_string(const T i, int length = -1, bool baseprefix = true) {
        std::ostringstream stream;
        // if length is not defined, use a standard (full) one
        if(length < 0) {
            length = (std::numeric_limits<T>::digits + 1) / 4;
        }
        if(baseprefix) {
            stream << "0x";
        }
        stream << std::hex << std::setfill('0') << std::setw(length) << static_cast<uint64_t>(i);
        return stream.str();
    }

    template <typename T> std::string listVector(std::vector<T> vec, const std::string& separator = ", ", bool hex = false) {
        std::stringstream os;
        for(auto it : vec) {
            if(hex) {
                os << to_hex_string(it);
            } else {
                os << static_cast<uint64_t>(it);
            }
            os << separator;
        }
        return os.str();
    }

    template <typename T1, typename T2>
    std::string listVector(std::vector<std::pair<T1, T2>> vec, const std::string& separator = ", ", bool hex = false) {
        std::stringstream os;
        for(auto it : vec) {
            if(hex) {
                os << to_hex_string(it.first) << ":" << to_hex_string(it.second);
            } else {
                os << static_cast<unsigned int>(it.first) << ":" << static_cast<unsigned int>(it.second);
            }
            os << separator;
        }
        return os.str();
    }

    template <typename T1>
    std::string listVector(std::vector<std::pair<std::string, T1>> vec,
                           const std::string& separator = ", ",
                           bool hex = false) {
        std::stringstream os;
        for(auto it : vec) {
            if(hex) {
                os << it.first << ":" << to_hex_string(it.second);
            } else {
                os << it.first << ":" << static_cast<unsigned int>(it.second);
            }
            os << separator;
        }
        return os.str();
    }

} // namespace peary::utils
  

Updated on 2025-11-14 at 11:31:23 +0100