/* * tuningCollection.cpp * -------------------- * Purpose: Alternative sample tuning collection class. * Notes : (currently none) * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ #include "stdafx.h" #include "tuningcollection.h" #include "mpt/io/io.hpp" #include "mpt/io/io_stdstream.hpp" #include "../common/serialization_utils.h" #include #include "../common/mptFileIO.h" #include "Loaders.h" #ifdef MODPLUG_TRACKER #include "../mptrack/TrackerSettings.h" #endif //MODPLUG_TRACKER OPENMPT_NAMESPACE_BEGIN namespace Tuning { /* Version history: 2->3: Serialization revamp(August 2007) 1->2: Sizetypes of string serialisation from size_t(uint32) to uint8. (March 2007) */ namespace CTuningS11n { void ReadStr(std::istream &iStrm, mpt::ustring &ustr, const std::size_t dummy, mpt::Charset charset); void WriteStr(std::ostream &oStrm, const mpt::ustring &ustr); } // namespace CTuningS11n using namespace CTuningS11n; static void ReadTuning(std::istream &iStrm, CTuningCollection &Tc, const std::size_t dummy, mpt::Charset defaultCharset) { MPT_UNREFERENCED_PARAMETER(dummy); Tc.AddTuning(iStrm, defaultCharset); } static void WriteTuning(std::ostream& oStrm, const CTuning& t) { t.Serialize(oStrm); } CTuning* CTuningCollection::GetTuning(const mpt::ustring &name) { for(std::size_t i = 0; iGetName() == name) { return m_Tunings[i].get(); } } return nullptr; } const CTuning* CTuningCollection::GetTuning(const mpt::ustring &name) const { for(std::size_t i = 0; iGetName() == name) { return m_Tunings[i].get(); } } return nullptr; } Tuning::SerializationResult CTuningCollection::Serialize(std::ostream& oStrm, const mpt::ustring &name) const { srlztn::SsbWrite ssb(oStrm); ssb.BeginWrite("TC", 3); // version ssb.WriteItem(int8(1), "UTF8"); ssb.WriteItem(name, "0", &WriteStr); uint16 dummyEditMask = 0xffff; ssb.WriteItem(dummyEditMask, "1"); const size_t tcount = m_Tunings.size(); for(size_t i = 0; i(inStrm, beginMarker); if(beginMarker != MagicBE("TCSH")) // Magic is reversed in file, hence BE return Tuning::SerializationResult::NoMagic; //2. version int32 version = 0; mpt::IO::ReadIntLE(inStrm, version); if(version > 2 || version < 1) return Tuning::SerializationResult::Failure; //3. Name if(version < 2) { std::string name; if(!mpt::IO::ReadSizedStringLE(inStrm, name, 256)) return Tuning::SerializationResult::Failure; uname = mpt::ToUnicode(defaultCharset, name); } else { std::string name; if(!mpt::IO::ReadSizedStringLE(inStrm, name)) return Tuning::SerializationResult::Failure; uname = mpt::ToUnicode(defaultCharset, name); } //4. Editmask int16 em = 0; mpt::IO::ReadIntLE(inStrm, em); //Not assigning the value yet, for if it sets some property const, //further loading might fail. //5. Tunings { uint32 s = 0; mpt::IO::ReadIntLE(inStrm, s); if(s > 50) return Tuning::SerializationResult::Failure; for(size_t i = 0; i(inStrm, endMarker); if(endMarker != MagicBE("TCSF")) // Magic is reversed in file, hence BE return Tuning::SerializationResult::Failure; return Tuning::SerializationResult::Success; } bool CTuningCollection::Remove(const CTuning *pT) { const auto it = std::find_if(m_Tunings.begin(), m_Tunings.end(), [&] (const std::unique_ptr & upT) -> bool { return upT.get() == pT; } ); if(it == m_Tunings.end()) { return false; } m_Tunings.erase(it); return true; } bool CTuningCollection::Remove(const std::size_t i) { if(i >= m_Tunings.size()) { return false; } m_Tunings.erase(m_Tunings.begin() + i); return true; } CTuning* CTuningCollection::AddTuning(std::unique_ptr pT) { if(m_Tunings.size() >= s_nMaxTuningCount) { return nullptr; } if(!pT) { return nullptr; } CTuning *result = pT.get(); m_Tunings.push_back(std::move(pT)); return result; } CTuning* CTuningCollection::AddTuning(std::istream &inStrm, mpt::Charset defaultCharset) { if(m_Tunings.size() >= s_nMaxTuningCount) { return nullptr; } if(!inStrm.good()) { return nullptr; } std::unique_ptr pT = CTuning::CreateDeserializeOLD(inStrm, defaultCharset); if(!pT) { pT = CTuning::CreateDeserialize(inStrm, defaultCharset); } if(!pT) { return nullptr; } CTuning *result = pT.get(); m_Tunings.push_back(std::move(pT)); return result; } #ifdef MODPLUG_TRACKER bool UnpackTuningCollection(const CTuningCollection &tc, const mpt::PathString &prefix) { bool error = false; auto numberFmt = mpt::FormatSpec().Dec().FillNul().Width(1 + static_cast(std::log10(tc.GetNumTunings()))); for(std::size_t i = 0; i < tc.GetNumTunings(); ++i) { const CTuning & tuning = *(tc.GetTuning(i)); mpt::PathString fn; fn += prefix; mpt::ustring tuningName = tuning.GetName(); if(tuningName.empty()) { tuningName = U_("untitled"); } SanitizeFilename(tuningName); fn += mpt::PathString::FromUnicode(MPT_UFORMAT("{} - {}")(mpt::ufmt::fmt(i + 1, numberFmt), tuningName)); fn += mpt::PathString::FromUTF8(CTuning::s_FileExtension); if(fn.FileOrDirectoryExists()) { error = true; } else { mpt::SafeOutputFile sfout(fn, std::ios::binary, mpt::FlushModeFromBool(TrackerSettings::Instance().MiscFlushFileBuffersOnSave)); if(tuning.Serialize(sfout) != Tuning::SerializationResult::Success) { error = true; } } } return !error; } #endif } // namespace Tuning OPENMPT_NAMESPACE_END