1c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez//
2c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// Copyright 2012 Francisco Jerez
3c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez//
4c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// Permission is hereby granted, free of charge, to any person obtaining a
5c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// copy of this software and associated documentation files (the "Software"),
6c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// to deal in the Software without restriction, including without limitation
7c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// and/or sell copies of the Software, and to permit persons to whom the
9c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// Software is furnished to do so, subject to the following conditions:
10c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez//
11c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// The above copyright notice and this permission notice shall be included in
12c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// all copies or substantial portions of the Software.
13c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez//
14c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// SOFTWARE.
21c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez//
22c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
23c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#ifndef __CL_UTIL_HPP__
24c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#define __CL_UTIL_HPP__
25c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
26c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <cstdint>
27c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <cstring>
28c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <algorithm>
29c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <map>
30c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
31c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include "core/base.hpp"
32c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include "pipe/p_compiler.h"
33c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
34c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jereznamespace clover {
35c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
36c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Return a matrix (a container of containers) in \a buf with
37c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// argument and bounds checking.  Intended to be used by
38c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// implementations of \a clGetXXXInfo().
39c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
40c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   template<typename T, typename V>
41c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   cl_int
42c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   matrix_property(void *buf, size_t size, size_t *size_ret, const V& v) {
43c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (buf && size < sizeof(T *) * v.size())
44c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         return CL_INVALID_VALUE;
45c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
46c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (size_ret)
47c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         *size_ret = sizeof(T *) * v.size();
48c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
49c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (buf)
50c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         for_each([](typename V::value_type src, T *dst) {
51c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez               if (dst)
52c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez                  std::copy(src.begin(), src.end(), dst);
53c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez            },
54c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez            v.begin(), v.end(), (T **)buf);
55c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
56c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      return CL_SUCCESS;
57c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   }
58c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
59c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
60c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Return a vector in \a buf with argument and bounds checking.
61c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Intended to be used by implementations of \a clGetXXXInfo().
62c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
63c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   template<typename T, typename V>
64c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   cl_int
65c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   vector_property(void *buf, size_t size, size_t *size_ret, const V& v) {
66c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (buf && size < sizeof(T) * v.size())
67c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         return CL_INVALID_VALUE;
68c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
69c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (size_ret)
70c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         *size_ret = sizeof(T) * v.size();
71c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (buf)
72c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         std::copy(v.begin(), v.end(), (T *)buf);
73c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
74c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      return CL_SUCCESS;
75c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   }
76c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
77c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
78c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Return a scalar in \a buf with argument and bounds checking.
79c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Intended to be used by implementations of \a clGetXXXInfo().
80c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
81c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   template<typename T>
82c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   cl_int
83c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   scalar_property(void *buf, size_t size, size_t *size_ret, T v) {
84c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      return vector_property<T>(buf, size, size_ret, std::vector<T>(1, v));
85c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   }
86c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
87c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
88c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Return a string in \a buf with argument and bounds checking.
89c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Intended to be used by implementations of \a clGetXXXInfo().
90c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
91c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   inline cl_int
92c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   string_property(void *buf, size_t size, size_t *size_ret,
93c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez                   const std::string &v) {
94c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (buf && size < v.size() + 1)
95c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         return CL_INVALID_VALUE;
96c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
97c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (size_ret)
98c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         *size_ret = v.size() + 1;
99c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (buf)
100c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         std::strcpy((char *)buf, v.c_str());
101c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
102c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      return CL_SUCCESS;
103c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   }
104c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
105c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
106c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Convert a NULL-terminated property list into an std::map.
107c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
108c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   template<typename T>
109c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   std::map<T, T>
110c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   property_map(const T *props) {
111c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      std::map<T, T> m;
112c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
113c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      while (props && *props) {
114c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         T key = *props++;
115c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         T value = *props++;
116c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
117c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         if (m.count(key))
118c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez            throw clover::error(CL_INVALID_PROPERTY);
119c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
120c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         m.insert({ key, value });
121c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      }
122c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
123c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      return m;
124c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   }
125c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
126c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
127c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Convert an std::map into a NULL-terminated property list.
128c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
129c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   template<typename T>
130c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   std::vector<T>
131c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   property_vector(const std::map<T, T> &m) {
132c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      std::vector<T> v;
133c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
134c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      for (auto &p : m) {
135c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         v.push_back(p.first);
136c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         v.push_back(p.second);
137c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      }
138c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
139c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      v.push_back(0);
140c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      return v;
141c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   }
142c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
143c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
144c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Return an error code in \a p if non-zero.
145c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
146c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   inline void
147c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ret_error(cl_int *p, const clover::error &e) {
148c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (p)
149c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         *p = e.get();
150c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   }
151c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
152c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
153c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Return a reference-counted object in \a p if non-zero.
154c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   /// Otherwise release object ownership.
155c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ///
156c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   template<typename T, typename S>
157c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   void
158c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   ret_object(T p, S v) {
159c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      if (p)
160c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         *p = v;
161c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez      else
162c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez         v->release();
163c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez   }
164c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez}
165c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez
166c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#endif
167