og-odamex/common/olumpname.cpp

267 lines
5.1 KiB
C++

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright (C) 2006-2026 by The Odamex Team.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// DESCRIPTION:
// Wrapper class around a char[8] to make dealing with lump names quicker
// and easier. Under most cases, the lump name will guaranteed to be completely
// uppercase.
//
//-----------------------------------------------------------------------------
#include "odamex.h"
#include "olumpname.h"
#include <stdexcept>
// private functions
void OLumpName::MakeDataPresentable()
{
// make m_data uppercase
for (int i = 0; i < 8; ++i)
m_data[i] = static_cast<char>(toupper(m_data[i]));
// ensure last char is a null terminator
m_data[8] = '\0';
}
// constructors/assignment operators
OLumpName::OLumpName()
{
memset(m_data, '\0', 9);
}
OLumpName::OLumpName(const OLumpName& other)
{
memcpy(m_data, other.m_data, 8);
MakeDataPresentable();
}
OLumpName::OLumpName(const char* other)
{
if (other)
{
strncpy(m_data, other, 8);
MakeDataPresentable();
}
}
OLumpName::OLumpName(const std::string& other)
{
if (!other.empty())
{
strncpy(m_data, other.data(), 8);
MakeDataPresentable();
}
}
OLumpName& OLumpName::operator=(const OLumpName& other)
{
if (this != &other)
{
memcpy(m_data, other.m_data, 8);
MakeDataPresentable();
}
return *this;
}
OLumpName& OLumpName::operator=(const char* other)
{
strncpy(m_data, other, 8);
MakeDataPresentable();
return *this;
}
OLumpName& OLumpName::operator=(const std::string& other)
{
strncpy(m_data, other.data(), 8);
MakeDataPresentable();
return *this;
}
OLumpName& OLumpName::operator=(std::string_view other)
{
strncpy(m_data, other.data(), 8);
MakeDataPresentable();
return *this;
}
// capacity
size_t OLumpName::size() const
{
size_t i = 0;
for (; i < 8; ++i)
{
if (m_data[i] == '\0')
{
break;
}
}
return i;
}
size_t OLumpName::length() const
{
return size();
}
void OLumpName::clear()
{
m_data[0] = '\0';
}
bool OLumpName::empty() const
{
return m_data[0] == '\0';
}
// element access
//
// WARNING: If you use any of the non-const element access functions, the uppercase
// guarantee will no longer apply! You can edit the char's to be whatever you
// want at that point. Be careful!
char& OLumpName::at(const size_t pos)
{
const size_t s = size();
if (pos > 7 || pos > s)
{
throw std::out_of_range(fmt::format("Attempted to access OLumpName at position {} when the size was {}", pos, s));
}
return m_data[pos];
}
const char& OLumpName::at(const size_t pos) const
{
const size_t s = size();
if (pos > 7 || pos > s)
{
throw std::out_of_range(fmt::format("Attempted to access OLumpName at position {} when the size was {}", pos, s));
}
return m_data[pos];
}
char& OLumpName::operator[](const size_t pos)
{
return m_data[pos];
}
const char& OLumpName::operator[](const size_t pos) const
{
return m_data[pos];
}
OLumpName OLumpName::substr(const size_t pos, size_t npos) const
{
const size_t s = size();
if (pos > 7 || pos > s)
{
throw std::out_of_range(fmt::format("Attempted to access OLumpName at position {} when the size was {}", pos, s));
}
if (npos > s)
{
npos = s;
}
OLumpName out;
strncpy(out.m_data, m_data + pos, npos);
return out;
}
// string operations
const char* OLumpName::c_str() const
{
return m_data;
}
const char* OLumpName::data() const
{
return m_data;
}
int OLumpName::compare(const OLumpName& other) const
{
return !stricmp(m_data, other.m_data);
}
int OLumpName::compare(const char* other) const
{
return !stricmp(m_data, other);
}
int OLumpName::compare(const std::string& other) const
{
return !stricmp(m_data, other.data());
}
int OLumpName::compare(std::string_view other) const
{
return other.length() < 9 && !strnicmp(m_data, other.data(), 8);
}
bool operator==(const OLumpName& lhs, const OLumpName& rhs)
{
return !stricmp(lhs.m_data, rhs.m_data);
}
bool operator==(const OLumpName& lhs, const char* rhs)
{
return !stricmp(lhs.m_data, rhs);
}
bool operator==(const OLumpName& lhs, const std::string& rhs)
{
return !stricmp(lhs.m_data, rhs.data());
}
bool operator==(const OLumpName& lhs, std::string_view rhs)
{
return rhs.length() < 9 && !strnicmp(lhs.m_data, rhs.data(), 8);
}
bool operator!=(const OLumpName& lhs, const OLumpName& rhs)
{
return stricmp(lhs.m_data, rhs.m_data);
}
bool operator!=(const OLumpName& lhs, const char* rhs)
{
return stricmp(lhs.m_data, rhs);
}
bool operator!=(const OLumpName& lhs, const std::string& rhs)
{
return stricmp(lhs.m_data, rhs.data());
}
bool operator!=(const OLumpName& lhs, std::string_view rhs)
{
return rhs.length() < 9 && strnicmp(lhs.m_data, rhs.data(), 8);
}