Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. //
  2. // Copyright 2013 Francisco Jerez
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a
  5. // copy of this software and associated documentation files (the "Software"),
  6. // to deal in the Software without restriction, including without limitation
  7. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. // and/or sell copies of the Software, and to permit persons to whom the
  9. // Software is furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17. // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. // OTHER DEALINGS IN THE SOFTWARE.
  21. //
  22.  
  23. #ifndef CLOVER_CORE_PROPERTY_HPP
  24. #define CLOVER_CORE_PROPERTY_HPP
  25.  
  26. #include <map>
  27.  
  28. #include "util/range.hpp"
  29. #include "util/algorithm.hpp"
  30.  
  31. namespace clover {
  32.    class property_buffer;
  33.  
  34.    namespace detail {
  35.       template<typename T>
  36.       class property_scalar {
  37.       public:
  38.          property_scalar(property_buffer &buf) : buf(buf) {
  39.          }
  40.  
  41.          inline property_scalar &
  42.          operator=(const T &x);
  43.  
  44.       private:
  45.          property_buffer &buf;
  46.       };
  47.  
  48.       template<typename T>
  49.       class property_vector {
  50.       public:
  51.          property_vector(property_buffer &buf) : buf(buf) {
  52.          }
  53.  
  54.          template<typename S>
  55.          inline property_vector &
  56.          operator=(const S &v);
  57.  
  58.       private:
  59.          property_buffer &buf;
  60.       };
  61.  
  62.       template<typename T>
  63.       class property_matrix {
  64.       public:
  65.          property_matrix(property_buffer &buf) : buf(buf) {
  66.          }
  67.  
  68.          template<typename S>
  69.          inline property_matrix &
  70.          operator=(const S &v);
  71.  
  72.       private:
  73.          property_buffer &buf;
  74.       };
  75.  
  76.       class property_string {
  77.       public:
  78.          property_string(property_buffer &buf) : buf(buf) {
  79.          }
  80.  
  81.          inline property_string &
  82.          operator=(const std::string &v);
  83.  
  84.       private:
  85.          property_buffer &buf;
  86.       };
  87.    };
  88.  
  89.    ///
  90.    /// Return value buffer used by the CL property query functions.
  91.    ///
  92.    class property_buffer {
  93.    public:
  94.       property_buffer(void *r_buf, size_t size, size_t *r_size) :
  95.          r_buf(r_buf), size(size), r_size(r_size) {
  96.       }
  97.  
  98.       template<typename T>
  99.       detail::property_scalar<T>
  100.       as_scalar() {
  101.          return { *this };
  102.       }
  103.  
  104.       template<typename T>
  105.       detail::property_vector<T>
  106.       as_vector() {
  107.          return { *this };
  108.       }
  109.  
  110.       template<typename T>
  111.       detail::property_matrix<T>
  112.       as_matrix() {
  113.          return { *this };
  114.       }
  115.  
  116.       detail::property_string
  117.       as_string() {
  118.          return { *this };
  119.       }
  120.  
  121.       template<typename T>
  122.       iterator_range<T *>
  123.       allocate(size_t n) {
  124.          if (r_buf && size < n * sizeof(T))
  125.             throw error(CL_INVALID_VALUE);
  126.  
  127.          if (r_size)
  128.             *r_size = n * sizeof(T);
  129.  
  130.          if (r_buf)
  131.             return range((T *)r_buf, n);
  132.          else
  133.             return { };
  134.       }
  135.  
  136.    private:
  137.       void *const r_buf;
  138.       const size_t size;
  139.       size_t *const r_size;
  140.    };
  141.  
  142.    namespace detail {
  143.       template<typename T>
  144.       inline property_scalar<T> &
  145.       property_scalar<T>::operator=(const T &x) {
  146.          auto r = buf.allocate<T>(1);
  147.  
  148.          if (!r.empty())
  149.             r.front() = x;
  150.  
  151.          return *this;
  152.       }
  153.  
  154.       template<typename T>
  155.       template<typename S>
  156.       inline property_vector<T> &
  157.       property_vector<T>::operator=(const S &v) {
  158.          auto r = buf.allocate<T>(v.size());
  159.  
  160.          if (!r.empty())
  161.             copy(v, r.begin());
  162.  
  163.          return *this;
  164.       }
  165.  
  166.       template<typename T>
  167.       template<typename S>
  168.       inline property_matrix<T> &
  169.       property_matrix<T>::operator=(const S &v) {
  170.          auto r = buf.allocate<T *>(v.size());
  171.  
  172.          if (!r.empty())
  173.             for_each([](typename S::value_type src, T *dst) {
  174.                   if (dst)
  175.                      copy(src, dst);
  176.                }, v, r);
  177.  
  178.          return *this;
  179.       }
  180.  
  181.       inline property_string &
  182.       property_string::operator=(const std::string &v) {
  183.          auto r = buf.allocate<char>(v.size() + 1);
  184.  
  185.          if (!r.empty())
  186.             copy(range(v.begin(), r.size()), r.begin());
  187.  
  188.          return *this;
  189.       }
  190.    };
  191.  
  192.    template<typename T>
  193.    class property_element {
  194.    public:
  195.       property_element() : x() {
  196.       }
  197.  
  198.       property_element(T x) : x(x) {
  199.       }
  200.  
  201.       template<typename S>
  202.       S
  203.       as() const {
  204.          assert(sizeof(S) <= sizeof(T));
  205.          return reinterpret_cast<S>(x);
  206.       }
  207.  
  208.    private:
  209.       T x;
  210.    };
  211.  
  212.    template<typename D>
  213.    using property_list = std::map<D, property_element<D>>;
  214.  
  215.    struct property_list_tag;
  216.  
  217.    ///
  218.    /// Create a clover::property_list object from a zero-terminated
  219.    /// CL property list.
  220.    ///
  221.    template<typename T, typename D,
  222.             typename = typename std::enable_if<
  223.                std::is_same<T, property_list_tag>::value>::type>
  224.    property_list<D>
  225.    obj(const D *d_props) {
  226.       property_list<D> props;
  227.  
  228.       while (d_props && *d_props) {
  229.          auto key = *d_props++;
  230.          auto value = *d_props++;
  231.  
  232.          if (props.count(key))
  233.             throw error(CL_INVALID_PROPERTY);
  234.  
  235.          props.insert({ key, value });
  236.       }
  237.  
  238.       return props;
  239.    }
  240.  
  241.    ///
  242.    /// Create a zero-terminated CL property list from a
  243.    /// clover::property_list object.
  244.    ///
  245.    template<typename D>
  246.    std::vector<D>
  247.    desc(const property_list<D> &props) {
  248.       std::vector<D> d_props;
  249.  
  250.       for (auto &prop : props) {
  251.          d_props.push_back(prop.first);
  252.          d_props.push_back(prop.second.template as<D>());
  253.       }
  254.  
  255.       d_props.push_back(0);
  256.  
  257.       return d_props;
  258.    }
  259. }
  260.  
  261. #endif
  262.