111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/*
211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * Copyright (C) 2016 The Android Open Source Project
311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar *
411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * you may not use this file except in compliance with the License.
611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * You may obtain a copy of the License at
711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar *
811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar *
1011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * Unless required by applicable law or agreed to in writing, software
1111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
1211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * See the License for the specific language governing permissions and
1411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * limitations under the License.
1511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar */
1611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
1711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#ifndef C2UTILS_PARAM_UTILS_H_
1811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#define C2UTILS_PARAM_UTILS_H_
1911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
2011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#include <C2Param.h>
2111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#include <util/_C2MacroUtils.h>
2211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
2311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#include <iostream>
2411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
2511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/** \file
2611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * Utilities for parameter handling to be used by Codec2 implementations.
2711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar */
2811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
2911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarnamespace android {
3011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
3111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/// \cond INTERNAL
3211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
3311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/* ---------------------------- UTILITIES FOR ENUMERATION REFLECTION ---------------------------- */
3411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
3511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/**
3611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * Utility class that allows ignoring enum value assignment (e.g. both '(_C2EnumConst)kValue = x'
3711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar * and '(_C2EnumConst)kValue' will eval to kValue.
3811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar */
3911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnartemplate<typename T>
4011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarclass _C2EnumConst {
4111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarpublic:
4211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // implicit conversion from T
4311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    inline _C2EnumConst(T value) : _mValue(value) {}
4411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // implicit conversion to T
4511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    inline operator T() { return _mValue; }
4611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // implicit conversion to C2Value::Primitive
4711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    inline operator C2Value::Primitive() { return (T)_mValue; }
4811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // ignore assignment and return T here to avoid implicit conversion to T later
4911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    inline T &operator =(T value __unused) { return _mValue; }
5011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarprivate:
5111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    T _mValue;
5211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar};
5311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
5411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/// mapper to get name of enum
5511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/// \note this will contain any initialization, which we will remove when converting to lower-case
5611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#define _C2_GET_ENUM_NAME(x, y) #x
5711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/// mapper to get value of enum
5811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#define _C2_GET_ENUM_VALUE(x, type) (_C2EnumConst<type>)x
5911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
6011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/// \endcond
6111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
6211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#define DEFINE_C2_ENUM_VALUE_AUTO_HELPER(name, type, prefix, ...) \
6311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnartemplate<> C2FieldDescriptor::named_values_type C2FieldDescriptor::namedValuesFor(const name &r __unused) { \
6411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    return C2ParamUtils::sanitizeEnumValues( \
6511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            std::vector<C2Value::Primitive> { _C2_MAP(_C2_GET_ENUM_VALUE, type, __VA_ARGS__) }, \
6611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            { _C2_MAP(_C2_GET_ENUM_NAME, type, __VA_ARGS__) }, \
6711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            prefix); \
6811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar}
6911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
7011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#define DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(name, type, names, ...) \
7111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnartemplate<> C2FieldDescriptor::named_values_type C2FieldDescriptor::namedValuesFor(const name &r __unused) { \
7211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    return C2ParamUtils::customEnumValues( \
7311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            std::vector<std::pair<C2StringLiteral, name>> names); \
7411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar}
7511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
7611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
7711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarclass C2ParamUtils {
7811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarprivate:
7911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    static size_t countLeadingUnderscores(C2StringLiteral a) {
8011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        size_t i = 0;
8111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        while (a[i] == '_') {
8211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            ++i;
8311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        }
8411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        return i;
8511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    }
8611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
8711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    static size_t countMatching(C2StringLiteral a, const C2String &b) {
8811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        for (size_t i = 0; i < b.size(); ++i) {
8911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            if (!a[i] || a[i] != b[i]) {
9011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                return i;
9111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            }
9211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        }
9311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        return b.size();
9411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    }
9511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
9611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // ABCDef => abc-def
9711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // ABCD2ef => abcd2-ef // 0
9811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // ABCD2Ef => ancd2-ef // -1
9911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // AbcDef => abc-def // -1
10011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // Abc2Def => abc-2def
10111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // Abc2def => abc-2-def
10211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // _Yo => _yo
10311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // _yo => _yo
10411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // C2_yo => c2-yo
10511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    // C2__yo => c2-yo
10611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
10711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    static C2String camelCaseToDashed(C2String name) {
10811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        enum {
10911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            kNone = '.',
11011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            kLower = 'a',
11111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            kUpper = 'A',
11211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            kDigit = '1',
11311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            kDash = '-',
11411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            kUnderscore = '_',
11511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        } type = kNone;
11611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        size_t word_start = 0;
11711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        for (size_t ix = 0; ix < name.size(); ++ix) {
11811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            /* std::cout << name.substr(0, word_start) << "|"
11911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    << name.substr(word_start, ix - word_start) << "["
12011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    << name.substr(ix, 1) << "]" << name.substr(ix + 1)
12111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    << ": " << (char)type << std::endl; */
12211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            if (isupper(name[ix])) {
12311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                if (type == kLower) {
12411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    name.insert(ix++, 1, '-');
12511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    word_start = ix;
12611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                }
12711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                name[ix] = tolower(name[ix]);
12811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                type = kUpper;
12911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            } else if (islower(name[ix])) {
13011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                if (type == kDigit && ix > 0) {
13111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    name.insert(ix++, 1, '-');
13211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    word_start = ix;
13311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                } else if (type == kUpper && ix > word_start + 1) {
13411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    name.insert(ix++ - 1, 1, '-');
13511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    word_start = ix - 1;
13611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                }
13711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                type = kLower;
13811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            } else if (isdigit(name[ix])) {
13911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                if (type == kLower) {
14011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    name.insert(ix++, 1, '-');
14111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    word_start = ix;
14211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                }
14311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                type = kDigit;
14411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            } else if (name[ix] == '_') {
14511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                if (type == kDash) {
14611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    name.erase(ix--, 1);
14711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                } else if (type != kNone && type != kUnderscore) {
14811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    name[ix] = '-';
14911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    type = kDash;
15011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    word_start = ix + 1;
15111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                } else {
15211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    type = kUnderscore;
15311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    word_start = ix + 1;
15411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                }
15511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            } else {
15611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                name.resize(ix);
15711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            }
15811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        }
15911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        // std::cout << "=> " << name << std::endl;
16011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        return name;
16111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    }
16211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
16311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    static std::vector<C2String> sanitizeEnumValueNames(
16411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            const std::vector<C2StringLiteral> names,
16511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            C2StringLiteral _prefix = NULL) {
16611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        std::vector<C2String> sanitizedNames;
16711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        C2String prefix;
16811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        size_t extraUnderscores = 0;
16911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        bool first = true;
17011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        if (_prefix) {
17111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            extraUnderscores = countLeadingUnderscores(_prefix);
17211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            prefix = _prefix + extraUnderscores;
17311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            first = false;
17411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            // std::cout << "prefix:" << prefix << ", underscores:" << extraUnderscores << std::endl;
17511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        }
17611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
17711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        // calculate prefix and minimum leading underscores
17811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        for (C2StringLiteral s : names) {
17911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            // std::cout << s << std::endl;
18011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            size_t underscores = countLeadingUnderscores(s);
18111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            if (first) {
18211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                extraUnderscores = underscores;
18311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                prefix = s + underscores;
18411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                first = false;
18511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            } else {
18611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                size_t matching = countMatching(
18711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    s + underscores,
18811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                    prefix);
18911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                prefix.resize(matching);
19011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                extraUnderscores = std::min(underscores, extraUnderscores);
19111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            }
19211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            // std::cout << "prefix:" << prefix << ", underscores:" << extraUnderscores << std::endl;
19311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            if (prefix.size() == 0 && extraUnderscores == 0) {
19411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                break;
19511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            }
19611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        }
19711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
19811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        // we swallow the first underscore after upper case prefixes
19911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        bool upperCasePrefix = true;
20011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        for (size_t i = 0; i < prefix.size(); ++i) {
20111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            if (islower(prefix[i])) {
20211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                upperCasePrefix = false;
20311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                break;
20411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            }
20511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        }
20611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
20711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        for (C2StringLiteral s : names) {
20811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            size_t underscores = countLeadingUnderscores(s);
20911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            C2String sanitized = C2String(s, underscores - extraUnderscores);
21011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            sanitized.append(s + prefix.size() + underscores +
21111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                        (upperCasePrefix && s[prefix.size() + underscores] == '_'));
21211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            sanitizedNames.push_back(camelCaseToDashed(sanitized));
21311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        }
21411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
21511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        for (C2String s : sanitizedNames) {
21611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            std::cout << s << std::endl;
21711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        }
21811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
21911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        return sanitizedNames;
22011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    }
22111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
22211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    friend class C2ParamTest_ParamUtilsTest_Test;
22311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
22411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarpublic:
22511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    static std::vector<C2String> getEnumValuesFromString(C2StringLiteral value) {
22611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        std::vector<C2String> foundNames;
22711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        size_t pos = 0, len = strlen(value);
22811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        do {
22911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            size_t endPos = strcspn(value + pos, " ,=") + pos;
23011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            if (endPos > pos) {
23111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                foundNames.emplace_back(value + pos, endPos - pos);
23211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            }
23311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            if (value[endPos] && value[endPos] != ',') {
23411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar                endPos += strcspn(value + endPos, ",");
23511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            }
23611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            pos = strspn(value + endPos, " ,") + endPos;
23711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        } while (pos < len);
23811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        return foundNames;
23911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    }
24011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
24111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    template<typename T>
24211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    static C2FieldDescriptor::named_values_type sanitizeEnumValues(
24311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            std::vector<T> values,
24411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            std::vector<C2StringLiteral> names,
24511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            C2StringLiteral prefix = NULL) {
24611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        C2FieldDescriptor::named_values_type namedValues;
24711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        std::vector<C2String> sanitizedNames = sanitizeEnumValueNames(names, prefix);
24811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        for (size_t i = 0; i < values.size() && i < sanitizedNames.size(); ++i) {
24911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            namedValues.emplace_back(sanitizedNames[i], values[i]);
25011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        }
25111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        return namedValues;
25211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    }
25311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
25411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    template<typename E>
25511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    static C2FieldDescriptor::named_values_type customEnumValues(
25611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            std::vector<std::pair<C2StringLiteral, E>> items) {
25711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        C2FieldDescriptor::named_values_type namedValues;
25811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        for (auto &item : items) {
25911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar            namedValues.emplace_back(item.first, item.second);
26011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        }
26111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar        return namedValues;
26211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    }
26311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar};
26411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
26511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/* ---------------------------- UTILITIES FOR PARAMETER REFLECTION ---------------------------- */
26611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
26711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/* ======================== UTILITY TEMPLATES FOR PARAMETER REFLECTION ======================== */
26811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
26911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#if 1
27011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnartemplate<typename... Params>
27111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarclass C2_HIDE _C2Tuple { };
27211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
27311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos MolnarC2_HIDE
27411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarvoid addC2Params(std::list<const C2FieldDescriptor> &, _C2Tuple<> *) {
27511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar}
27611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
27711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnartemplate<typename T, typename... Params>
27811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos MolnarC2_HIDE
27911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarvoid addC2Params(std::list<const C2FieldDescriptor> &fields, _C2Tuple<T, Params...> *)
28011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar{
28111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    //C2Param::index_t index = T::baseIndex;
28211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    //(void)index;
28311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    fields.insert(fields.end(), T::fieldList);
28411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    addC2Params(fields, (_C2Tuple<Params...> *)nullptr);
28511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar}
28611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
28711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnartemplate<typename... Params>
28811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos MolnarC2_HIDE
28911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnarstd::list<const C2FieldDescriptor> describeC2Params() {
29011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    std::list<const C2FieldDescriptor> fields;
29111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    addC2Params(fields, (_C2Tuple<Params...> *)nullptr);
29211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar    return fields;
29311ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar}
29411ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
29511ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#endif
29611ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
29711ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar/* ---------------------------- UTILITIES FOR ENUMERATION REFLECTION ---------------------------- */
29811ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
29911ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar}  // namespace android
30011ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
30111ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar#endif  // C2UTILS_PARAM_UTILS_H_
30211ca9ffc72a9d7c628353c1a9295d3b23ec51d22Lajos Molnar
303