FreeCAD

Форк
0
/
IndexedName.cpp 
122 строки · 5.2 Кб
1
// SPDX-License-Identifier: LGPL-2.1-or-later
2

3
/****************************************************************************
4
 *   Copyright (c) 2022 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
5
 *   Copyright (c) 2023 FreeCAD Project Association                         *
6
 *                                                                          *
7
 *   This file is part of FreeCAD.                                          *
8
 *                                                                          *
9
 *   FreeCAD is free software: you can redistribute it and/or modify it     *
10
 *   under the terms of the GNU Lesser General Public License as            *
11
 *   published by the Free Software Foundation, either version 2.1 of the   *
12
 *   License, or (at your option) any later version.                        *
13
 *                                                                          *
14
 *   FreeCAD is distributed in the hope that it will be useful, but         *
15
 *   WITHOUT ANY WARRANTY; without even the implied warranty of             *
16
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU       *
17
 *   Lesser General Public License for more details.                        *
18
 *                                                                          *
19
 *   You should have received a copy of the GNU Lesser General Public       *
20
 *   License along with FreeCAD. If not, see                                *
21
 *   <https://www.gnu.org/licenses/>.                                       *
22
 *                                                                          *
23
 ***************************************************************************/
24

25
// NOLINTNEXTLINE
26
#include "PreCompiled.h"
27

28
#ifndef _PreComp_
29
# include <cstdlib>
30
# include <unordered_set>
31
#endif
32

33
#include "IndexedName.h"
34

35
using namespace Data;
36

37
/// Check whether the input character is an underscore or an ASCII letter a-Z or A-Z
38
inline bool isInvalidChar(char test)
39
{
40
    return test != '_' && (test < 'a' || test > 'z' ) && (test < 'A' || test > 'Z');
41
}
42

43
/// Get the integer suffix of name. Returns a tuple of (suffix, suffixPosition). Calling code
44
/// should check to ensure that suffixPosition is not equal to nameLength (in which case there was no
45
/// suffix).
46
///
47
/// \param name The name to check
48
/// \param nameLength The length of the string in name
49
/// \returns An integer pair of the suffix itself and the position of that suffix in name
50
std::pair<int,int> getIntegerSuffix(const char *name, int nameLength)
51
{
52
    int suffixPosition {nameLength - 1};
53

54
    for (; suffixPosition >= 0; --suffixPosition) {
55
        // When we support C++20 we can use std::span<> to eliminate the clang-tidy warning
56
        // NOLINTNEXTLINE cppcoreguidelines-pro-bounds-pointer-arithmetic
57
        if (!isdigit(name[suffixPosition])) {
58
            break;
59
        }
60
    }
61
    ++suffixPosition;
62
    int suffix {0};
63
    if (suffixPosition < nameLength) {
64
        // When we support C++20 we can use std::span<> to eliminate the clang-tidy warning
65
        // NOLINTNEXTLINE cppcoreguidelines-pro-bounds-pointer-arithmetic
66
        suffix = std::atoi(name + suffixPosition);
67
    }
68
    return std::make_pair(suffix, suffixPosition);
69
}
70

71
void IndexedName::set(
72
    const char* name,
73
    int length,
74
    const std::vector<const char*>& allowedNames,
75
    bool allowOthers)
76
{
77
    // Storage for names that we weren't given external storage for
78
    static std::unordered_set<ByteArray, ByteArrayHasher> NameSet;
79

80
    if (length < 0) {
81
        length = static_cast<int>(std::strlen(name));
82
    }
83
    // Name typically ends with an integer: find that integer
84
    auto [suffix, suffixPosition] = getIntegerSuffix(name, length);
85
    if (suffixPosition < length) {
86
        this->index = suffix;
87
    }
88

89
    // Make sure that every character is either an ASCII letter (upper or lowercase), or an
90
    // underscore. If any other character appears, reject the entire string.
91
    // When we support C++20 we can use std::span<> to eliminate the clang-tidy warning
92
    // NOLINTNEXTLINE cppcoreguidelines-pro-bounds-pointer-arithmetic
93
    if (std::any_of(name, name+suffixPosition, isInvalidChar)) {
94
        this->type = "";
95
        return;
96
    }
97

98
    // If a list of allowedNames was provided, see if our set name matches one of those allowedNames: if it
99
    // does, reference that memory location and return.
100
    for (const auto *typeName : allowedNames) {
101
        if (std::strncmp(name, typeName, suffixPosition) == 0) {
102
            this->type = typeName;
103
            return;
104
        }
105
    }
106

107
    // If the type was NOT in the list of allowedNames, but the caller has set the allowOthers flag to
108
    // true, then add the new type to the static NameSet (if it is not already there).
109
    if (allowOthers) {
110
        auto res = NameSet.insert(ByteArray(QByteArray::fromRawData(name, suffixPosition)));
111
        if (res.second /*The insert succeeded (the type was new)*/) {
112
            // Make sure that the data in the set is a unique (unshared) copy of the text
113
            res.first->ensureUnshared();
114
        }
115
        this->type = res.first->bytes.constData();
116
    }
117
    else {
118
        // The passed-in type is not in the allowed list, and allowOthers was not true, so don't
119
        // store the type
120
        this->type = "";
121
    }
122
}
123

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.