1
/***************************************************************************
2
* Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
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. *
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. *
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 *
21
***************************************************************************/
24
#include "PreCompiled.h"
33
#include "Interpreter.h"
40
// s1 and s2 must be numbers represented as string
41
bool operator()(const std::string& s1, const std::string& s2)
43
if (s1.size() < s2.size()) {
46
if (s1.size() > s2.size()) {
52
static std::string increment(const std::string& s)
56
for (std::string::reverse_iterator it = n.rbegin(); it != n.rend(); ++it) {
62
*it = ((d % 10) + 48);
79
unique_name(std::string name, const std::vector<std::string>& names, int padding)
80
: base_name {std::move(name)}
83
removeDigitsFromEnd();
84
findHighestSuffix(names);
87
std::string get() const
89
return appendSuffix();
93
void removeDigitsFromEnd()
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);
102
void findHighestSuffix(const std::vector<std::string>& names)
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());
117
std::string appendSuffix() const
119
std::stringstream str;
125
str << Base::string_comp::increment(num_suffix);
130
std::string num_suffix;
131
std::string base_name;
138
Base::Tools::getUniqueName(const std::string& name, const std::vector<std::string>& names, int pad)
144
Base::unique_name unique(name, names, pad);
148
std::string Base::Tools::addNumber(const std::string& name, unsigned int num, int d)
150
std::stringstream str;
160
std::string Base::Tools::getIdentifier(const std::string& name)
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) {
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
182
std::wstring Base::Tools::widen(const std::string& str)
184
std::wostringstream wstm;
185
const std::ctype<wchar_t>& ctfacet = std::use_facet<std::ctype<wchar_t>>(wstm.getloc());
187
wstm << ctfacet.widen(i);
192
std::string Base::Tools::narrow(const std::wstring& str)
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);
202
std::string Base::Tools::escapedUnicodeFromUtf8(const char* s)
204
Base::PyGILStateLocker lock;
205
std::string escapedstr;
207
PyObject* unicode = PyUnicode_FromString(s);
212
PyObject* escaped = PyUnicode_AsUnicodeEscapeString(unicode);
214
escapedstr = std::string(PyBytes_AsString(escaped));
222
std::string Base::Tools::escapedUnicodeToUtf8(const std::string& s)
224
Base::PyGILStateLocker lock;
228
PyUnicode_DecodeUnicodeEscape(s.c_str(), static_cast<Py_ssize_t>(s.size()), "strict");
232
if (PyUnicode_Check(unicode)) {
233
string = PyUnicode_AsUTF8(unicode);
239
std::string Base::Tools::escapeQuotesFromString(const std::string& s)
242
size_t len = s.size();
243
for (size_t i = 0; i < len; ++i) {
259
QString Base::Tools::escapeEncodeString(const QString& s)
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("\\\\");
268
else if (s.at(i) == QLatin1Char('\"')) {
269
result += QLatin1String("\\\"");
271
else if (s.at(i) == QLatin1Char('\'')) {
272
result += QLatin1String("\\\'");
282
std::string Base::Tools::escapeEncodeString(const std::string& s)
285
size_t len = s.size();
286
for (size_t i = 0; i < len; ++i) {
305
QString Base::Tools::escapeEncodeFilename(const QString& s)
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("\\\"");
314
else if (s.at(i) == QLatin1Char('\'')) {
315
result += QLatin1String("\\\'");
325
std::string Base::Tools::escapeEncodeFilename(const std::string& s)
328
size_t len = s.size();
329
for (size_t i = 0; i < len; ++i) {
345
std::string Base::Tools::quoted(const char* name)
347
std::stringstream str;
348
str << "\"" << name << "\"";
352
std::string Base::Tools::quoted(const std::string& name)
354
std::stringstream str;
355
str << "\"" << name << "\"";
359
std::string Base::Tools::joinList(const std::vector<std::string>& vec, const std::string& sep)
361
std::stringstream str;
362
for (const auto& it : vec) {
368
std::string Base::Tools::currentDateTimeString()
370
return QDateTime::currentDateTime()
371
.toTimeSpec(Qt::OffsetFromUTC)
372
.toString(Qt::ISODate)
376
std::vector<std::string> Base::Tools::splitSubName(const std::string& subname)
378
// Turns 'Part.Part001.Body.Pad.Edge1'
379
// Into ['Part', 'Part001', 'Body', 'Pad', 'Edge1']
380
std::vector<std::string> subNames;
382
std::istringstream subNameStream(subname);
383
while (std::getline(subNameStream, subName, '.')) {
384
subNames.push_back(subName);
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.