1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stddef.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include "value.h"
22
23#define NULL_VALUE_TYPE           0
24#define INT_VALUE_TYPE            1
25#define FLOAT_VALUE_TYPE          2
26#define STRING_VALUE_TYPE         3
27#define BUFFER_VALUE_TYPE         4
28#define MUTABLE_BUFFER_VALUE_TYPE 5
29#define INT_ARRAY_VALUE_TYPE      6
30#define FLOAT_ARRAY_VALUE_TYPE    7
31
32// Templated versions //////////////////////////////////////////////////////////////////////////////
33template<typename POD, int TYPEID>
34POD GetPODValue(Value value) {
35  return value.type == TYPEID ? *reinterpret_cast<POD*>(value.value) : POD();
36}
37
38template<typename PTR, int TYPEID>
39PTR GetPtrValue(Value value) {
40  return value.type == TYPEID ? reinterpret_cast<PTR>(value.value) : NULL;
41}
42
43template<typename POD, int TYPEID>
44Value MakePODValue(POD value) {
45  Value result;
46  result.type = TYPEID;
47  result.value = malloc(sizeof(POD));
48  result.count = 1;
49  *reinterpret_cast<POD*>(result.value) = value;
50  return result;
51}
52
53template<typename BASE, int TYPEID>
54Value MakePtrValue(const BASE* values, int count) {
55  Value result;
56  result.type = TYPEID;
57  result.value = malloc(sizeof(BASE) * count);
58  memcpy(result.value, values, sizeof(BASE) * count);
59  result.count = count;
60  return result;
61}
62
63template<typename POD, int TYPEID>
64int SetPODValue(Value* value, POD new_value) {
65  if (value->type == NULL_VALUE_TYPE) {
66    value->type = TYPEID;
67    value->value = malloc(sizeof(POD));
68    value->count = 1;
69  }
70  if (value->type == TYPEID) {
71    *reinterpret_cast<POD*>(value->value) = new_value;
72    return 1;
73  }
74  return 0;
75}
76
77template<typename BASE, int TYPEID>
78int SetPtrValue(Value* value, const BASE* new_values, int count) {
79  if (value->type == NULL_VALUE_TYPE) {
80    value->type = TYPEID;
81    value->value = malloc(sizeof(BASE) * count);
82    value->count = count;
83  }
84  if (value->type == TYPEID && value->count == count) {
85    memcpy(value->value, new_values, sizeof(BASE) * count);
86    return 1;
87  }
88  return 0;
89}
90
91// C Wrappers //////////////////////////////////////////////////////////////////////////////////////
92int GetIntValue(Value value) {
93  return GetPODValue<int, INT_VALUE_TYPE>(value);
94}
95
96float GetFloatValue(Value value) {
97  return GetPODValue<float, FLOAT_VALUE_TYPE>(value);
98}
99
100const char* GetStringValue(Value value) {
101  return GetPtrValue<const char*, STRING_VALUE_TYPE>(value);
102}
103
104const char* GetBufferValue(Value value) {
105  return (value.type == BUFFER_VALUE_TYPE || value.type == MUTABLE_BUFFER_VALUE_TYPE)
106    ? (const char*)value.value
107    : NULL;
108}
109
110char* GetMutableBufferValue(Value value) {
111  return GetPtrValue<char*, MUTABLE_BUFFER_VALUE_TYPE>(value);
112}
113
114int* GetIntArrayValue(Value value) {
115  return GetPtrValue<int*, INT_ARRAY_VALUE_TYPE>(value);
116}
117
118float* GetFloatArrayValue(Value value) {
119  return GetPtrValue<float*, FLOAT_ARRAY_VALUE_TYPE>(value);
120}
121
122int ValueIsNull(Value value) {
123  return value.type == NULL_VALUE_TYPE;
124}
125
126int ValueIsInt(Value value) {
127  return value.type == INT_VALUE_TYPE;
128}
129
130int ValueIsFloat(Value value) {
131  return value.type == FLOAT_VALUE_TYPE;
132}
133
134int ValueIsString(Value value) {
135  return value.type == STRING_VALUE_TYPE;
136}
137
138int ValueIsBuffer(Value value) {
139  return value.type == BUFFER_VALUE_TYPE || value.type == MUTABLE_BUFFER_VALUE_TYPE;
140}
141
142int ValueIsIntArray(Value value) {
143  return value.type == INT_ARRAY_VALUE_TYPE;
144}
145
146int ValueIsFloatArray(Value value) {
147  return value.type == FLOAT_ARRAY_VALUE_TYPE;
148}
149
150Value MakeNullValue() {
151  Value result;
152  result.type = NULL_VALUE_TYPE;
153  result.value = NULL;
154  result.count = 0;
155  return result;
156}
157
158Value MakeIntValue(int value) {
159  return MakePODValue<int, INT_VALUE_TYPE>(value);
160}
161
162Value MakeFloatValue(float value) {
163  return MakePODValue<float, FLOAT_VALUE_TYPE>(value);
164}
165
166Value MakeStringValue(const char* value) {
167  return MakePtrValue<char, STRING_VALUE_TYPE>(value, strlen(value) + 1);
168}
169
170Value MakeBufferValue(const char* buffer, int size) {
171  return MakePtrValue<char, BUFFER_VALUE_TYPE>(buffer, size);
172}
173
174Value MakeBufferValueNoCopy(const char* buffer, int size) {
175  Value result;
176  result.type = BUFFER_VALUE_TYPE;
177  result.value = (void*)buffer;
178  result.count = size;
179  return result;
180}
181
182Value MakeMutableBufferValue(const char* buffer, int size) {
183  return MakePtrValue<const char, MUTABLE_BUFFER_VALUE_TYPE>(buffer, size);
184}
185
186Value MakeMutableBufferValueNoCopy(char* buffer, int size) {
187  Value result;
188  result.type = MUTABLE_BUFFER_VALUE_TYPE;
189  result.value = (void*)buffer;
190  result.count = size;
191  return result;
192}
193
194Value MakeIntArrayValue(const int* values, int count) {
195  return MakePtrValue<int, INT_ARRAY_VALUE_TYPE>(values, count);
196}
197
198Value MakeFloatArrayValue(const float* values, int count) {
199  return MakePtrValue<float, FLOAT_ARRAY_VALUE_TYPE>(values, count);
200}
201
202int SetIntValue(Value* value, int new_value) {
203  return SetPODValue<int, INT_VALUE_TYPE>(value, new_value);
204}
205
206int SetFloatValue(Value* value, float new_value) {
207  return SetPODValue<float, FLOAT_VALUE_TYPE>(value, new_value);
208}
209
210int SetStringValue(Value* value, const char* new_value) {
211  return SetPtrValue<char, STRING_VALUE_TYPE>(value, new_value, strlen(new_value) + 1);
212}
213
214int SetMutableBufferValue(Value* value, const char* new_data, int size) {
215  return SetPtrValue<char, MUTABLE_BUFFER_VALUE_TYPE>(value, new_data, size);
216}
217
218int SetIntArrayValue(Value* value, const int* new_values, int count) {
219  return SetPtrValue<int, INT_ARRAY_VALUE_TYPE>(value, new_values, count);
220}
221
222int SetFloatArrayValue(Value* value, const float* new_values, int count) {
223  return SetPtrValue<float, FLOAT_ARRAY_VALUE_TYPE>(value, new_values, count);
224}
225
226int GetValueCount(Value value) {
227  return value.count;
228}
229
230void ReleaseValue(Value* value) {
231  if (value && value->value) {
232    free(value->value);
233    value->value = NULL;
234    value->type = NULL_VALUE_TYPE;
235  }
236}
237
238