Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PROPOSAL: Refactor EID class into a pseudo-UUID #25666

Merged
merged 2 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/engraving/dom/engravingitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2801,7 +2801,7 @@ void EngravingItem::LayoutData::setWidthDebugHook(double w)
void EngravingItem::LayoutData::dump(std::stringstream& ss) const
{
ss << "\n";
ss << m_item->typeName() << " id: " << m_item->eid().id() << "\n";
ss << m_item->typeName() << " id: " << m_item->eid().toStdString() << "\n";

ss << "skip: " << (m_isSkipDraw ? "yes" : "no") << "\n";
ss << "mag: " << m_mag << "\n";
Expand Down
39 changes: 12 additions & 27 deletions src/engraving/dom/engravingobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,6 @@ EngravingObject::EngravingObject(const ElementType& type, EngravingObject* paren
m_score = static_cast<Score*>(this);
}

// gen EID
if (type != ElementType::SCORE) {
Score* s = score();
if (s) {
MasterScore* ms = s->masterScore();
if (ms) {
m_eid = ms->eidRegister()->newEID(m_type);
}
}
}

// reg to debug
if (type != ElementType::SCORE) {
if (m_score && m_score->elementsProvider()) {
Expand All @@ -103,17 +92,6 @@ EngravingObject::EngravingObject(const EngravingObject& se)
}
m_links = 0;

// gen EID
if (m_type != ElementType::SCORE) {
Score* s = score();
if (s) {
MasterScore* ms = s->masterScore();
if (ms) {
m_eid = ms->eidRegister()->newEID(m_type);
}
}
}

// reg to debug
if (m_type != ElementType::SCORE) {
if (m_score && m_score->elementsProvider()) {
Expand Down Expand Up @@ -727,12 +705,19 @@ String EngravingObject::translatedTypeUserName() const
return typeUserName().translated();
}

void EngravingObject::setEID(EID id)
EID EngravingObject::eid() const
{
m_eid = id;
if (registerId()) {
masterScore()->eidRegister()->registerItemEID(id, this);
}
return masterScore()->eidRegister()->EIDFromItem(this);
}

void EngravingObject::setEID(EID id) const
{
masterScore()->eidRegister()->registerItemEID(id, this);
}

EID EngravingObject::assignNewEID() const
{
return masterScore()->eidRegister()->newEIDForItem(this);
}

//---------------------------------------------------------
Expand Down
8 changes: 4 additions & 4 deletions src/engraving/dom/engravingobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,9 @@ class EngravingObject
virtual TranslatableString typeUserName() const;
virtual String translatedTypeUserName() const;

inline EID eid() const { return m_eid; }
void setEID(EID id);
virtual bool registerId() const { return false; }
EID eid() const;
void setEID(EID id) const;
EID assignNewEID() const;

EngravingObject* parent() const;
void setParent(EngravingObject* p);
Expand Down Expand Up @@ -300,7 +300,7 @@ class EngravingObject
void doSetScore(Score* sc);

ElementType m_type = ElementType::INVALID;
mutable EID m_eid;

EngravingObject* m_parent = nullptr;
bool m_isParentExplicitlySet = false;
EngravingObjectList m_children;
Expand Down
2 changes: 0 additions & 2 deletions src/engraving/dom/measurebase.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,6 @@ class MeasureBase : public EngravingItem
bool isStartOfSystemLock() const;
bool isEndOfSystemLock() const;

bool registerId() const override { return true; }

protected:

MeasureBase(const ElementType& type, System* system = 0);
Expand Down
4 changes: 0 additions & 4 deletions src/engraving/dom/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,6 @@ Score::Score(MasterScore* parent, bool forcePartStyle /* = true */)
Score::validScores.insert(this);
m_masterScore = parent;

if (m_masterScore) {
setEID(m_masterScore->eidRegister()->newEID(type()));
}

if (DefaultStyle::defaultStyleForParts()) {
m_style = *DefaultStyle::defaultStyleForParts();
} else {
Expand Down
150 changes: 123 additions & 27 deletions src/engraving/infrastructure/eid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,55 +19,151 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <string>
#include <random>

#include <logger.h>

#include "eid.h"

using namespace mu::engraving;

EID::EID(ElementType type, uint32_t id)
: m_type(type), m_id(id)
static constexpr char SEPARATOR = '_';

static std::string int64ToBase64Str(uint64_t n)
{
}
static constexpr char CHARS[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
mike-spa marked this conversation as resolved.
Show resolved Hide resolved

struct _Data {
uint16_t type = 0;
uint16_t reserved = 0;
uint32_t id = 0;
};
std::stringstream ss;
do {
ss << CHARS[n & 63];
n = n >> 6;
} while (n != 0);

union _Pack
{
uint64_t val;
_Data data;
};
return ss.str();
}

uint64_t EID::toUint64() const
static constexpr uint64_t charToInt(char c)
{
_Pack pack = { 0 };
pack.data.type = static_cast<uint16_t>(m_type);
pack.data.id = m_id;
return pack.val;
switch (c) {
case 'A': return 0;
case 'B': return 1;
case 'C': return 2;
case 'D': return 3;
case 'E': return 4;
case 'F': return 5;
case 'G': return 6;
case 'H': return 7;
case 'I': return 8;
case 'J': return 9;
case 'K': return 10;
case 'L': return 11;
case 'M': return 12;
case 'N': return 13;
case 'O': return 14;
case 'P': return 15;
case 'Q': return 16;
case 'R': return 17;
case 'S': return 18;
case 'T': return 19;
case 'U': return 20;
case 'V': return 21;
case 'W': return 22;
case 'X': return 23;
case 'Y': return 24;
case 'Z': return 25;
case 'a': return 26;
case 'b': return 27;
case 'c': return 28;
case 'd': return 29;
case 'e': return 30;
case 'f': return 31;
case 'g': return 32;
case 'h': return 33;
case 'i': return 34;
case 'j': return 35;
case 'k': return 36;
case 'l': return 37;
case 'm': return 38;
case 'n': return 39;
case 'o': return 40;
case 'p': return 41;
case 'q': return 42;
case 'r': return 43;
case 's': return 44;
case 't': return 45;
case 'u': return 46;
case 'v': return 47;
case 'w': return 48;
case 'x': return 49;
case 'y': return 50;
case 'z': return 51;
case '0': return 52;
case '1': return 53;
case '2': return 54;
case '3': return 55;
case '4': return 56;
case '5': return 57;
case '6': return 58;
case '7': return 59;
case '8': return 60;
case '9': return 61;
case '+': return 62;
case '/': return 63;
default:
UNREACHABLE;
}
}

EID EID::fromUint64(uint64_t v)
static uint64_t base64StrToInt64(const std::string& s)
{
_Pack pack = { 0 };
pack.val = v;
return EID(static_cast<ElementType>(pack.data.type), pack.data.id);
uint64_t result = 0;

for (auto iter = s.rbegin(); iter != s.rend(); ++iter) {
result = result << 6;
result |= charToInt(*iter);
}

return result;
}

std::string EID::toStdString() const
{
return std::to_string(toUint64());
std::stringstream ss;
ss << int64ToBase64Str(m_first) << SEPARATOR << int64ToBase64Str(m_second);
return ss.str();
}

EID EID::fromStdString(const std::string& s)
{
uint64_t v = std::stoull(s);
return fromUint64(v);
std::stringstream ss(s);
std::string str;
std::vector<std::string> strings;

while (std::getline(ss, str, SEPARATOR)) {
strings.push_back(str);
}

if (strings.size() != 2) {
return EID::invalid();
}

const std::string& first = strings[0];
const std::string& second = strings[1];

return EID(base64StrToInt64(first), base64StrToInt64(second));
}

EID EID::fromStdString(const std::string_view& s)
{
uint64_t v = std::stoull(s.data(), nullptr, 10);
return fromUint64(v);
return fromStdString(std::string(s));
}

EID EID::newUnique()
{
static std::random_device s_device;
static std::mt19937_64 s_engine(s_device());
static std::uniform_int_distribution<uint64_t> s_unifDist;

return EID(s_unifDist(s_engine), s_unifDist(s_engine));
}
39 changes: 25 additions & 14 deletions src/engraving/infrastructure/eid.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#ifndef MU_ENGRAVING_EID_H
#define MU_ENGRAVING_EID_H

#include <bitset>
#include <cstdint>
#include <string>
#include <string_view>
Expand All @@ -34,33 +35,43 @@ namespace mu::engraving {
class EID
{
public:
EID(ElementType type = ElementType::INVALID, uint32_t id = 0);
bool isValid() const { return m_first != INVALID || m_second != INVALID; }

bool isValid() const { return m_type != ElementType::INVALID && m_id != 0; }

ElementType type() const { return m_type; }
uint32_t id() const { return m_id; }

inline bool operator ==(const EID& other) const { return m_type == other.m_type && m_id == other.m_id; }
inline bool operator !=(const EID& other) const { return !this->operator ==(other); }

uint64_t toUint64() const;
static EID fromUint64(uint64_t v);
inline bool operator ==(const EID& other) const { return m_first == other.m_first && m_second == other.m_second; }
inline bool operator !=(const EID& other) const { return m_first != other.m_first || m_second != other.m_second; }

std::string toStdString() const;
static EID fromStdString(const std::string& v);
static EID fromStdString(const std::string_view& v);
static EID newUnique();
static EID invalid() { return EID(INVALID, INVALID); }

private:
EID() = delete;
EID(uint64_t f, uint64_t s)
: m_first(f), m_second(s) {}

static constexpr uint64_t INVALID = uint64_t(-1);

ElementType m_type = ElementType::INVALID;
uint32_t m_id = 0;
uint64_t m_first = INVALID;
uint64_t m_second = INVALID;

friend struct std::hash<EID>;
};
}

template<>
struct std::hash<mu::engraving::EID>
{
size_t operator()(const mu::engraving::EID& eid) const
{
return std::hash<uint64_t>()(eid.m_first) ^ (std::hash<uint64_t>()(eid.m_second) << 1);
}
};

inline muse::logger::Stream& operator<<(muse::logger::Stream& s, const mu::engraving::EID& v)
{
s << "[" << static_cast<int>(v.type()) << "] " << v.id();
s << v.toStdString();
return s;
}

Expand Down
Loading