diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/soundlib/tuningCollection.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/soundlib/tuningCollection.cpp')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/soundlib/tuningCollection.cpp | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/soundlib/tuningCollection.cpp b/Src/external_dependencies/openmpt-trunk/soundlib/tuningCollection.cpp new file mode 100644 index 00000000..f11260b2 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/soundlib/tuningCollection.cpp @@ -0,0 +1,320 @@ +/* + * 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 <algorithm> +#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; i<m_Tunings.size(); i++) + { + if(m_Tunings[i]->GetName() == name) + { + return m_Tunings[i].get(); + } + } + return nullptr; +} + +const CTuning* CTuningCollection::GetTuning(const mpt::ustring &name) const +{ + for(std::size_t i = 0; i<m_Tunings.size(); i++) + { + if(m_Tunings[i]->GetName() == 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<tcount; i++) + ssb.WriteItem(*m_Tunings[i], "2", &WriteTuning); + ssb.FinishWrite(); + + if(ssb.GetStatus() & srlztn::SNT_FAILURE) + return Tuning::SerializationResult::Failure; + else + return Tuning::SerializationResult::Success; +} + + +Tuning::SerializationResult CTuningCollection::Deserialize(std::istream &iStrm, mpt::ustring &name, mpt::Charset defaultCharset) +{ + std::istream::pos_type startpos = iStrm.tellg(); + + const Tuning::SerializationResult oldLoadingResult = DeserializeOLD(iStrm, name, defaultCharset); + + if(oldLoadingResult == Tuning::SerializationResult::NoMagic) + { // An old version was not recognised - trying new version. + iStrm.clear(); + iStrm.seekg(startpos); + srlztn::SsbRead ssb(iStrm); + ssb.BeginRead("TC", 3); // version + int8 use_utf8 = 0; + ssb.ReadItem(use_utf8, "UTF8"); + const mpt::Charset charset = use_utf8 ? mpt::Charset::UTF8 : defaultCharset; + + const srlztn::SsbRead::ReadIterator iterBeg = ssb.GetReadBegin(); + const srlztn::SsbRead::ReadIterator iterEnd = ssb.GetReadEnd(); + for(srlztn::SsbRead::ReadIterator iter = iterBeg; iter != iterEnd; iter++) + { + uint16 dummyEditMask = 0xffff; + if (ssb.CompareId(iter, "0") == srlztn::SsbRead::IdMatch) + ssb.ReadIterItem(iter, name, [charset](std::istream &iStrm, mpt::ustring &ustr, const std::size_t dummy){ return ReadStr(iStrm, ustr, dummy, charset); }); + else if (ssb.CompareId(iter, "1") == srlztn::SsbRead::IdMatch) + ssb.ReadIterItem(iter, dummyEditMask); + else if (ssb.CompareId(iter, "2") == srlztn::SsbRead::IdMatch) + ssb.ReadIterItem(iter, *this, [charset](std::istream &iStrm, CTuningCollection &Tc, const std::size_t dummy){ return ReadTuning(iStrm, Tc, dummy, charset); }); + } + + if(ssb.GetStatus() & srlztn::SNT_FAILURE) + return Tuning::SerializationResult::Failure; + else + return Tuning::SerializationResult::Success; + } + else + { + return oldLoadingResult; + } +} + + +Tuning::SerializationResult CTuningCollection::DeserializeOLD(std::istream &inStrm, mpt::ustring &uname, mpt::Charset defaultCharset) +{ + + //1. begin marker: + uint32 beginMarker = 0; + mpt::IO::ReadIntLE<uint32>(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<int32>(inStrm, version); + if(version > 2 || version < 1) + return Tuning::SerializationResult::Failure; + + //3. Name + if(version < 2) + { + std::string name; + if(!mpt::IO::ReadSizedStringLE<uint32>(inStrm, name, 256)) + return Tuning::SerializationResult::Failure; + uname = mpt::ToUnicode(defaultCharset, name); + } + else + { + std::string name; + if(!mpt::IO::ReadSizedStringLE<uint8>(inStrm, name)) + return Tuning::SerializationResult::Failure; + uname = mpt::ToUnicode(defaultCharset, name); + } + + //4. Editmask + int16 em = 0; + mpt::IO::ReadIntLE<int16>(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<uint32>(inStrm, s); + if(s > 50) + return Tuning::SerializationResult::Failure; + for(size_t i = 0; i<s; i++) + { + if(!AddTuning(inStrm, defaultCharset)) + { + return Tuning::SerializationResult::Failure; + } + } + } + + //6. End marker + uint32 endMarker = 0; + mpt::IO::ReadIntLE<uint32>(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<CTuning> & 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<CTuning> 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<CTuning> 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<int>(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 |