Loading media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h 0 → 100644 +302 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef C2UTILS_PARAM_UTILS_H_ #define C2UTILS_PARAM_UTILS_H_ #include <C2Param.h> #include <util/_C2MacroUtils.h> #include <iostream> /** \file * Utilities for parameter handling to be used by Codec2 implementations. */ namespace android { /// \cond INTERNAL /* ---------------------------- UTILITIES FOR ENUMERATION REFLECTION ---------------------------- */ /** * Utility class that allows ignoring enum value assignment (e.g. both '(_C2EnumConst)kValue = x' * and '(_C2EnumConst)kValue' will eval to kValue. */ template<typename T> class _C2EnumConst { public: // implicit conversion from T inline _C2EnumConst(T value) : _mValue(value) {} // implicit conversion to T inline operator T() { return _mValue; } // implicit conversion to C2Value::Primitive inline operator C2Value::Primitive() { return (T)_mValue; } // ignore assignment and return T here to avoid implicit conversion to T later inline T &operator =(T value __unused) { return _mValue; } private: T _mValue; }; /// mapper to get name of enum /// \note this will contain any initialization, which we will remove when converting to lower-case #define _C2_GET_ENUM_NAME(x, y) #x /// mapper to get value of enum #define _C2_GET_ENUM_VALUE(x, type) (_C2EnumConst<type>)x /// \endcond #define DEFINE_C2_ENUM_VALUE_AUTO_HELPER(name, type, prefix, ...) \ template<> C2FieldDescriptor::named_values_type C2FieldDescriptor::namedValuesFor(const name &r __unused) { \ return C2ParamUtils::sanitizeEnumValues( \ std::vector<C2Value::Primitive> { _C2_MAP(_C2_GET_ENUM_VALUE, type, __VA_ARGS__) }, \ { _C2_MAP(_C2_GET_ENUM_NAME, type, __VA_ARGS__) }, \ prefix); \ } #define DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(name, type, names, ...) \ template<> C2FieldDescriptor::named_values_type C2FieldDescriptor::namedValuesFor(const name &r __unused) { \ return C2ParamUtils::customEnumValues( \ std::vector<std::pair<C2StringLiteral, name>> names); \ } class C2ParamUtils { private: static size_t countLeadingUnderscores(C2StringLiteral a) { size_t i = 0; while (a[i] == '_') { ++i; } return i; } static size_t countMatching(C2StringLiteral a, const C2String &b) { for (size_t i = 0; i < b.size(); ++i) { if (!a[i] || a[i] != b[i]) { return i; } } return b.size(); } // ABCDef => abc-def // ABCD2ef => abcd2-ef // 0 // ABCD2Ef => ancd2-ef // -1 // AbcDef => abc-def // -1 // Abc2Def => abc-2def // Abc2def => abc-2-def // _Yo => _yo // _yo => _yo // C2_yo => c2-yo // C2__yo => c2-yo static C2String camelCaseToDashed(C2String name) { enum { kNone = '.', kLower = 'a', kUpper = 'A', kDigit = '1', kDash = '-', kUnderscore = '_', } type = kNone; size_t word_start = 0; for (size_t ix = 0; ix < name.size(); ++ix) { /* std::cout << name.substr(0, word_start) << "|" << name.substr(word_start, ix - word_start) << "[" << name.substr(ix, 1) << "]" << name.substr(ix + 1) << ": " << (char)type << std::endl; */ if (isupper(name[ix])) { if (type == kLower) { name.insert(ix++, 1, '-'); word_start = ix; } name[ix] = tolower(name[ix]); type = kUpper; } else if (islower(name[ix])) { if (type == kDigit && ix > 0) { name.insert(ix++, 1, '-'); word_start = ix; } else if (type == kUpper && ix > word_start + 1) { name.insert(ix++ - 1, 1, '-'); word_start = ix - 1; } type = kLower; } else if (isdigit(name[ix])) { if (type == kLower) { name.insert(ix++, 1, '-'); word_start = ix; } type = kDigit; } else if (name[ix] == '_') { if (type == kDash) { name.erase(ix--, 1); } else if (type != kNone && type != kUnderscore) { name[ix] = '-'; type = kDash; word_start = ix + 1; } else { type = kUnderscore; word_start = ix + 1; } } else { name.resize(ix); } } // std::cout << "=> " << name << std::endl; return name; } static std::vector<C2String> sanitizeEnumValueNames( const std::vector<C2StringLiteral> names, C2StringLiteral _prefix = NULL) { std::vector<C2String> sanitizedNames; C2String prefix; size_t extraUnderscores = 0; bool first = true; if (_prefix) { extraUnderscores = countLeadingUnderscores(_prefix); prefix = _prefix + extraUnderscores; first = false; // std::cout << "prefix:" << prefix << ", underscores:" << extraUnderscores << std::endl; } // calculate prefix and minimum leading underscores for (C2StringLiteral s : names) { // std::cout << s << std::endl; size_t underscores = countLeadingUnderscores(s); if (first) { extraUnderscores = underscores; prefix = s + underscores; first = false; } else { size_t matching = countMatching( s + underscores, prefix); prefix.resize(matching); extraUnderscores = std::min(underscores, extraUnderscores); } // std::cout << "prefix:" << prefix << ", underscores:" << extraUnderscores << std::endl; if (prefix.size() == 0 && extraUnderscores == 0) { break; } } // we swallow the first underscore after upper case prefixes bool upperCasePrefix = true; for (size_t i = 0; i < prefix.size(); ++i) { if (islower(prefix[i])) { upperCasePrefix = false; break; } } for (C2StringLiteral s : names) { size_t underscores = countLeadingUnderscores(s); C2String sanitized = C2String(s, underscores - extraUnderscores); sanitized.append(s + prefix.size() + underscores + (upperCasePrefix && s[prefix.size() + underscores] == '_')); sanitizedNames.push_back(camelCaseToDashed(sanitized)); } for (C2String s : sanitizedNames) { std::cout << s << std::endl; } return sanitizedNames; } friend class C2ParamTest_ParamUtilsTest_Test; public: static std::vector<C2String> getEnumValuesFromString(C2StringLiteral value) { std::vector<C2String> foundNames; size_t pos = 0, len = strlen(value); do { size_t endPos = strcspn(value + pos, " ,=") + pos; if (endPos > pos) { foundNames.emplace_back(value + pos, endPos - pos); } if (value[endPos] && value[endPos] != ',') { endPos += strcspn(value + endPos, ","); } pos = strspn(value + endPos, " ,") + endPos; } while (pos < len); return foundNames; } template<typename T> static C2FieldDescriptor::named_values_type sanitizeEnumValues( std::vector<T> values, std::vector<C2StringLiteral> names, C2StringLiteral prefix = NULL) { C2FieldDescriptor::named_values_type namedValues; std::vector<C2String> sanitizedNames = sanitizeEnumValueNames(names, prefix); for (size_t i = 0; i < values.size() && i < sanitizedNames.size(); ++i) { namedValues.emplace_back(sanitizedNames[i], values[i]); } return namedValues; } template<typename E> static C2FieldDescriptor::named_values_type customEnumValues( std::vector<std::pair<C2StringLiteral, E>> items) { C2FieldDescriptor::named_values_type namedValues; for (auto &item : items) { namedValues.emplace_back(item.first, item.second); } return namedValues; } }; /* ---------------------------- UTILITIES FOR PARAMETER REFLECTION ---------------------------- */ /* ======================== UTILITY TEMPLATES FOR PARAMETER REFLECTION ======================== */ #if 1 template<typename... Params> class C2_HIDE _C2Tuple { }; C2_HIDE void addC2Params(std::list<const C2FieldDescriptor> &, _C2Tuple<> *) { } template<typename T, typename... Params> C2_HIDE void addC2Params(std::list<const C2FieldDescriptor> &fields, _C2Tuple<T, Params...> *) { //C2Param::index_t index = T::baseIndex; //(void)index; fields.insert(fields.end(), T::fieldList); addC2Params(fields, (_C2Tuple<Params...> *)nullptr); } template<typename... Params> C2_HIDE std::list<const C2FieldDescriptor> describeC2Params() { std::list<const C2FieldDescriptor> fields; addC2Params(fields, (_C2Tuple<Params...> *)nullptr); return fields; } #endif /* ---------------------------- UTILITIES FOR ENUMERATION REFLECTION ---------------------------- */ } // namespace android #endif // C2UTILS_PARAM_UTILS_H_ media/libstagefright/codec2/vndk/include/util/_C2MacroUtils.h 0 → 100644 +162 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef C2UTILS_MACRO_UTILS_H_ #define C2UTILS_MACRO_UTILS_H_ /** \file * Macro utilities for the utils library used by Codec2 implementations. */ /// \if 0 /* --------------------------------- VARIABLE ARGUMENT COUNTING --------------------------------- */ // remove empty arguments - _C2_ARG() expands to '', while _C2_ARG(x) expands to ', x' // _C2_ARGn(...) does the same for n arguments #define _C2_ARG(...) , ##__VA_ARGS__ #define _C2_ARG2(_1, _2) _C2_ARG(_1) _C2_ARG(_2) #define _C2_ARG4(_1, _2, _3, _4) _C2_ARG2(_1, _2) _C2_ARG2(_3, _4) #define _C2_ARG8(_1, _2, _3, _4, _5, _6, _7, _8) _C2_ARG4(_1, _2, _3, _4) _C2_ARG4(_5, _6, _7, _8) #define _C2_ARG16(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ _C2_ARG8(_1, _2, _3, _4, _5, _6, _7, _8) _C2_ARG8(_9, _10, _11, _12, _13, _14, _15, _16) // return the 65th argument #define _C2_ARGC_3(_, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, \ _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, \ _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, ...) _64 /// \endif /** * Returns the number of arguments. */ // We do this by prepending 1 and appending 65 designed values such that the 65th element // will be the number of arguments. #define _C2_ARGC(...) _C2_ARGC_1(0, ##__VA_ARGS__, \ 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, \ 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) /// \if 0 // step 1. remove empty arguments - this is needed to allow trailing comma in enum definitions // (NOTE: we don't know which argument will have this trailing comma so we have to try all) #define _C2_ARGC_1(_, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, \ _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, \ _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, ...) \ _C2_ARGC_2(_ _C2_ARG(_0) \ _C2_ARG16(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ _C2_ARG16(_17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32) \ _C2_ARG16(_33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48) \ _C2_ARG16(_49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64), \ ##__VA_ARGS__) // step 2. this is needed as removed arguments cannot be passed directly as empty into a macro #define _C2_ARGC_2(...) _C2_ARGC_3(__VA_ARGS__) /// \endif /* -------------------------------- VARIABLE ARGUMENT CONVERSION -------------------------------- */ /// \if 0 // macros that convert _1, _2, _3, ... to fn(_1, arg), fn(_2, arg), fn(_3, arg), ... #define _C2_MAP_64(fn, arg, head, ...) fn(head, arg), _C2_MAP_63(fn, arg, ##__VA_ARGS__) #define _C2_MAP_63(fn, arg, head, ...) fn(head, arg), _C2_MAP_62(fn, arg, ##__VA_ARGS__) #define _C2_MAP_62(fn, arg, head, ...) fn(head, arg), _C2_MAP_61(fn, arg, ##__VA_ARGS__) #define _C2_MAP_61(fn, arg, head, ...) fn(head, arg), _C2_MAP_60(fn, arg, ##__VA_ARGS__) #define _C2_MAP_60(fn, arg, head, ...) fn(head, arg), _C2_MAP_59(fn, arg, ##__VA_ARGS__) #define _C2_MAP_59(fn, arg, head, ...) fn(head, arg), _C2_MAP_58(fn, arg, ##__VA_ARGS__) #define _C2_MAP_58(fn, arg, head, ...) fn(head, arg), _C2_MAP_57(fn, arg, ##__VA_ARGS__) #define _C2_MAP_57(fn, arg, head, ...) fn(head, arg), _C2_MAP_56(fn, arg, ##__VA_ARGS__) #define _C2_MAP_56(fn, arg, head, ...) fn(head, arg), _C2_MAP_55(fn, arg, ##__VA_ARGS__) #define _C2_MAP_55(fn, arg, head, ...) fn(head, arg), _C2_MAP_54(fn, arg, ##__VA_ARGS__) #define _C2_MAP_54(fn, arg, head, ...) fn(head, arg), _C2_MAP_53(fn, arg, ##__VA_ARGS__) #define _C2_MAP_53(fn, arg, head, ...) fn(head, arg), _C2_MAP_52(fn, arg, ##__VA_ARGS__) #define _C2_MAP_52(fn, arg, head, ...) fn(head, arg), _C2_MAP_51(fn, arg, ##__VA_ARGS__) #define _C2_MAP_51(fn, arg, head, ...) fn(head, arg), _C2_MAP_50(fn, arg, ##__VA_ARGS__) #define _C2_MAP_50(fn, arg, head, ...) fn(head, arg), _C2_MAP_49(fn, arg, ##__VA_ARGS__) #define _C2_MAP_49(fn, arg, head, ...) fn(head, arg), _C2_MAP_48(fn, arg, ##__VA_ARGS__) #define _C2_MAP_48(fn, arg, head, ...) fn(head, arg), _C2_MAP_47(fn, arg, ##__VA_ARGS__) #define _C2_MAP_47(fn, arg, head, ...) fn(head, arg), _C2_MAP_46(fn, arg, ##__VA_ARGS__) #define _C2_MAP_46(fn, arg, head, ...) fn(head, arg), _C2_MAP_45(fn, arg, ##__VA_ARGS__) #define _C2_MAP_45(fn, arg, head, ...) fn(head, arg), _C2_MAP_44(fn, arg, ##__VA_ARGS__) #define _C2_MAP_44(fn, arg, head, ...) fn(head, arg), _C2_MAP_43(fn, arg, ##__VA_ARGS__) #define _C2_MAP_43(fn, arg, head, ...) fn(head, arg), _C2_MAP_42(fn, arg, ##__VA_ARGS__) #define _C2_MAP_42(fn, arg, head, ...) fn(head, arg), _C2_MAP_41(fn, arg, ##__VA_ARGS__) #define _C2_MAP_41(fn, arg, head, ...) fn(head, arg), _C2_MAP_40(fn, arg, ##__VA_ARGS__) #define _C2_MAP_40(fn, arg, head, ...) fn(head, arg), _C2_MAP_39(fn, arg, ##__VA_ARGS__) #define _C2_MAP_39(fn, arg, head, ...) fn(head, arg), _C2_MAP_38(fn, arg, ##__VA_ARGS__) #define _C2_MAP_38(fn, arg, head, ...) fn(head, arg), _C2_MAP_37(fn, arg, ##__VA_ARGS__) #define _C2_MAP_37(fn, arg, head, ...) fn(head, arg), _C2_MAP_36(fn, arg, ##__VA_ARGS__) #define _C2_MAP_36(fn, arg, head, ...) fn(head, arg), _C2_MAP_35(fn, arg, ##__VA_ARGS__) #define _C2_MAP_35(fn, arg, head, ...) fn(head, arg), _C2_MAP_34(fn, arg, ##__VA_ARGS__) #define _C2_MAP_34(fn, arg, head, ...) fn(head, arg), _C2_MAP_33(fn, arg, ##__VA_ARGS__) #define _C2_MAP_33(fn, arg, head, ...) fn(head, arg), _C2_MAP_32(fn, arg, ##__VA_ARGS__) #define _C2_MAP_32(fn, arg, head, ...) fn(head, arg), _C2_MAP_31(fn, arg, ##__VA_ARGS__) #define _C2_MAP_31(fn, arg, head, ...) fn(head, arg), _C2_MAP_30(fn, arg, ##__VA_ARGS__) #define _C2_MAP_30(fn, arg, head, ...) fn(head, arg), _C2_MAP_29(fn, arg, ##__VA_ARGS__) #define _C2_MAP_29(fn, arg, head, ...) fn(head, arg), _C2_MAP_28(fn, arg, ##__VA_ARGS__) #define _C2_MAP_28(fn, arg, head, ...) fn(head, arg), _C2_MAP_27(fn, arg, ##__VA_ARGS__) #define _C2_MAP_27(fn, arg, head, ...) fn(head, arg), _C2_MAP_26(fn, arg, ##__VA_ARGS__) #define _C2_MAP_26(fn, arg, head, ...) fn(head, arg), _C2_MAP_25(fn, arg, ##__VA_ARGS__) #define _C2_MAP_25(fn, arg, head, ...) fn(head, arg), _C2_MAP_24(fn, arg, ##__VA_ARGS__) #define _C2_MAP_24(fn, arg, head, ...) fn(head, arg), _C2_MAP_23(fn, arg, ##__VA_ARGS__) #define _C2_MAP_23(fn, arg, head, ...) fn(head, arg), _C2_MAP_22(fn, arg, ##__VA_ARGS__) #define _C2_MAP_22(fn, arg, head, ...) fn(head, arg), _C2_MAP_21(fn, arg, ##__VA_ARGS__) #define _C2_MAP_21(fn, arg, head, ...) fn(head, arg), _C2_MAP_20(fn, arg, ##__VA_ARGS__) #define _C2_MAP_20(fn, arg, head, ...) fn(head, arg), _C2_MAP_19(fn, arg, ##__VA_ARGS__) #define _C2_MAP_19(fn, arg, head, ...) fn(head, arg), _C2_MAP_18(fn, arg, ##__VA_ARGS__) #define _C2_MAP_18(fn, arg, head, ...) fn(head, arg), _C2_MAP_17(fn, arg, ##__VA_ARGS__) #define _C2_MAP_17(fn, arg, head, ...) fn(head, arg), _C2_MAP_16(fn, arg, ##__VA_ARGS__) #define _C2_MAP_16(fn, arg, head, ...) fn(head, arg), _C2_MAP_15(fn, arg, ##__VA_ARGS__) #define _C2_MAP_15(fn, arg, head, ...) fn(head, arg), _C2_MAP_14(fn, arg, ##__VA_ARGS__) #define _C2_MAP_14(fn, arg, head, ...) fn(head, arg), _C2_MAP_13(fn, arg, ##__VA_ARGS__) #define _C2_MAP_13(fn, arg, head, ...) fn(head, arg), _C2_MAP_12(fn, arg, ##__VA_ARGS__) #define _C2_MAP_12(fn, arg, head, ...) fn(head, arg), _C2_MAP_11(fn, arg, ##__VA_ARGS__) #define _C2_MAP_11(fn, arg, head, ...) fn(head, arg), _C2_MAP_10(fn, arg, ##__VA_ARGS__) #define _C2_MAP_10(fn, arg, head, ...) fn(head, arg), _C2_MAP_9(fn, arg, ##__VA_ARGS__) #define _C2_MAP_9(fn, arg, head, ...) fn(head, arg), _C2_MAP_8(fn, arg, ##__VA_ARGS__) #define _C2_MAP_8(fn, arg, head, ...) fn(head, arg), _C2_MAP_7(fn, arg, ##__VA_ARGS__) #define _C2_MAP_7(fn, arg, head, ...) fn(head, arg), _C2_MAP_6(fn, arg, ##__VA_ARGS__) #define _C2_MAP_6(fn, arg, head, ...) fn(head, arg), _C2_MAP_5(fn, arg, ##__VA_ARGS__) #define _C2_MAP_5(fn, arg, head, ...) fn(head, arg), _C2_MAP_4(fn, arg, ##__VA_ARGS__) #define _C2_MAP_4(fn, arg, head, ...) fn(head, arg), _C2_MAP_3(fn, arg, ##__VA_ARGS__) #define _C2_MAP_3(fn, arg, head, ...) fn(head, arg), _C2_MAP_2(fn, arg, ##__VA_ARGS__) #define _C2_MAP_2(fn, arg, head, ...) fn(head, arg), _C2_MAP_1(fn, arg, ##__VA_ARGS__) #define _C2_MAP_1(fn, arg, head, ...) fn(head, arg) /// \endif /** * Maps each argument using another macro x -> fn(x, arg) */ // use wrapper to call the proper mapper based on the number of arguments #define _C2_MAP(fn, arg, ...) _C2_MAP__(_C2_ARGC(__VA_ARGS__), fn, arg, ##__VA_ARGS__) /// \if 0 // evaluate _n so it becomes a number #define _C2_MAP__(_n, fn, arg, ...) _C2_MAP_(_n, fn, arg, __VA_ARGS__) // call the proper mapper #define _C2_MAP_(_n, fn, arg, ...) _C2_MAP_##_n (fn, arg, __VA_ARGS__) /// \endif #endif // C2UTILS_MACRO_UTILS_H_ Loading
media/libstagefright/codec2/vndk/include/util/C2ParamUtils.h 0 → 100644 +302 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef C2UTILS_PARAM_UTILS_H_ #define C2UTILS_PARAM_UTILS_H_ #include <C2Param.h> #include <util/_C2MacroUtils.h> #include <iostream> /** \file * Utilities for parameter handling to be used by Codec2 implementations. */ namespace android { /// \cond INTERNAL /* ---------------------------- UTILITIES FOR ENUMERATION REFLECTION ---------------------------- */ /** * Utility class that allows ignoring enum value assignment (e.g. both '(_C2EnumConst)kValue = x' * and '(_C2EnumConst)kValue' will eval to kValue. */ template<typename T> class _C2EnumConst { public: // implicit conversion from T inline _C2EnumConst(T value) : _mValue(value) {} // implicit conversion to T inline operator T() { return _mValue; } // implicit conversion to C2Value::Primitive inline operator C2Value::Primitive() { return (T)_mValue; } // ignore assignment and return T here to avoid implicit conversion to T later inline T &operator =(T value __unused) { return _mValue; } private: T _mValue; }; /// mapper to get name of enum /// \note this will contain any initialization, which we will remove when converting to lower-case #define _C2_GET_ENUM_NAME(x, y) #x /// mapper to get value of enum #define _C2_GET_ENUM_VALUE(x, type) (_C2EnumConst<type>)x /// \endcond #define DEFINE_C2_ENUM_VALUE_AUTO_HELPER(name, type, prefix, ...) \ template<> C2FieldDescriptor::named_values_type C2FieldDescriptor::namedValuesFor(const name &r __unused) { \ return C2ParamUtils::sanitizeEnumValues( \ std::vector<C2Value::Primitive> { _C2_MAP(_C2_GET_ENUM_VALUE, type, __VA_ARGS__) }, \ { _C2_MAP(_C2_GET_ENUM_NAME, type, __VA_ARGS__) }, \ prefix); \ } #define DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(name, type, names, ...) \ template<> C2FieldDescriptor::named_values_type C2FieldDescriptor::namedValuesFor(const name &r __unused) { \ return C2ParamUtils::customEnumValues( \ std::vector<std::pair<C2StringLiteral, name>> names); \ } class C2ParamUtils { private: static size_t countLeadingUnderscores(C2StringLiteral a) { size_t i = 0; while (a[i] == '_') { ++i; } return i; } static size_t countMatching(C2StringLiteral a, const C2String &b) { for (size_t i = 0; i < b.size(); ++i) { if (!a[i] || a[i] != b[i]) { return i; } } return b.size(); } // ABCDef => abc-def // ABCD2ef => abcd2-ef // 0 // ABCD2Ef => ancd2-ef // -1 // AbcDef => abc-def // -1 // Abc2Def => abc-2def // Abc2def => abc-2-def // _Yo => _yo // _yo => _yo // C2_yo => c2-yo // C2__yo => c2-yo static C2String camelCaseToDashed(C2String name) { enum { kNone = '.', kLower = 'a', kUpper = 'A', kDigit = '1', kDash = '-', kUnderscore = '_', } type = kNone; size_t word_start = 0; for (size_t ix = 0; ix < name.size(); ++ix) { /* std::cout << name.substr(0, word_start) << "|" << name.substr(word_start, ix - word_start) << "[" << name.substr(ix, 1) << "]" << name.substr(ix + 1) << ": " << (char)type << std::endl; */ if (isupper(name[ix])) { if (type == kLower) { name.insert(ix++, 1, '-'); word_start = ix; } name[ix] = tolower(name[ix]); type = kUpper; } else if (islower(name[ix])) { if (type == kDigit && ix > 0) { name.insert(ix++, 1, '-'); word_start = ix; } else if (type == kUpper && ix > word_start + 1) { name.insert(ix++ - 1, 1, '-'); word_start = ix - 1; } type = kLower; } else if (isdigit(name[ix])) { if (type == kLower) { name.insert(ix++, 1, '-'); word_start = ix; } type = kDigit; } else if (name[ix] == '_') { if (type == kDash) { name.erase(ix--, 1); } else if (type != kNone && type != kUnderscore) { name[ix] = '-'; type = kDash; word_start = ix + 1; } else { type = kUnderscore; word_start = ix + 1; } } else { name.resize(ix); } } // std::cout << "=> " << name << std::endl; return name; } static std::vector<C2String> sanitizeEnumValueNames( const std::vector<C2StringLiteral> names, C2StringLiteral _prefix = NULL) { std::vector<C2String> sanitizedNames; C2String prefix; size_t extraUnderscores = 0; bool first = true; if (_prefix) { extraUnderscores = countLeadingUnderscores(_prefix); prefix = _prefix + extraUnderscores; first = false; // std::cout << "prefix:" << prefix << ", underscores:" << extraUnderscores << std::endl; } // calculate prefix and minimum leading underscores for (C2StringLiteral s : names) { // std::cout << s << std::endl; size_t underscores = countLeadingUnderscores(s); if (first) { extraUnderscores = underscores; prefix = s + underscores; first = false; } else { size_t matching = countMatching( s + underscores, prefix); prefix.resize(matching); extraUnderscores = std::min(underscores, extraUnderscores); } // std::cout << "prefix:" << prefix << ", underscores:" << extraUnderscores << std::endl; if (prefix.size() == 0 && extraUnderscores == 0) { break; } } // we swallow the first underscore after upper case prefixes bool upperCasePrefix = true; for (size_t i = 0; i < prefix.size(); ++i) { if (islower(prefix[i])) { upperCasePrefix = false; break; } } for (C2StringLiteral s : names) { size_t underscores = countLeadingUnderscores(s); C2String sanitized = C2String(s, underscores - extraUnderscores); sanitized.append(s + prefix.size() + underscores + (upperCasePrefix && s[prefix.size() + underscores] == '_')); sanitizedNames.push_back(camelCaseToDashed(sanitized)); } for (C2String s : sanitizedNames) { std::cout << s << std::endl; } return sanitizedNames; } friend class C2ParamTest_ParamUtilsTest_Test; public: static std::vector<C2String> getEnumValuesFromString(C2StringLiteral value) { std::vector<C2String> foundNames; size_t pos = 0, len = strlen(value); do { size_t endPos = strcspn(value + pos, " ,=") + pos; if (endPos > pos) { foundNames.emplace_back(value + pos, endPos - pos); } if (value[endPos] && value[endPos] != ',') { endPos += strcspn(value + endPos, ","); } pos = strspn(value + endPos, " ,") + endPos; } while (pos < len); return foundNames; } template<typename T> static C2FieldDescriptor::named_values_type sanitizeEnumValues( std::vector<T> values, std::vector<C2StringLiteral> names, C2StringLiteral prefix = NULL) { C2FieldDescriptor::named_values_type namedValues; std::vector<C2String> sanitizedNames = sanitizeEnumValueNames(names, prefix); for (size_t i = 0; i < values.size() && i < sanitizedNames.size(); ++i) { namedValues.emplace_back(sanitizedNames[i], values[i]); } return namedValues; } template<typename E> static C2FieldDescriptor::named_values_type customEnumValues( std::vector<std::pair<C2StringLiteral, E>> items) { C2FieldDescriptor::named_values_type namedValues; for (auto &item : items) { namedValues.emplace_back(item.first, item.second); } return namedValues; } }; /* ---------------------------- UTILITIES FOR PARAMETER REFLECTION ---------------------------- */ /* ======================== UTILITY TEMPLATES FOR PARAMETER REFLECTION ======================== */ #if 1 template<typename... Params> class C2_HIDE _C2Tuple { }; C2_HIDE void addC2Params(std::list<const C2FieldDescriptor> &, _C2Tuple<> *) { } template<typename T, typename... Params> C2_HIDE void addC2Params(std::list<const C2FieldDescriptor> &fields, _C2Tuple<T, Params...> *) { //C2Param::index_t index = T::baseIndex; //(void)index; fields.insert(fields.end(), T::fieldList); addC2Params(fields, (_C2Tuple<Params...> *)nullptr); } template<typename... Params> C2_HIDE std::list<const C2FieldDescriptor> describeC2Params() { std::list<const C2FieldDescriptor> fields; addC2Params(fields, (_C2Tuple<Params...> *)nullptr); return fields; } #endif /* ---------------------------- UTILITIES FOR ENUMERATION REFLECTION ---------------------------- */ } // namespace android #endif // C2UTILS_PARAM_UTILS_H_
media/libstagefright/codec2/vndk/include/util/_C2MacroUtils.h 0 → 100644 +162 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef C2UTILS_MACRO_UTILS_H_ #define C2UTILS_MACRO_UTILS_H_ /** \file * Macro utilities for the utils library used by Codec2 implementations. */ /// \if 0 /* --------------------------------- VARIABLE ARGUMENT COUNTING --------------------------------- */ // remove empty arguments - _C2_ARG() expands to '', while _C2_ARG(x) expands to ', x' // _C2_ARGn(...) does the same for n arguments #define _C2_ARG(...) , ##__VA_ARGS__ #define _C2_ARG2(_1, _2) _C2_ARG(_1) _C2_ARG(_2) #define _C2_ARG4(_1, _2, _3, _4) _C2_ARG2(_1, _2) _C2_ARG2(_3, _4) #define _C2_ARG8(_1, _2, _3, _4, _5, _6, _7, _8) _C2_ARG4(_1, _2, _3, _4) _C2_ARG4(_5, _6, _7, _8) #define _C2_ARG16(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ _C2_ARG8(_1, _2, _3, _4, _5, _6, _7, _8) _C2_ARG8(_9, _10, _11, _12, _13, _14, _15, _16) // return the 65th argument #define _C2_ARGC_3(_, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, \ _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, \ _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, ...) _64 /// \endif /** * Returns the number of arguments. */ // We do this by prepending 1 and appending 65 designed values such that the 65th element // will be the number of arguments. #define _C2_ARGC(...) _C2_ARGC_1(0, ##__VA_ARGS__, \ 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, \ 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) /// \if 0 // step 1. remove empty arguments - this is needed to allow trailing comma in enum definitions // (NOTE: we don't know which argument will have this trailing comma so we have to try all) #define _C2_ARGC_1(_, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, \ _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, \ _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, ...) \ _C2_ARGC_2(_ _C2_ARG(_0) \ _C2_ARG16(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ _C2_ARG16(_17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32) \ _C2_ARG16(_33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48) \ _C2_ARG16(_49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64), \ ##__VA_ARGS__) // step 2. this is needed as removed arguments cannot be passed directly as empty into a macro #define _C2_ARGC_2(...) _C2_ARGC_3(__VA_ARGS__) /// \endif /* -------------------------------- VARIABLE ARGUMENT CONVERSION -------------------------------- */ /// \if 0 // macros that convert _1, _2, _3, ... to fn(_1, arg), fn(_2, arg), fn(_3, arg), ... #define _C2_MAP_64(fn, arg, head, ...) fn(head, arg), _C2_MAP_63(fn, arg, ##__VA_ARGS__) #define _C2_MAP_63(fn, arg, head, ...) fn(head, arg), _C2_MAP_62(fn, arg, ##__VA_ARGS__) #define _C2_MAP_62(fn, arg, head, ...) fn(head, arg), _C2_MAP_61(fn, arg, ##__VA_ARGS__) #define _C2_MAP_61(fn, arg, head, ...) fn(head, arg), _C2_MAP_60(fn, arg, ##__VA_ARGS__) #define _C2_MAP_60(fn, arg, head, ...) fn(head, arg), _C2_MAP_59(fn, arg, ##__VA_ARGS__) #define _C2_MAP_59(fn, arg, head, ...) fn(head, arg), _C2_MAP_58(fn, arg, ##__VA_ARGS__) #define _C2_MAP_58(fn, arg, head, ...) fn(head, arg), _C2_MAP_57(fn, arg, ##__VA_ARGS__) #define _C2_MAP_57(fn, arg, head, ...) fn(head, arg), _C2_MAP_56(fn, arg, ##__VA_ARGS__) #define _C2_MAP_56(fn, arg, head, ...) fn(head, arg), _C2_MAP_55(fn, arg, ##__VA_ARGS__) #define _C2_MAP_55(fn, arg, head, ...) fn(head, arg), _C2_MAP_54(fn, arg, ##__VA_ARGS__) #define _C2_MAP_54(fn, arg, head, ...) fn(head, arg), _C2_MAP_53(fn, arg, ##__VA_ARGS__) #define _C2_MAP_53(fn, arg, head, ...) fn(head, arg), _C2_MAP_52(fn, arg, ##__VA_ARGS__) #define _C2_MAP_52(fn, arg, head, ...) fn(head, arg), _C2_MAP_51(fn, arg, ##__VA_ARGS__) #define _C2_MAP_51(fn, arg, head, ...) fn(head, arg), _C2_MAP_50(fn, arg, ##__VA_ARGS__) #define _C2_MAP_50(fn, arg, head, ...) fn(head, arg), _C2_MAP_49(fn, arg, ##__VA_ARGS__) #define _C2_MAP_49(fn, arg, head, ...) fn(head, arg), _C2_MAP_48(fn, arg, ##__VA_ARGS__) #define _C2_MAP_48(fn, arg, head, ...) fn(head, arg), _C2_MAP_47(fn, arg, ##__VA_ARGS__) #define _C2_MAP_47(fn, arg, head, ...) fn(head, arg), _C2_MAP_46(fn, arg, ##__VA_ARGS__) #define _C2_MAP_46(fn, arg, head, ...) fn(head, arg), _C2_MAP_45(fn, arg, ##__VA_ARGS__) #define _C2_MAP_45(fn, arg, head, ...) fn(head, arg), _C2_MAP_44(fn, arg, ##__VA_ARGS__) #define _C2_MAP_44(fn, arg, head, ...) fn(head, arg), _C2_MAP_43(fn, arg, ##__VA_ARGS__) #define _C2_MAP_43(fn, arg, head, ...) fn(head, arg), _C2_MAP_42(fn, arg, ##__VA_ARGS__) #define _C2_MAP_42(fn, arg, head, ...) fn(head, arg), _C2_MAP_41(fn, arg, ##__VA_ARGS__) #define _C2_MAP_41(fn, arg, head, ...) fn(head, arg), _C2_MAP_40(fn, arg, ##__VA_ARGS__) #define _C2_MAP_40(fn, arg, head, ...) fn(head, arg), _C2_MAP_39(fn, arg, ##__VA_ARGS__) #define _C2_MAP_39(fn, arg, head, ...) fn(head, arg), _C2_MAP_38(fn, arg, ##__VA_ARGS__) #define _C2_MAP_38(fn, arg, head, ...) fn(head, arg), _C2_MAP_37(fn, arg, ##__VA_ARGS__) #define _C2_MAP_37(fn, arg, head, ...) fn(head, arg), _C2_MAP_36(fn, arg, ##__VA_ARGS__) #define _C2_MAP_36(fn, arg, head, ...) fn(head, arg), _C2_MAP_35(fn, arg, ##__VA_ARGS__) #define _C2_MAP_35(fn, arg, head, ...) fn(head, arg), _C2_MAP_34(fn, arg, ##__VA_ARGS__) #define _C2_MAP_34(fn, arg, head, ...) fn(head, arg), _C2_MAP_33(fn, arg, ##__VA_ARGS__) #define _C2_MAP_33(fn, arg, head, ...) fn(head, arg), _C2_MAP_32(fn, arg, ##__VA_ARGS__) #define _C2_MAP_32(fn, arg, head, ...) fn(head, arg), _C2_MAP_31(fn, arg, ##__VA_ARGS__) #define _C2_MAP_31(fn, arg, head, ...) fn(head, arg), _C2_MAP_30(fn, arg, ##__VA_ARGS__) #define _C2_MAP_30(fn, arg, head, ...) fn(head, arg), _C2_MAP_29(fn, arg, ##__VA_ARGS__) #define _C2_MAP_29(fn, arg, head, ...) fn(head, arg), _C2_MAP_28(fn, arg, ##__VA_ARGS__) #define _C2_MAP_28(fn, arg, head, ...) fn(head, arg), _C2_MAP_27(fn, arg, ##__VA_ARGS__) #define _C2_MAP_27(fn, arg, head, ...) fn(head, arg), _C2_MAP_26(fn, arg, ##__VA_ARGS__) #define _C2_MAP_26(fn, arg, head, ...) fn(head, arg), _C2_MAP_25(fn, arg, ##__VA_ARGS__) #define _C2_MAP_25(fn, arg, head, ...) fn(head, arg), _C2_MAP_24(fn, arg, ##__VA_ARGS__) #define _C2_MAP_24(fn, arg, head, ...) fn(head, arg), _C2_MAP_23(fn, arg, ##__VA_ARGS__) #define _C2_MAP_23(fn, arg, head, ...) fn(head, arg), _C2_MAP_22(fn, arg, ##__VA_ARGS__) #define _C2_MAP_22(fn, arg, head, ...) fn(head, arg), _C2_MAP_21(fn, arg, ##__VA_ARGS__) #define _C2_MAP_21(fn, arg, head, ...) fn(head, arg), _C2_MAP_20(fn, arg, ##__VA_ARGS__) #define _C2_MAP_20(fn, arg, head, ...) fn(head, arg), _C2_MAP_19(fn, arg, ##__VA_ARGS__) #define _C2_MAP_19(fn, arg, head, ...) fn(head, arg), _C2_MAP_18(fn, arg, ##__VA_ARGS__) #define _C2_MAP_18(fn, arg, head, ...) fn(head, arg), _C2_MAP_17(fn, arg, ##__VA_ARGS__) #define _C2_MAP_17(fn, arg, head, ...) fn(head, arg), _C2_MAP_16(fn, arg, ##__VA_ARGS__) #define _C2_MAP_16(fn, arg, head, ...) fn(head, arg), _C2_MAP_15(fn, arg, ##__VA_ARGS__) #define _C2_MAP_15(fn, arg, head, ...) fn(head, arg), _C2_MAP_14(fn, arg, ##__VA_ARGS__) #define _C2_MAP_14(fn, arg, head, ...) fn(head, arg), _C2_MAP_13(fn, arg, ##__VA_ARGS__) #define _C2_MAP_13(fn, arg, head, ...) fn(head, arg), _C2_MAP_12(fn, arg, ##__VA_ARGS__) #define _C2_MAP_12(fn, arg, head, ...) fn(head, arg), _C2_MAP_11(fn, arg, ##__VA_ARGS__) #define _C2_MAP_11(fn, arg, head, ...) fn(head, arg), _C2_MAP_10(fn, arg, ##__VA_ARGS__) #define _C2_MAP_10(fn, arg, head, ...) fn(head, arg), _C2_MAP_9(fn, arg, ##__VA_ARGS__) #define _C2_MAP_9(fn, arg, head, ...) fn(head, arg), _C2_MAP_8(fn, arg, ##__VA_ARGS__) #define _C2_MAP_8(fn, arg, head, ...) fn(head, arg), _C2_MAP_7(fn, arg, ##__VA_ARGS__) #define _C2_MAP_7(fn, arg, head, ...) fn(head, arg), _C2_MAP_6(fn, arg, ##__VA_ARGS__) #define _C2_MAP_6(fn, arg, head, ...) fn(head, arg), _C2_MAP_5(fn, arg, ##__VA_ARGS__) #define _C2_MAP_5(fn, arg, head, ...) fn(head, arg), _C2_MAP_4(fn, arg, ##__VA_ARGS__) #define _C2_MAP_4(fn, arg, head, ...) fn(head, arg), _C2_MAP_3(fn, arg, ##__VA_ARGS__) #define _C2_MAP_3(fn, arg, head, ...) fn(head, arg), _C2_MAP_2(fn, arg, ##__VA_ARGS__) #define _C2_MAP_2(fn, arg, head, ...) fn(head, arg), _C2_MAP_1(fn, arg, ##__VA_ARGS__) #define _C2_MAP_1(fn, arg, head, ...) fn(head, arg) /// \endif /** * Maps each argument using another macro x -> fn(x, arg) */ // use wrapper to call the proper mapper based on the number of arguments #define _C2_MAP(fn, arg, ...) _C2_MAP__(_C2_ARGC(__VA_ARGS__), fn, arg, ##__VA_ARGS__) /// \if 0 // evaluate _n so it becomes a number #define _C2_MAP__(_n, fn, arg, ...) _C2_MAP_(_n, fn, arg, __VA_ARGS__) // call the proper mapper #define _C2_MAP_(_n, fn, arg, ...) _C2_MAP_##_n (fn, arg, __VA_ARGS__) /// \endif #endif // C2UTILS_MACRO_UTILS_H_