You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
6.2 KiB
210 lines
6.2 KiB
/*
|
|
* 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.
|
|
*/
|
|
|
|
#define __C2_GENERATE_GLOBAL_VARS__ // to be able to implement the methods defined
|
|
#include <C2Enum.h>
|
|
#include <util/C2Debug-log.h>
|
|
#include <util/C2ParamUtils.h>
|
|
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
/** \file
|
|
* Utilities for parameter handling to be used by Codec2 implementations.
|
|
*/
|
|
|
|
/// \cond INTERNAL
|
|
|
|
/* ---------------------------- UTILITIES FOR ENUMERATION REFLECTION ---------------------------- */
|
|
|
|
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 _C2EnumUtils::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) {
|
|
C2_LOG(VERBOSE) << name.substr(0, word_start) << "|"
|
|
<< name.substr(word_start, ix - word_start) << "["
|
|
<< name.substr(ix, 1) << "]" << name.substr(ix + 1)
|
|
<< ": " << (char)type;
|
|
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);
|
|
}
|
|
}
|
|
C2_LOG(VERBOSE) << "=> " << name;
|
|
return name;
|
|
}
|
|
|
|
//static
|
|
std::vector<C2String> _C2EnumUtils::sanitizeEnumValueNames(
|
|
const std::vector<C2StringLiteral> names,
|
|
C2StringLiteral _prefix) {
|
|
std::vector<C2String> sanitizedNames;
|
|
C2String prefix;
|
|
size_t extraUnderscores = 0;
|
|
bool first = true;
|
|
if (_prefix) {
|
|
extraUnderscores = countLeadingUnderscores(_prefix);
|
|
prefix = _prefix + extraUnderscores;
|
|
first = false;
|
|
C2_LOG(VERBOSE) << "prefix:" << prefix << ", underscores:" << extraUnderscores;
|
|
}
|
|
|
|
// calculate prefix and minimum leading underscores
|
|
for (C2StringLiteral s : names) {
|
|
C2_LOG(VERBOSE) << s;
|
|
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);
|
|
}
|
|
C2_LOG(VERBOSE) << "prefix:" << prefix << ", underscores:" << extraUnderscores;
|
|
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) {
|
|
C2_LOG(VERBOSE) << s;
|
|
}
|
|
|
|
return sanitizedNames;
|
|
}
|
|
|
|
//static
|
|
std::vector<C2String> _C2EnumUtils::parseEnumValuesFromString(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;
|
|
}
|
|
|
|
/// safe(r) parsing from parameter blob
|
|
//static
|
|
C2Param *C2ParamUtils::ParseFirst(const uint8_t *blob, size_t size) {
|
|
// _mSize must fit into size, but really C2Param must also to be a valid param
|
|
if (size < sizeof(C2Param)) {
|
|
return nullptr;
|
|
}
|
|
// _mSize must match length
|
|
C2Param *param = (C2Param*)blob;
|
|
if (param->size() > size) {
|
|
return nullptr;
|
|
}
|
|
return param;
|
|
}
|
|
|