blob: fb73ce563fa5d011f3a0192a1f4c91c10c45f6d1 [file] [log] [blame]
/*
*
* D-Bus++ - C++ bindings for D-Bus
*
* Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com>
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __DBUSXX_TYPES_H
#define __DBUSXX_TYPES_H
#include <stdint.h>
#include <string>
#include <vector>
#include <map>
#include "api.h"
#include "util.h"
#include "message.h"
#include "error.h"
namespace DBus {
struct DXXAPI Path : public std::string
{
Path() {}
Path(const std::string &s) : std::string(s) {}
Path(const char *c) : std::string(c) {}
Path &operator = (std::string &s)
{
std::string::operator = (s);
return *this;
}
};
struct DXXAPI Signature : public std::string
{
Signature() {}
Signature(const std::string &s) : std::string(s) {}
Signature(const char *c) : std::string(c) {}
Signature &operator = (std::string &s)
{
std::string::operator = (s);
return *this;
}
};
class DXXAPI FileDescriptor
{
public:
FileDescriptor() : _fd(-1) {}
FileDescriptor(int n) : _fd(n) {}
FileDescriptor &operator = (int fd)
{
_fd = fd;
return *this;
}
int get() const { return _fd; }
private:
int _fd;
};
struct DXXAPI Invalid {};
class DXXAPI Variant
{
public:
Variant();
Variant(MessageIter &it);
Variant &operator = (const Variant &v);
const Signature signature() const;
void clear();
MessageIter reader() const
{
return _msg.reader();
}
MessageIter writer()
{
return _msg.writer();
}
template <typename T>
operator T() const;
private:
Message _msg;
};
template <
typename T1,
typename T2 = Invalid,
typename T3 = Invalid,
typename T4 = Invalid,
typename T5 = Invalid,
typename T6 = Invalid,
typename T7 = Invalid,
typename T8 = Invalid // who needs more than eight?
>
struct Struct
{
T1 _1; T2 _2; T3 _3; T4 _4; T5 _5; T6 _6; T7 _7; T8 _8;
};
template<typename K, typename V>
inline bool dict_has_key(const std::map<K,V>& map, const K &key)
{
return map.find(key) != map.end();
}
template <typename T>
struct type
{
static std::string sig()
{
throw ErrorInvalidArgs("unknown type");
return "";
}
};
template <> struct type<Variant> { static std::string sig(){ return "v"; } };
template <> struct type<uint8_t> { static std::string sig(){ return "y"; } };
template <> struct type<bool> { static std::string sig(){ return "b"; } };
template <> struct type<int16_t> { static std::string sig(){ return "n"; } };
template <> struct type<uint16_t> { static std::string sig(){ return "q"; } };
template <> struct type<int32_t> { static std::string sig(){ return "i"; } };
template <> struct type<uint32_t> { static std::string sig(){ return "u"; } };
template <> struct type<int64_t> { static std::string sig(){ return "x"; } };
template <> struct type<uint64_t> { static std::string sig(){ return "t"; } };
template <> struct type<double> { static std::string sig(){ return "d"; } };
template <> struct type<std::string> { static std::string sig(){ return "s"; } };
template <> struct type<Path> { static std::string sig(){ return "o"; } };
template <> struct type<Signature> { static std::string sig(){ return "g"; } };
template <> struct type<Invalid> { static std::string sig(){ return ""; } };
template <typename E>
struct type< std::vector<E> >
{ static std::string sig(){ return "a" + type<E>::sig(); } };
template <typename K, typename V>
struct type< std::map<K,V> >
{ static std::string sig(){ return "a{" + type<K>::sig() + type<V>::sig() + "}"; } };
template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8 // who needs more than eight?
>
struct type< Struct<T1,T2,T3,T4,T5,T6,T7,T8> >
{
static std::string sig()
{
return "("
+ type<T1>::sig()
+ type<T2>::sig()
+ type<T3>::sig()
+ type<T4>::sig()
+ type<T5>::sig()
+ type<T6>::sig()
+ type<T7>::sig()
+ type<T8>::sig()
+ ")";
}
};
extern DXXAPI DBus::MessageIter &operator << (DBus::MessageIter &iter, const DBus::Variant &val);
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const DBus::Invalid &)
{
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const uint8_t &val)
{
iter.append_byte(val);
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const bool &val)
{
iter.append_bool(val);
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const int16_t& val)
{
iter.append_int16(val);
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const uint16_t& val)
{
iter.append_uint16(val);
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const int32_t& val)
{
iter.append_int32(val);
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const uint32_t& val)
{
iter.append_uint32(val);
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const int64_t& val)
{
iter.append_int64(val);
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const uint64_t& val)
{
iter.append_uint64(val);
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const double &val)
{
iter.append_double(val);
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const std::string &val)
{
iter.append_string(val.c_str());
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const DBus::Path &val)
{
iter.append_path(val.c_str());
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const DBus::Signature &val)
{
iter.append_signature(val.c_str());
return iter;
}
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const DBus::FileDescriptor &val)
{
iter.append_fd(val.get());
return iter;
}
template<typename E>
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const std::vector<E>& val)
{
const std::string sig = DBus::type<E>::sig();
DBus::MessageIter ait = iter.new_array(sig.c_str());
typename std::vector<E>::const_iterator vit;
for (vit = val.begin(); vit != val.end(); ++vit)
{
ait << *vit;
}
iter.close_container(ait);
return iter;
}
template<>
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const std::vector<uint8_t>& val)
{
DBus::MessageIter ait = iter.new_array("y");
ait.append_array('y', &val.front(), val.size());
iter.close_container(ait);
return iter;
}
template<typename K, typename V>
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const std::map<K,V>& val)
{
const std::string sig = "{" + DBus::type<K>::sig() + DBus::type<V>::sig() + "}";
DBus::MessageIter ait = iter.new_array(sig.c_str());
typename std::map<K,V>::const_iterator mit;
for (mit = val.begin(); mit != val.end(); ++mit)
{
DBus::MessageIter eit = ait.new_dict_entry();
eit << mit->first << mit->second;
ait.close_container(eit);
}
iter.close_container(ait);
return iter;
}
template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8
>
inline DBus::MessageIter &operator << (DBus::MessageIter &iter, const DBus::Struct<T1,T2,T3,T4,T5,T6,T7,T8>& val)
{
/* const std::string sig =
DBus::type<T1>::sig() + DBus::type<T2>::sig() + DBus::type<T3>::sig() + DBus::type<T4>::sig() +
DBus::type<T5>::sig() + DBus::type<T6>::sig() + DBus::type<T7>::sig() + DBus::type<T8>::sig();
*/
DBus::MessageIter sit = iter.new_struct(/*sig.c_str()*/);
sit << val._1 << val._2 << val._3 << val._4 << val._5 << val._6 << val._7 << val._8;
iter.close_container(sit);
return iter;
}
/*
*/
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, DBus::Invalid &)
{
return iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, uint8_t &val)
{
val = iter.get_byte();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, bool &val)
{
val = iter.get_bool();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, int16_t& val)
{
val = iter.get_int16();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, uint16_t& val)
{
val = iter.get_uint16();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, int32_t& val)
{
val = iter.get_int32();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, uint32_t& val)
{
val = iter.get_uint32();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, int64_t& val)
{
val = iter.get_int64();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, uint64_t& val)
{
val = iter.get_uint64();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, double &val)
{
val = iter.get_double();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, std::string &val)
{
val = iter.get_string();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, DBus::Path &val)
{
val = iter.get_path();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, DBus::Signature &val)
{
val = iter.get_signature();
return ++iter;
}
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, DBus::FileDescriptor &val)
{
val = iter.get_fd();
return ++iter;
}
extern DXXAPI DBus::MessageIter &operator >> (DBus::MessageIter &iter, DBus::Variant &val);
template<typename E>
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, std::vector<E>& val)
{
if (!iter.is_array())
throw DBus::ErrorInvalidArgs("array expected");
DBus::MessageIter ait = iter.recurse();
while (!ait.at_end())
{
E elem;
ait >> elem;
val.push_back(elem);
}
return ++iter;
}
template<>
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, std::vector<uint8_t>& val)
{
if (!iter.is_array())
throw DBus::ErrorInvalidArgs("array expected");
if (iter.array_type() != 'y')
throw DBus::ErrorInvalidArgs("byte-array expected");
DBus::MessageIter ait = iter.recurse();
uint8_t *array;
size_t length = ait.get_array(&array);
val.insert(val.end(), array, array+length);
return ++iter;
}
template<typename K, typename V>
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, std::map<K,V>& val)
{
if (!iter.is_dict())
throw DBus::ErrorInvalidArgs("dictionary value expected");
DBus::MessageIter mit = iter.recurse();
while (!mit.at_end())
{
K key; V value;
DBus::MessageIter eit = mit.recurse();
eit >> key >> value;
val[key] = value;
++mit;
}
return ++iter;
}
template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8
>
inline DBus::MessageIter &operator >> (DBus::MessageIter &iter, DBus::Struct<T1,T2,T3,T4,T5,T6,T7,T8>& val)
{
DBus::MessageIter sit = iter.recurse();
sit >> val._1 >> val._2 >> val._3 >> val._4 >> val._5 >> val._6 >> val._7 >> val._8;
return ++iter;
}
template <typename T>
inline DBus::Variant::operator T() const
{
T cast;
DBus::MessageIter ri = _msg.reader();
ri >> cast;
return cast;
}
} /* namespace DBus */
#endif//__DBUSXX_TYPES_H