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
34namespace 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