LCOV - code coverage report
Current view: top level - src/engraving/infrastructure - eid.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 91.7 % 121 111
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : #include "eid.h"
      23              : 
      24              : #include <string>
      25              : #include <random>
      26              : 
      27              : #include "global/log.h"
      28              : 
      29              : using namespace mu::engraving;
      30              : 
      31              : static constexpr char SEPARATOR = '_';
      32              : 
      33       213150 : static char* toBase64Chars(char* const first, char* const last, uint64_t n)
      34              : {
      35              :     static constexpr char CHARS[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      36              : 
      37       213150 :     IF_ASSERT_FAILED(static_cast<size_t>(last - first) >= EID::MAX_UINT64_BASE64_SIZE) {
      38            0 :         return first;
      39              :     }
      40              : 
      41       213150 :     char* it = first;
      42              :     do {
      43       409484 :         *it++ = CHARS[n % 64];
      44       409484 :         n = n / 64;
      45       409484 :     } while (n != 0);
      46              : 
      47       213150 :     return it;
      48              : }
      49              : 
      50       443885 : static constexpr uint64_t charToInt(char c)
      51              : {
      52       443885 :     switch (c) {
      53         5887 :     case 'A': return 0;
      54        20154 :     case 'B': return 1;
      55        14160 :     case 'C': return 2;
      56        13926 :     case 'D': return 3;
      57        10972 :     case 'E': return 4;
      58         8110 :     case 'F': return 5;
      59         8214 :     case 'G': return 6;
      60         8564 :     case 'H': return 7;
      61         8576 :     case 'I': return 8;
      62         8283 :     case 'J': return 9;
      63         7984 :     case 'K': return 10;
      64         8132 :     case 'L': return 11;
      65         8158 :     case 'M': return 12;
      66         8076 :     case 'N': return 13;
      67         8331 :     case 'O': return 14;
      68         8671 :     case 'P': return 15;
      69         6673 :     case 'Q': return 16;
      70         6139 :     case 'R': return 17;
      71         5668 :     case 'S': return 18;
      72         6022 :     case 'T': return 19;
      73         6361 :     case 'U': return 20;
      74         6377 :     case 'V': return 21;
      75         5914 :     case 'W': return 22;
      76         6047 :     case 'X': return 23;
      77         6131 :     case 'Y': return 24;
      78         5906 :     case 'Z': return 25;
      79         5732 :     case 'a': return 26;
      80         5886 :     case 'b': return 27;
      81         5807 :     case 'c': return 28;
      82         6249 :     case 'd': return 29;
      83         5967 :     case 'e': return 30;
      84         5863 :     case 'f': return 31;
      85         6148 :     case 'g': return 32;
      86         5826 :     case 'h': return 33;
      87         6021 :     case 'i': return 34;
      88         5914 :     case 'j': return 35;
      89         5971 :     case 'k': return 36;
      90         5887 :     case 'l': return 37;
      91         5731 :     case 'm': return 38;
      92         6178 :     case 'n': return 39;
      93         6365 :     case 'o': return 40;
      94         5954 :     case 'p': return 41;
      95         5866 :     case 'q': return 42;
      96         5937 :     case 'r': return 43;
      97         5885 :     case 's': return 44;
      98         5831 :     case 't': return 45;
      99         5830 :     case 'u': return 46;
     100         5689 :     case 'v': return 47;
     101         6029 :     case 'w': return 48;
     102         5914 :     case 'x': return 49;
     103         5879 :     case 'y': return 50;
     104         6081 :     case 'z': return 51;
     105         6093 :     case '0': return 52;
     106         5952 :     case '1': return 53;
     107         5832 :     case '2': return 54;
     108         6149 :     case '3': return 55;
     109         6180 :     case '4': return 56;
     110         5969 :     case '5': return 57;
     111         6047 :     case '6': return 58;
     112         5623 :     case '7': return 59;
     113         6268 :     case '8': return 60;
     114         5698 :     case '9': return 61;
     115         6012 :     case '+': return 62;
     116         6186 :     case '/': return 63;
     117            0 :     default:
     118            0 :         UNREACHABLE;
     119              :         return uint64_t(-1);
     120              :     }
     121              : }
     122              : 
     123        75730 : static uint64_t base64StrToInt64(const std::string& s)
     124              : {
     125        75730 :     uint64_t result = 0;
     126              : 
     127       519615 :     for (auto iter = s.rbegin(); iter != s.rend(); ++iter) {
     128       443885 :         result = result << 6;
     129       443885 :         result |= charToInt(*iter);
     130              :     }
     131              : 
     132        75730 :     return result;
     133              : }
     134              : 
     135       106575 : char* EID::toChars(char* const first, char* const last) const
     136              : {
     137       106575 :     IF_ASSERT_FAILED(static_cast<size_t>(last - first) >= MAX_STR_SIZE) {
     138            0 :         return first;
     139              :     }
     140              : 
     141       106575 :     char* it = toBase64Chars(first, last, m_first);
     142       106575 :     *it++ = SEPARATOR;
     143       106575 :     it = toBase64Chars(it, last, m_second);
     144              : 
     145       106575 :     return it;
     146              : }
     147              : 
     148        12537 : std::string EID::toStdString() const
     149              : {
     150        12537 :     std::string base64Repr(MAX_STR_SIZE, char {});
     151        12537 :     const char* last = toChars(base64Repr.data(), base64Repr.data() + base64Repr.size());
     152        12537 :     base64Repr.resize(last - base64Repr.data());
     153              : 
     154        12537 :     return base64Repr;
     155            0 : }
     156              : 
     157        39455 : EID EID::fromStdString(const std::string& s)
     158              : {
     159        39455 :     std::stringstream ss(s);
     160        39455 :     std::string str;
     161        39455 :     std::vector<std::string> strings;
     162              : 
     163       116775 :     while (std::getline(ss, str, SEPARATOR)) {
     164        77320 :         strings.push_back(str);
     165              :     }
     166              : 
     167        39455 :     if (strings.size() != 2) {
     168         1590 :         return EID::invalid();
     169              :     }
     170              : 
     171        37865 :     const std::string& first = strings[0];
     172        37865 :     const std::string& second = strings[1];
     173              : 
     174        37865 :     return EID(base64StrToInt64(first), base64StrToInt64(second));
     175        39455 : }
     176              : 
     177        39454 : EID EID::fromStdString(const std::string_view& s)
     178              : {
     179        78908 :     return fromStdString(std::string(s));
     180              : }
     181              : 
     182            0 : EID EID::newUnique()
     183              : {
     184            0 :     static std::random_device s_device;
     185            0 :     thread_local static std::mt19937_64 s_engine(s_device());
     186            0 :     thread_local static std::uniform_int_distribution<uint64_t> s_unifDist;
     187              : 
     188            0 :     return EID(s_unifDist(s_engine), s_unifDist(s_engine));
     189              : }
     190              : 
     191              : // FOR UNIT TESTING
     192              : // EIDs are creates sequentially instead of randomly for test repeatability
     193              : 
     194        70256 : EID EID::newUniqueTestMode(uint64_t& maxVal)
     195              : {
     196        70256 :     ++maxVal;
     197        70256 :     return EID(maxVal, maxVal);
     198              : }
     199              : 
     200       102289 : void EID::updateMaxValTestMode(const EID& curEID, uint64_t& maxVal)
     201              : {
     202       102289 :     maxVal = std::max(maxVal, curEID.m_first);
     203       102289 :     maxVal = std::max(maxVal, curEID.m_second);
     204       102289 : }
        

Generated by: LCOV version 2.0-1