// 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 represents a custom string type for a D-Bus object path.
//
// >>
// >>> DISCUSSION
// >>
//
// A D-Bus object path is normal string in the form "/com/example/foo/bar". This class provides a set of methods for building
// these paths safely in such a way that they are guaranteed to always provide a valid path.
//
// In addition to this functionality, our DBusObjectPath is its own distinct type requiring explicit conversion, providing a level
// of protection against accidentally using an arbitrary string as an object path.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma once
#include
#include
struct DBusObjectPath
{
// Default constructor (creates a root path)
inline DBusObjectPath() { path = "/"; }
// Copy constructor
inline DBusObjectPath(const DBusObjectPath &path) : path(path.path) {}
// Constructor that accepts a C string
//
// Note: explicit because we don't want accidental conversion. Creating a DBusObjectPath must be intentional.
inline explicit DBusObjectPath(const char *pPath) : path(pPath) {}
// Constructor that accepts a std::string
//
// Note: explicit because we don't want accidental conversion. Creating a DBusObjectPath must be intentional.
inline explicit DBusObjectPath(const std::string &path) : path(path) {}
// Explicit conversion to std::string
inline const std::string &toString() const { return path; }
// Explicit conversion to a C string
inline const char *c_str() const { return path.c_str(); }
// Assignment
inline DBusObjectPath &operator =(const DBusObjectPath &rhs)
{
if (this == &rhs) return *this;
path = rhs.path;
return *this;
}
// Concatenation
inline const DBusObjectPath &append(const char *rhs)
{
if (nullptr == rhs || !*rhs) { return *this; }
if (path.empty()) { path = rhs; return *this; }
bool ls = path.back() == '/';
bool rs = *rhs == '/';
if (ls && rs) { path.erase(path.length()-1); }
if (!ls && !rs) { path += "/"; }
path += rhs;
return *this;
}
// Adds a path node (in the form of an std::string) to the end of the path
inline const DBusObjectPath &append(const std::string &rhs)
{
return append(rhs.c_str());
}
// Adds a path node (in the form of a DBusObjectPath) to the end of the path
inline const DBusObjectPath &append(const DBusObjectPath &rhs)
{
return append(rhs.path.c_str());
}
// Adds a path node (in the form of a DBusObjectPath) to the end of the path
inline void operator +=(const DBusObjectPath &rhs)
{
append(rhs);
}
// Adds a path node (in the form of a C string) to the end of the path
inline void operator +=(const char *rhs)
{
append(rhs);
}
// Adds a path node (in the form of an std::string) to the end of the path
inline void operator +=(const std::string &rhs)
{
append(rhs);
}
// Concats two DBusObjectPaths into one, returning the resulting path
inline DBusObjectPath operator +(const DBusObjectPath &rhs) const
{
DBusObjectPath result(*this);
result += rhs;
return result;
}
// Concats a C string onto a DBusObjectPath, returning the resulting path
inline DBusObjectPath operator +(const char *rhs) const
{
DBusObjectPath result(*this);
result += rhs;
return result;
}
// Concats a std::string onto a DBusObjectPath, returning the resulting path
inline DBusObjectPath operator +(const std::string &rhs) const
{
DBusObjectPath result(*this);
result += rhs;
return result;
}
// Tests two DBusObjectPaths for equality, returning true of the two strings are identical
inline bool operator ==(const DBusObjectPath &rhs) const
{
return path == rhs.path;
}
private:
std::string path;
};
// Mixed-mode override for adding a DBusObjectPath to a C string, returning a new DBusObjectPath result
inline DBusObjectPath operator +(const char *lhs, const DBusObjectPath &rhs) { return DBusObjectPath(lhs) + rhs; }
// Mixed-mode override for adding a DBusObjectPath to a std::string, returning a new DBusObjectPath result
inline DBusObjectPath operator +(const std::string &lhs, const DBusObjectPath &rhs) { return DBusObjectPath(lhs) + rhs; }
// Streaming support for our DBusObjectPath (useful for our logging mechanism)
inline std::ostream& operator<<(std::ostream &os, const DBusObjectPath &path)
{
os << path.toString();
return os;
}
// Streaming support for our DBusObjectPath (useful for our logging mechanism)
inline std::ostream& operator +(std::ostream &os, const DBusObjectPath &path)
{
os << path.toString();
return os;
}