LCOV - code coverage report
Current view: top level - muse/framework/global/serialization - textstream.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 67.9 % 78 53
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-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 "textstream.h"
      23              : 
      24              : #include <array>
      25              : #include <charconv>
      26              : 
      27              : #include "global/io/iodevice.h"
      28              : #include "global/types/bytearray.h"
      29              : #include "global/types/string.h"
      30              : 
      31              : #include "global/log.h"
      32              : 
      33              : using namespace muse;
      34              : 
      35              : static constexpr int TEXTSTREAM_BUFFERSIZE = 16384;
      36              : 
      37            6 : TextStream::TextStream(io::IODevice* device)
      38            6 :     : m_device(device)
      39              : {
      40            6 :     m_buf.reserve(TEXTSTREAM_BUFFERSIZE);
      41            6 : }
      42              : 
      43         2247 : TextStream::~TextStream()
      44              : {
      45         2247 :     flush();
      46         2247 : }
      47              : 
      48         2241 : void TextStream::setDevice(io::IODevice* device)
      49              : {
      50         2241 :     m_device = device;
      51         2241 : }
      52              : 
      53         7328 : void TextStream::flush()
      54              : {
      55         7328 :     if (m_device && m_device->isOpen()) {
      56         6108 :         m_device->write(m_buf.data(), m_buf.size());
      57         6108 :         m_buf.clear();
      58              :     }
      59         7328 : }
      60              : 
      61      9842536 : TextStream& TextStream::operator<<(char ch)
      62              : {
      63      9842536 :     write(&ch, 1);
      64      9842536 :     return *this;
      65              : }
      66              : 
      67       154669 : TextStream& TextStream::operator<<(const int32_t val)
      68              : {
      69              :     // ceil(log_10(2^31)) = 10 (+ sign)
      70       154669 :     std::array<char, 11> buf{};
      71       464007 :     const auto [last, ec] = std::to_chars(buf.data(), buf.data() + buf.size(), val);
      72       154669 :     IF_ASSERT_FAILED(ec == std::errc {}) {
      73            0 :         return *this;
      74              :     }
      75              : 
      76       464007 :     write(buf.data(), static_cast<size_t>(last - buf.data()));
      77              : 
      78       154669 :     return *this;
      79              : }
      80              : 
      81            0 : TextStream& TextStream::operator<<(const uint32_t val)
      82              : {
      83              :     // ceil(log_10(2^32)) = 10
      84            0 :     std::array<char, 10> buf{};
      85            0 :     const auto [last, ec] = std::to_chars(buf.data(), buf.data() + buf.size(), val);
      86            0 :     IF_ASSERT_FAILED(ec == std::errc {}) {
      87            0 :         return *this;
      88              :     }
      89              : 
      90            0 :     write(buf.data(), static_cast<size_t>(last - buf.data()));
      91            0 :     return *this;
      92              : }
      93              : 
      94        13085 : TextStream& TextStream::operator<<(double val)
      95              : {
      96              :     // macOS: requires macOS 13.3 at runtime
      97              :     // linux: requires at least libstdc++ 11 (we compile with libstdc++ 10) or libc++ 14
      98              : #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 130300) \
      99              :     || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 160300) \
     100              :     || defined(_MSC_VER) \
     101              :     || (!defined(__APPLE__) && defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 14000) \
     102              :     || (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 11)
     103        13085 :     std::array<char, 24> buf{};
     104              : 
     105              :     // emulate std::stringstream default behavior
     106        13085 :     constexpr auto format = std::chars_format::general;
     107        13085 :     constexpr int precision = 6;
     108        39255 :     const auto [last, ec] = std::to_chars(buf.data(), buf.data() + buf.size(), val, format, precision);
     109        13085 :     IF_ASSERT_FAILED(ec == std::errc {}) {
     110            0 :         return *this;
     111              :     }
     112        39255 :     write(buf.data(), static_cast<size_t>(last - buf.data()));
     113              : #else
     114              :     std::stringstream ss;
     115              :     ss << val;
     116              :     std::string buf = ss.str();
     117              :     write(buf.data(), buf.size());
     118              : #endif
     119              : 
     120        13085 :     return *this;
     121              : }
     122              : 
     123            0 : TextStream& TextStream::operator<<(const int64_t val)
     124              : {
     125              :     // ceil(log_10(2^63)) = 20 (+ sign)
     126            0 :     std::array<char, 21> buf{};
     127            0 :     const auto [last, ec] = std::to_chars(buf.data(), buf.data() + buf.size(), val);
     128            0 :     IF_ASSERT_FAILED(ec == std::errc {}) {
     129            0 :         return *this;
     130              :     }
     131              : 
     132            0 :     write(buf.data(), static_cast<size_t>(last - buf.data()));
     133              : 
     134            0 :     return *this;
     135              : }
     136              : 
     137         2800 : TextStream& TextStream::operator<<(const uint64_t val)
     138              : {
     139              :     // ceil(log_10(2^64)) = 20
     140         2800 :     std::array<char, 20> buf{};
     141         8400 :     const auto [last, ec] = std::to_chars(buf.data(), buf.data() + buf.size(), val);
     142         2800 :     IF_ASSERT_FAILED(ec == std::errc {}) {
     143            0 :         return *this;
     144              :     }
     145              : 
     146         8400 :     write(buf.data(), static_cast<size_t>(last - buf.data()));
     147              : 
     148         2800 :     return *this;
     149              : }
     150              : 
     151       569409 : TextStream& TextStream::operator<<(const char* s)
     152              : {
     153       569409 :     return operator<<(std::string_view { s });
     154              : }
     155              : 
     156      1914334 : TextStream& TextStream::operator<<(const std::string_view str)
     157              : {
     158      1914334 :     write(str.data(), str.size());
     159      1914334 :     return *this;
     160              : }
     161              : 
     162              : #ifndef NO_QT_SUPPORT
     163            0 : TextStream& TextStream::operator<<(const QString& s)
     164              : {
     165            0 :     QByteArray ba = s.toUtf8();
     166            0 :     write(ba.constData(), ba.length());
     167            0 :     return *this;
     168            0 : }
     169              : 
     170              : #endif
     171              : 
     172            0 : TextStream& TextStream::operator<<(const ByteArray& b)
     173              : {
     174            0 :     write(reinterpret_cast<const char*>(b.constData()), b.size());
     175            0 :     return *this;
     176              : }
     177              : 
     178        43133 : TextStream& TextStream::operator<<(const String& s)
     179              : {
     180        43133 :     ByteArray b = s.toUtf8();
     181        43133 :     write(reinterpret_cast<const char*>(b.constData()), b.size());
     182        43133 :     return *this;
     183        43133 : }
     184              : 
     185     11970557 : void TextStream::write(const char* ch, size_t len)
     186              : {
     187     11970557 :     m_buf.insert(m_buf.end(), reinterpret_cast<const uint8_t*>(ch), reinterpret_cast<const uint8_t*>(ch + len));
     188     11970557 :     if (m_device && m_buf.size() > TEXTSTREAM_BUFFERSIZE) {
     189          596 :         flush();
     190              :     }
     191     11970557 : }
        

Generated by: LCOV version 2.0-1