123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- /*
- * 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
|