Skip to content

Commit

Permalink
Merge pull request #25666 from mike-spa/reworkEID
Browse files Browse the repository at this point in the history
PROPOSAL: Refactor EID class into a pseudo-UUID
  • Loading branch information
mike-spa authored Dec 4, 2024
2 parents 3568fe1 + e78aacd commit 6b9b3b0
Show file tree
Hide file tree
Showing 94 changed files with 911 additions and 941 deletions.
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+/";

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

0 comments on commit 6b9b3b0

Please sign in to comment.