Files
create/src/App/Enumeration.cpp
2022-08-24 07:20:57 +02:00

298 lines
7.0 KiB
C++

/***************************************************************************
* Copyright (c) 2015 Ian Rees <ian.rees@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cassert>
# include <cstring>
#endif
#include <Base/Exception.h>
#include "Enumeration.h"
#include <string_view>
using namespace App;
namespace {
struct StringCopy : public Enumeration::Object {
explicit StringCopy(const char* str) : d(str) {
}
const char* data() const override {
return d.data();
}
bool isEqual(const char* str) const override {
return d == str;
}
bool isCustom() const override {
return true;
}
private:
std::string d;
};
struct StringView : public Enumeration::Object {
explicit StringView(const char* str) : d(str) {
}
const char* data() const override {
return d.data();
}
bool isEqual(const char* str) const override {
return d == str;
}
bool isCustom() const override {
return false;
}
private:
std::string_view d;
};
}
Enumeration::Enumeration()
: _index(0)
{
}
Enumeration::Enumeration(const Enumeration &other)
{
enumArray = other.enumArray;
_index = other._index;
}
Enumeration::Enumeration(const char *valStr)
: _index(0)
{
enumArray.push_back(std::make_shared<StringCopy>(valStr));
setValue(valStr);
}
Enumeration::Enumeration(const char **list, const char *valStr)
: _index(0)
{
while (list && *list) {
enumArray.push_back(std::make_shared<StringView>(*list));
list++;
}
setValue(valStr);
}
Enumeration::~Enumeration()
{
enumArray.clear();
}
void Enumeration::setEnums(const char **plEnums)
{
std::string oldValue;
bool preserve = (isValid() && plEnums != nullptr);
if (preserve) {
const char* str = getCStr();
if (str)
oldValue = str;
}
enumArray.clear();
while (plEnums && *plEnums) {
enumArray.push_back(std::make_shared<StringView>(*plEnums));
plEnums++;
}
// set _index
if (_index < 0)
_index = 0;
if (preserve) {
setValue(oldValue);
}
}
void Enumeration::setEnums(const std::vector<std::string> &values)
{
if (values.empty()) {
setEnums(nullptr);
return;
}
std::string oldValue;
bool preserve = isValid();
if (preserve) {
const char* str = getCStr();
if (str)
oldValue = str;
}
enumArray.clear();
for (std::vector<std::string>::const_iterator it = values.begin(); it != values.end(); ++it) {
enumArray.push_back(std::make_shared<StringCopy>(it->c_str()));
}
// set _index
if (_index < 0)
_index = 0;
if (preserve) {
setValue(oldValue);
}
}
void Enumeration::setValue(const char *value)
{
_index = 0;
for (std::size_t i = 0; i < enumArray.size(); i++) {
if (enumArray[i]->isEqual(value)) {
_index = static_cast<int>(i);
break;
}
}
}
void Enumeration::setValue(long value, bool checkRange)
{
if (value >= 0 && value < countItems()) {
_index = value;
} else {
if (checkRange) {
throw Base::ValueError("Out of range");
} else {
_index = value;
}
}
}
bool Enumeration::isValue(const char *value) const
{
int i = getInt();
if (i == -1) {
return false;
} else {
return enumArray[i]->isEqual(value);
}
}
bool Enumeration::contains(const char *value) const
{
if (!isValid()) {
return false;
}
for (const auto& it : enumArray) {
if (it->isEqual(value))
return true;
}
return false;
}
const char * Enumeration::getCStr() const
{
if (!isValid() || _index < 0 || _index >= countItems()) {
return nullptr;
}
return enumArray[_index]->data();
}
int Enumeration::getInt() const
{
if (!isValid() || _index < 0 || _index >= countItems()) {
return -1;
}
return _index;
}
std::vector<std::string> Enumeration::getEnumVector() const
{
std::vector<std::string> list;
for (const auto& it : enumArray)
list.emplace_back(it->data());
return list;
}
bool Enumeration::hasEnums() const
{
return (!enumArray.empty());
}
bool Enumeration::isValid() const
{
return (!enumArray.empty() && _index >= 0 && _index < countItems());
}
int Enumeration::maxValue() const
{
int num = -1;
if (!enumArray.empty())
num = static_cast<int>(enumArray.size()) - 1;
return num;
}
bool Enumeration::isCustom() const
{
for (const auto& it : enumArray) {
if (it->isCustom())
return true;
}
return false;
}
Enumeration & Enumeration::operator=(const Enumeration &other)
{
if (this == &other)
return *this;
enumArray = other.enumArray;
_index = other._index;
return *this;
}
bool Enumeration::operator==(const Enumeration &other) const
{
if (_index != other._index || enumArray.size() != other.enumArray.size()) {
return false;
}
for (size_t i = 0; i < enumArray.size(); ++i) {
if (enumArray[i]->data() == other.enumArray[i]->data())
continue;
if (!enumArray[i]->data() || !other.enumArray[i]->data())
return false;
if (!enumArray[i]->isEqual(other.enumArray[i]->data()))
return false;
}
return true;
}
bool Enumeration::operator==(const char *other) const
{
if (!getCStr()) {
return false;
}
return (strcmp(getCStr(), other) == 0);
}
int Enumeration::countItems() const
{
return static_cast<int>(enumArray.size());
}