1/*
2 * Copyright (C) 2016 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#ifndef ANDROID_TYPE_CONVERTER_H_
18#define ANDROID_TYPE_CONVERTER_H_
19
20#include <string>
21#include <string.h>
22
23#include <system/audio.h>
24#include <utils/Log.h>
25#include <utils/Vector.h>
26#include <utils/SortedVector.h>
27
28#include <media/AudioParameter.h>
29#include "convert.h"
30
31namespace android {
32
33struct SampleRateTraits
34{
35    typedef uint32_t Type;
36    typedef SortedVector<Type> Collection;
37};
38struct DeviceTraits
39{
40    typedef audio_devices_t Type;
41    typedef Vector<Type> Collection;
42};
43struct OutputDeviceTraits : public DeviceTraits {};
44struct InputDeviceTraits : public DeviceTraits {};
45struct OutputFlagTraits
46{
47    typedef audio_output_flags_t Type;
48    typedef Vector<Type> Collection;
49};
50struct InputFlagTraits
51{
52    typedef audio_input_flags_t Type;
53    typedef Vector<Type> Collection;
54};
55struct FormatTraits
56{
57    typedef audio_format_t Type;
58    typedef Vector<Type> Collection;
59};
60struct ChannelTraits
61{
62    typedef audio_channel_mask_t Type;
63    typedef SortedVector<Type> Collection;
64};
65struct OutputChannelTraits : public ChannelTraits {};
66struct InputChannelTraits : public ChannelTraits {};
67struct ChannelIndexTraits : public ChannelTraits {};
68struct GainModeTraits
69{
70    typedef audio_gain_mode_t Type;
71    typedef Vector<Type> Collection;
72};
73struct StreamTraits
74{
75    typedef audio_stream_type_t Type;
76    typedef Vector<Type> Collection;
77};
78struct AudioModeTraits
79{
80    typedef audio_mode_t Type;
81    typedef Vector<Type> Collection;
82};
83struct UsageTraits
84{
85    typedef audio_usage_t Type;
86    typedef Vector<Type> Collection;
87};
88struct SourceTraits
89{
90    typedef audio_source_t Type;
91    typedef Vector<Type> Collection;
92};
93template <typename T>
94struct DefaultTraits
95{
96    typedef T Type;
97    typedef Vector<Type> Collection;
98};
99
100template <class Traits>
101static void collectionFromString(const std::string &str, typename Traits::Collection &collection,
102                                 const char *del = AudioParameter::valueListSeparator)
103{
104    char *literal = strdup(str.c_str());
105    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
106        typename Traits::Type value;
107        if (utilities::convertTo<std::string, typename Traits::Type >(cstr, value)) {
108            collection.add(value);
109        }
110    }
111    free(literal);
112}
113
114template <class Traits>
115class TypeConverter
116{
117public:
118    static bool toString(const typename Traits::Type &value, std::string &str);
119
120    static bool fromString(const std::string &str, typename Traits::Type &result);
121
122    static void collectionFromString(const std::string &str,
123                                     typename Traits::Collection &collection,
124                                     const char *del = AudioParameter::valueListSeparator);
125
126    static uint32_t maskFromString(
127            const std::string &str, const char *del = AudioParameter::valueListSeparator);
128
129    static void maskToString(
130            uint32_t mask, std::string &str, const char *del = AudioParameter::valueListSeparator);
131
132protected:
133    struct Table {
134        const char *literal;
135        typename Traits::Type value;
136    };
137
138    static const Table mTable[];
139};
140
141template <class Traits>
142inline bool TypeConverter<Traits>::toString(const typename Traits::Type &value, std::string &str)
143{
144    for (size_t i = 0; mTable[i].literal; i++) {
145        if (mTable[i].value == value) {
146            str = mTable[i].literal;
147            return true;
148        }
149    }
150    char result[64];
151    snprintf(result, sizeof(result), "Unknown enum value %d", value);
152    str = result;
153    return false;
154}
155
156template <class Traits>
157inline bool TypeConverter<Traits>::fromString(const std::string &str, typename Traits::Type &result)
158{
159    for (size_t i = 0; mTable[i].literal; i++) {
160        if (strcmp(mTable[i].literal, str.c_str()) == 0) {
161            ALOGV("stringToEnum() found %s", mTable[i].literal);
162            result = mTable[i].value;
163            return true;
164        }
165    }
166    return false;
167}
168
169template <class Traits>
170inline void TypeConverter<Traits>::collectionFromString(const std::string &str,
171        typename Traits::Collection &collection,
172        const char *del)
173{
174    char *literal = strdup(str.c_str());
175
176    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
177        typename Traits::Type value;
178        if (fromString(cstr, value)) {
179            collection.add(value);
180        }
181    }
182    free(literal);
183}
184
185template <class Traits>
186inline uint32_t TypeConverter<Traits>::maskFromString(const std::string &str, const char *del)
187{
188    char *literal = strdup(str.c_str());
189    uint32_t value = 0;
190    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
191        typename Traits::Type type;
192        if (fromString(cstr, type)) {
193            value |= static_cast<uint32_t>(type);
194        }
195    }
196    free(literal);
197    return value;
198}
199
200template <class Traits>
201inline void TypeConverter<Traits>::maskToString(uint32_t mask, std::string &str, const char *del)
202{
203    if (mask != 0) {
204        bool first_flag = true;
205        for (size_t i = 0; mTable[i].literal; i++) {
206            if (mTable[i].value != 0 && (mask & mTable[i].value) == mTable[i].value) {
207                if (!first_flag) str += del;
208                first_flag = false;
209                str += mTable[i].literal;
210            }
211        }
212    } else {
213        toString(static_cast<typename Traits::Type>(0), str);
214    }
215}
216
217typedef TypeConverter<OutputDeviceTraits> OutputDeviceConverter;
218typedef TypeConverter<InputDeviceTraits> InputDeviceConverter;
219typedef TypeConverter<OutputFlagTraits> OutputFlagConverter;
220typedef TypeConverter<InputFlagTraits> InputFlagConverter;
221typedef TypeConverter<FormatTraits> FormatConverter;
222typedef TypeConverter<OutputChannelTraits> OutputChannelConverter;
223typedef TypeConverter<InputChannelTraits> InputChannelConverter;
224typedef TypeConverter<ChannelIndexTraits> ChannelIndexConverter;
225typedef TypeConverter<GainModeTraits> GainModeConverter;
226typedef TypeConverter<StreamTraits> StreamTypeConverter;
227typedef TypeConverter<AudioModeTraits> AudioModeConverter;
228typedef TypeConverter<UsageTraits> UsageTypeConverter;
229typedef TypeConverter<SourceTraits> SourceTypeConverter;
230
231bool deviceFromString(const std::string& literalDevice, audio_devices_t& device);
232
233bool deviceToString(audio_devices_t device, std::string& literalDevice);
234
235SampleRateTraits::Collection samplingRatesFromString(
236        const std::string &samplingRates, const char *del = AudioParameter::valueListSeparator);
237
238FormatTraits::Collection formatsFromString(
239        const std::string &formats, const char *del = AudioParameter::valueListSeparator);
240
241audio_format_t formatFromString(
242        const std::string &literalFormat, audio_format_t defaultFormat = AUDIO_FORMAT_DEFAULT);
243
244audio_channel_mask_t channelMaskFromString(const std::string &literalChannels);
245
246ChannelTraits::Collection channelMasksFromString(
247        const std::string &channels, const char *del = AudioParameter::valueListSeparator);
248
249InputChannelTraits::Collection inputChannelMasksFromString(
250        const std::string &inChannels, const char *del = AudioParameter::valueListSeparator);
251
252OutputChannelTraits::Collection outputChannelMasksFromString(
253        const std::string &outChannels, const char *del = AudioParameter::valueListSeparator);
254
255}; // namespace android
256
257#endif  /*ANDROID_TYPE_CONVERTER_H_*/
258