FreeCAD

Форк
0
/
Tools.cpp 
395 строк · 10.7 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23

24
#include "PreCompiled.h"
25
#ifndef _PreComp_
26
#include <sstream>
27
#include <locale>
28
#include <iostream>
29
#include <QDateTime>
30
#endif
31

32
#include "PyExport.h"
33
#include "Interpreter.h"
34
#include "Tools.h"
35

36
namespace Base
37
{
38
struct string_comp
39
{
40
    // s1 and s2 must be numbers represented as string
41
    bool operator()(const std::string& s1, const std::string& s2)
42
    {
43
        if (s1.size() < s2.size()) {
44
            return true;
45
        }
46
        if (s1.size() > s2.size()) {
47
            return false;
48
        }
49

50
        return s1 < s2;
51
    }
52
    static std::string increment(const std::string& s)
53
    {
54
        std::string n = s;
55
        int addcarry = 1;
56
        for (std::string::reverse_iterator it = n.rbegin(); it != n.rend(); ++it) {
57
            if (addcarry == 0) {
58
                break;
59
            }
60
            int d = *it - 48;
61
            d = d + addcarry;
62
            *it = ((d % 10) + 48);
63
            addcarry = d / 10;
64
        }
65
        if (addcarry > 0) {
66
            std::string b;
67
            b.resize(1);
68
            b[0] = addcarry + 48;
69
            n = b + n;
70
        }
71

72
        return n;
73
    }
74
};
75

76
class unique_name
77
{
78
public:
79
    unique_name(std::string name, const std::vector<std::string>& names, int padding)
80
        : base_name {std::move(name)}
81
        , padding {padding}
82
    {
83
        removeDigitsFromEnd();
84
        findHighestSuffix(names);
85
    }
86

87
    std::string get() const
88
    {
89
        return appendSuffix();
90
    }
91

92
private:
93
    void removeDigitsFromEnd()
94
    {
95
        std::string::size_type pos = base_name.find_last_not_of("0123456789");
96
        if (pos != std::string::npos && (pos + 1) < base_name.size()) {
97
            num_suffix = base_name.substr(pos + 1);
98
            base_name.erase(pos + 1);
99
        }
100
    }
101

102
    void findHighestSuffix(const std::vector<std::string>& names)
103
    {
104
        for (const auto& name : names) {
105
            if (name.substr(0, base_name.length()) == base_name) {  // same prefix
106
                std::string suffix(name.substr(base_name.length()));
107
                if (!suffix.empty()) {
108
                    std::string::size_type pos = suffix.find_first_not_of("0123456789");
109
                    if (pos == std::string::npos) {
110
                        num_suffix = std::max<std::string>(num_suffix, suffix, Base::string_comp());
111
                    }
112
                }
113
            }
114
        }
115
    }
116

117
    std::string appendSuffix() const
118
    {
119
        std::stringstream str;
120
        str << base_name;
121
        if (padding > 0) {
122
            str.fill('0');
123
            str.width(padding);
124
        }
125
        str << Base::string_comp::increment(num_suffix);
126
        return str.str();
127
    }
128

129
private:
130
    std::string num_suffix;
131
    std::string base_name;
132
    int padding;
133
};
134

135
}  // namespace Base
136

137
std::string
138
Base::Tools::getUniqueName(const std::string& name, const std::vector<std::string>& names, int pad)
139
{
140
    if (names.empty()) {
141
        return name;
142
    }
143

144
    Base::unique_name unique(name, names, pad);
145
    return unique.get();
146
}
147

148
std::string Base::Tools::addNumber(const std::string& name, unsigned int num, int d)
149
{
150
    std::stringstream str;
151
    str << name;
152
    if (d > 0) {
153
        str.fill('0');
154
        str.width(d);
155
    }
156
    str << num;
157
    return str.str();
158
}
159

160
std::string Base::Tools::getIdentifier(const std::string& name)
161
{
162
    if (name.empty()) {
163
        return "_";
164
    }
165
    // check for first character whether it's a digit
166
    std::string CleanName = name;
167
    if (!CleanName.empty() && CleanName[0] >= 48 && CleanName[0] <= 57) {
168
        CleanName[0] = '_';
169
    }
170
    // strip illegal chars
171
    for (char& it : CleanName) {
172
        if (!((it >= 48 && it <= 57) ||    // number
173
              (it >= 65 && it <= 90) ||    // uppercase letter
174
              (it >= 97 && it <= 122))) {  // lowercase letter
175
            it = '_';                      // it's neither number nor letter
176
        }
177
    }
178

179
    return CleanName;
180
}
181

182
std::wstring Base::Tools::widen(const std::string& str)
183
{
184
    std::wostringstream wstm;
185
    const std::ctype<wchar_t>& ctfacet = std::use_facet<std::ctype<wchar_t>>(wstm.getloc());
186
    for (char i : str) {
187
        wstm << ctfacet.widen(i);
188
    }
189
    return wstm.str();
190
}
191

192
std::string Base::Tools::narrow(const std::wstring& str)
193
{
194
    std::ostringstream stm;
195
    const std::ctype<char>& ctfacet = std::use_facet<std::ctype<char>>(stm.getloc());
196
    for (wchar_t i : str) {
197
        stm << ctfacet.narrow(i, 0);
198
    }
199
    return stm.str();
200
}
201

202
std::string Base::Tools::escapedUnicodeFromUtf8(const char* s)
203
{
204
    Base::PyGILStateLocker lock;
205
    std::string escapedstr;
206

207
    PyObject* unicode = PyUnicode_FromString(s);
208
    if (!unicode) {
209
        return escapedstr;
210
    }
211

212
    PyObject* escaped = PyUnicode_AsUnicodeEscapeString(unicode);
213
    if (escaped) {
214
        escapedstr = std::string(PyBytes_AsString(escaped));
215
        Py_DECREF(escaped);
216
    }
217

218
    Py_DECREF(unicode);
219
    return escapedstr;
220
}
221

222
std::string Base::Tools::escapedUnicodeToUtf8(const std::string& s)
223
{
224
    Base::PyGILStateLocker lock;
225
    std::string string;
226

227
    PyObject* unicode =
228
        PyUnicode_DecodeUnicodeEscape(s.c_str(), static_cast<Py_ssize_t>(s.size()), "strict");
229
    if (!unicode) {
230
        return string;
231
    }
232
    if (PyUnicode_Check(unicode)) {
233
        string = PyUnicode_AsUTF8(unicode);
234
    }
235
    Py_DECREF(unicode);
236
    return string;
237
}
238

239
std::string Base::Tools::escapeQuotesFromString(const std::string& s)
240
{
241
    std::string result;
242
    size_t len = s.size();
243
    for (size_t i = 0; i < len; ++i) {
244
        switch (s.at(i)) {
245
            case '\"':
246
                result += "\\\"";
247
                break;
248
            case '\'':
249
                result += "\\\'";
250
                break;
251
            default:
252
                result += s.at(i);
253
                break;
254
        }
255
    }
256
    return result;
257
}
258

259
QString Base::Tools::escapeEncodeString(const QString& s)
260
{
261
    QString result;
262
    const int len = s.length();
263
    result.reserve(int(len * 1.1));
264
    for (int i = 0; i < len; ++i) {
265
        if (s.at(i) == QLatin1Char('\\')) {
266
            result += QLatin1String("\\\\");
267
        }
268
        else if (s.at(i) == QLatin1Char('\"')) {
269
            result += QLatin1String("\\\"");
270
        }
271
        else if (s.at(i) == QLatin1Char('\'')) {
272
            result += QLatin1String("\\\'");
273
        }
274
        else {
275
            result += s.at(i);
276
        }
277
    }
278
    result.squeeze();
279
    return result;
280
}
281

282
std::string Base::Tools::escapeEncodeString(const std::string& s)
283
{
284
    std::string result;
285
    size_t len = s.size();
286
    for (size_t i = 0; i < len; ++i) {
287
        switch (s.at(i)) {
288
            case '\\':
289
                result += "\\\\";
290
                break;
291
            case '\"':
292
                result += "\\\"";
293
                break;
294
            case '\'':
295
                result += "\\\'";
296
                break;
297
            default:
298
                result += s.at(i);
299
                break;
300
        }
301
    }
302
    return result;
303
}
304

305
QString Base::Tools::escapeEncodeFilename(const QString& s)
306
{
307
    QString result;
308
    const int len = s.length();
309
    result.reserve(int(len * 1.1));
310
    for (int i = 0; i < len; ++i) {
311
        if (s.at(i) == QLatin1Char('\"')) {
312
            result += QLatin1String("\\\"");
313
        }
314
        else if (s.at(i) == QLatin1Char('\'')) {
315
            result += QLatin1String("\\\'");
316
        }
317
        else {
318
            result += s.at(i);
319
        }
320
    }
321
    result.squeeze();
322
    return result;
323
}
324

325
std::string Base::Tools::escapeEncodeFilename(const std::string& s)
326
{
327
    std::string result;
328
    size_t len = s.size();
329
    for (size_t i = 0; i < len; ++i) {
330
        switch (s.at(i)) {
331
            case '\"':
332
                result += "\\\"";
333
                break;
334
            case '\'':
335
                result += "\\\'";
336
                break;
337
            default:
338
                result += s.at(i);
339
                break;
340
        }
341
    }
342
    return result;
343
}
344

345
std::string Base::Tools::quoted(const char* name)
346
{
347
    std::stringstream str;
348
    str << "\"" << name << "\"";
349
    return str.str();
350
}
351

352
std::string Base::Tools::quoted(const std::string& name)
353
{
354
    std::stringstream str;
355
    str << "\"" << name << "\"";
356
    return str.str();
357
}
358

359
std::string Base::Tools::joinList(const std::vector<std::string>& vec, const std::string& sep)
360
{
361
    std::stringstream str;
362
    for (const auto& it : vec) {
363
        str << it << sep;
364
    }
365
    return str.str();
366
}
367

368
std::string Base::Tools::currentDateTimeString()
369
{
370
    return QDateTime::currentDateTime()
371
        .toTimeSpec(Qt::OffsetFromUTC)
372
        .toString(Qt::ISODate)
373
        .toStdString();
374
}
375

376
std::vector<std::string> Base::Tools::splitSubName(const std::string& subname)
377
{
378
    // Turns 'Part.Part001.Body.Pad.Edge1'
379
    // Into ['Part', 'Part001', 'Body', 'Pad', 'Edge1']
380
    std::vector<std::string> subNames;
381
    std::string subName;
382
    std::istringstream subNameStream(subname);
383
    while (std::getline(subNameStream, subName, '.')) {
384
        subNames.push_back(subName);
385
    }
386

387
    // Check if the last character of the input string is the delimiter.
388
    // If so, add an empty string to the subNames vector.
389
    // Because the last subname is the element name and can be empty.
390
    if (!subname.empty() && subname.back() == '.') {
391
        subNames.push_back("");  // Append empty string for trailing dot.
392
    }
393

394
    return subNames;
395
}
396

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

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

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

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