1 //
2 // Copyright 2012 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 // SOFTWARE.
21 //
22 
23 #ifndef __CL_UTIL_HPP__
24 #define __CL_UTIL_HPP__
25 
26 #include <cstdint>
27 #include <cstring>
28 #include <algorithm>
29 #include <map>
30 
31 #include "core/base.hpp"
32 #include "pipe/p_compiler.h"
33 
34 namespace clover {
35    ///
36    /// Return a matrix (a container of containers) in \a buf with
37    /// argument and bounds checking.  Intended to be used by
38    /// implementations of \a clGetXXXInfo().
39    ///
40    template<typename T, typename V>
41    cl_int
matrix_property(void * buf,size_t size,size_t * size_ret,const V & v)42    matrix_property(void *buf, size_t size, size_t *size_ret, const V& v) {
43       if (buf && size < sizeof(T *) * v.size())
44          return CL_INVALID_VALUE;
45 
46       if (size_ret)
47          *size_ret = sizeof(T *) * v.size();
48 
49       if (buf)
50          for_each([](typename V::value_type src, T *dst) {
51                if (dst)
52                   std::copy(src.begin(), src.end(), dst);
53             },
54             v.begin(), v.end(), (T **)buf);
55 
56       return CL_SUCCESS;
57    }
58 
59    ///
60    /// Return a vector in \a buf with argument and bounds checking.
61    /// Intended to be used by implementations of \a clGetXXXInfo().
62    ///
63    template<typename T, typename V>
64    cl_int
vector_property(void * buf,size_t size,size_t * size_ret,const V & v)65    vector_property(void *buf, size_t size, size_t *size_ret, const V& v) {
66       if (buf && size < sizeof(T) * v.size())
67          return CL_INVALID_VALUE;
68 
69       if (size_ret)
70          *size_ret = sizeof(T) * v.size();
71       if (buf)
72          std::copy(v.begin(), v.end(), (T *)buf);
73 
74       return CL_SUCCESS;
75    }
76 
77    ///
78    /// Return a scalar in \a buf with argument and bounds checking.
79    /// Intended to be used by implementations of \a clGetXXXInfo().
80    ///
81    template<typename T>
82    cl_int
scalar_property(void * buf,size_t size,size_t * size_ret,T v)83    scalar_property(void *buf, size_t size, size_t *size_ret, T v) {
84       return vector_property<T>(buf, size, size_ret, std::vector<T>(1, v));
85    }
86 
87    ///
88    /// Return a string in \a buf with argument and bounds checking.
89    /// Intended to be used by implementations of \a clGetXXXInfo().
90    ///
91    inline cl_int
string_property(void * buf,size_t size,size_t * size_ret,const std::string & v)92    string_property(void *buf, size_t size, size_t *size_ret,
93                    const std::string &v) {
94       if (buf && size < v.size() + 1)
95          return CL_INVALID_VALUE;
96 
97       if (size_ret)
98          *size_ret = v.size() + 1;
99       if (buf)
100          std::strcpy((char *)buf, v.c_str());
101 
102       return CL_SUCCESS;
103    }
104 
105    ///
106    /// Convert a NULL-terminated property list into an std::map.
107    ///
108    template<typename T>
109    std::map<T, T>
property_map(const T * props)110    property_map(const T *props) {
111       std::map<T, T> m;
112 
113       while (props && *props) {
114          T key = *props++;
115          T value = *props++;
116 
117          if (m.count(key))
118             throw clover::error(CL_INVALID_PROPERTY);
119 
120          m.insert({ key, value });
121       }
122 
123       return m;
124    }
125 
126    ///
127    /// Convert an std::map into a NULL-terminated property list.
128    ///
129    template<typename T>
130    std::vector<T>
property_vector(const std::map<T,T> & m)131    property_vector(const std::map<T, T> &m) {
132       std::vector<T> v;
133 
134       for (auto &p : m) {
135          v.push_back(p.first);
136          v.push_back(p.second);
137       }
138 
139       v.push_back(0);
140       return v;
141    }
142 
143    ///
144    /// Return an error code in \a p if non-zero.
145    ///
146    inline void
ret_error(cl_int * p,const clover::error & e)147    ret_error(cl_int *p, const clover::error &e) {
148       if (p)
149          *p = e.get();
150    }
151 
152    ///
153    /// Return a reference-counted object in \a p if non-zero.
154    /// Otherwise release object ownership.
155    ///
156    template<typename T, typename S>
157    void
ret_object(T p,S v)158    ret_object(T p, S v) {
159       if (p)
160          *p = v;
161       else
162          v->release();
163    }
164 }
165 
166 #endif
167