// // Copyright 2013 Francisco Jerez // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // #ifndef CLOVER_CORE_PROPERTY_HPP #define CLOVER_CORE_PROPERTY_HPP #include #include "util/range.hpp" #include "util/algorithm.hpp" namespace clover { class property_buffer; namespace detail { template class property_scalar { public: property_scalar(property_buffer &buf) : buf(buf) { } inline property_scalar & operator=(const T &x); private: property_buffer &buf; }; template class property_vector { public: property_vector(property_buffer &buf) : buf(buf) { } template inline property_vector & operator=(const S &v); private: property_buffer &buf; }; template class property_matrix { public: property_matrix(property_buffer &buf) : buf(buf) { } template inline property_matrix & operator=(const S &v); private: property_buffer &buf; }; class property_string { public: property_string(property_buffer &buf) : buf(buf) { } inline property_string & operator=(const std::string &v); private: property_buffer &buf; }; }; /// /// Return value buffer used by the CL property query functions. /// class property_buffer { public: property_buffer(void *r_buf, size_t size, size_t *r_size) : r_buf(r_buf), size(size), r_size(r_size) { } template detail::property_scalar as_scalar() { return { *this }; } template detail::property_vector as_vector() { return { *this }; } template detail::property_matrix as_matrix() { return { *this }; } detail::property_string as_string() { return { *this }; } template iterator_range allocate(size_t n) { if (r_buf && size < n * sizeof(T)) throw error(CL_INVALID_VALUE); if (r_size) *r_size = n * sizeof(T); if (r_buf) return range((T *)r_buf, n); else return { }; } private: void *const r_buf; const size_t size; size_t *const r_size; }; namespace detail { template inline property_scalar & property_scalar::operator=(const T &x) { auto r = buf.allocate(1); if (!r.empty()) r.front() = x; return *this; } template template inline property_vector & property_vector::operator=(const S &v) { auto r = buf.allocate(v.size()); if (!r.empty()) copy(v, r.begin()); return *this; } template template inline property_matrix & property_matrix::operator=(const S &v) { auto r = buf.allocate(v.size()); if (!r.empty()) for_each([](typename S::value_type src, T *dst) { if (dst) copy(src, dst); }, v, r); return *this; } inline property_string & property_string::operator=(const std::string &v) { auto r = buf.allocate(v.size() + 1); if (!r.empty()) copy(range(v.begin(), r.size()), r.begin()); return *this; } }; template class property_element { public: property_element() : x() { } property_element(T x) : x(x) { } template typename std::enable_if::value, S>::type as() const { static_assert(sizeof(S) <= sizeof(T), "Ensure type fits in property list"); return reinterpret_cast(x); } template typename std::enable_if::value, S>::type as() const { return static_cast(x); } private: T x; }; template using property_list = std::map>; struct property_list_tag; /// /// Create a clover::property_list object from a zero-terminated /// CL property list. /// template::value>::type> property_list obj(const D *d_props) { property_list props; while (d_props && *d_props) { auto key = *d_props++; auto value = *d_props++; if (props.count(key)) throw error(CL_INVALID_PROPERTY); props.insert({ key, value }); } return props; } /// /// Create a zero-terminated CL property list from a /// clover::property_list object. /// template std::vector desc(const property_list &props) { std::vector d_props; for (auto &prop : props) { d_props.push_back(prop.first); d_props.push_back(prop.second.template as()); } d_props.push_back(0); return d_props; } } #endif