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 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 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 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 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> 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> 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 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 158 ret_object(T p, S v) { 159 if (p) 160 *p = v; 161 else 162 v->release(); 163 } 164 } 165 166 #endif 167