1 /*
2  * PatternContainer.h
3  * ------------------
4  * Purpose: Container class for managing patterns.
5  * Notes  : (currently none)
6  * Authors: OpenMPT Devs
7  * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
8  */
9 
10 
11 #pragma once
12 
13 #include "openmpt/all/BuildSettings.hpp"
14 
15 #include "pattern.h"
16 
17 #include <algorithm>
18 
19 OPENMPT_NAMESPACE_BEGIN
20 
21 class CSoundFile;
22 
23 class CPatternContainer
24 {
25 public:
26 	CPattern& operator[](const int pat) { return m_Patterns[pat]; }
27 	const CPattern& operator[](const int pat) const { return m_Patterns[pat]; }
28 
29 public:
CPatternContainer(CSoundFile & sndFile)30 	CPatternContainer(CSoundFile& sndFile) : m_rSndFile(sndFile) { }
31 
32 	// Empty and initialize all patterns.
33 	void ClearPatterns();
34 	// Delete all patterns.
35 	void DestroyPatterns();
36 
37 	// Insert (default)pattern to given position. If pattern already exists at that position,
38 	// ignoring request. Returns true on success, false otherwise.
39 	bool Insert(const PATTERNINDEX index, const ROWINDEX rows);
40 
41 	// Insert pattern to position with the lowest index, and return that index, PATTERNINDEX_INVALID on failure.
42 	// If respectQtyLimits is true, inserting patterns will fail if the resulting pattern index would exceed the current format's pattern quantity limits.
43 	PATTERNINDEX InsertAny(const ROWINDEX rows, bool respectQtyLimits = false);
44 
45 	// Duplicate an existing pattern. Returns new pattern index on success, or PATTERNINDEX_INVALID on failure.
46 	// If respectQtyLimits is true, inserting patterns will fail if the resulting pattern index would exceed the current format's pattern quantity limits.
47 	PATTERNINDEX Duplicate(PATTERNINDEX from, bool respectQtyLimits = false);
48 
49 	//Remove pattern from given position. Currently it actually makes the pattern
50 	//'invisible' - the pattern data is cleared but the actual pattern object won't get removed.
51 	void Remove(const PATTERNINDEX index);
52 
53 	// Applies function object for modcommands in patterns in given range.
54 	// Return: Copy of the function object.
55 	template <class Func>
56 	Func ForEachModCommand(PATTERNINDEX nStartPat, PATTERNINDEX nLastPat, Func func);
57 	template <class Func>
ForEachModCommand(Func func)58 	Func ForEachModCommand(Func func) { return ForEachModCommand(0, Size() - 1, func); }
59 
begin()60 	std::vector<CPattern>::iterator begin() { return m_Patterns.begin(); }
begin()61 	std::vector<CPattern>::const_iterator begin() const { return m_Patterns.begin(); }
cbegin()62 	std::vector<CPattern>::const_iterator cbegin() const { return m_Patterns.cbegin(); }
end()63 	std::vector<CPattern>::iterator end() { return m_Patterns.end(); }
end()64 	std::vector<CPattern>::const_iterator end() const { return m_Patterns.end(); }
cend()65 	std::vector<CPattern>::const_iterator cend() const { return m_Patterns.cend(); }
66 
Size()67 	PATTERNINDEX Size() const { return static_cast<PATTERNINDEX>(m_Patterns.size()); }
68 
GetSoundFile()69 	CSoundFile& GetSoundFile() { return m_rSndFile; }
GetSoundFile()70 	const CSoundFile& GetSoundFile() const { return m_rSndFile; }
71 
72 	// Return true if pattern can be accessed with operator[](iPat), false otherwise.
IsValidIndex(const PATTERNINDEX iPat)73 	bool IsValidIndex(const PATTERNINDEX iPat) const { return (iPat < Size()); }
74 
75 	// Return true if IsValidIndex() is true and the corresponding pattern has allocated modcommand array, false otherwise.
IsValidPat(const PATTERNINDEX iPat)76 	bool IsValidPat(const PATTERNINDEX iPat) const { return IsValidIndex(iPat) && m_Patterns[iPat].IsValid(); }
77 
78 	// Returns true if the pattern is empty, i.e. there are no notes/effects in this pattern
79 	bool IsPatternEmpty(const PATTERNINDEX nPat) const;
80 
81 	void ResizeArray(const PATTERNINDEX newSize);
82 
83 	void OnModTypeChanged(const MODTYPE oldtype);
84 
85 	// Returns index of last valid pattern + 1, zero if no such pattern exists.
86 	PATTERNINDEX GetNumPatterns() const;
87 
88 	// Returns index of highest pattern with pattern named + 1.
89 	PATTERNINDEX GetNumNamedPatterns() const;
90 
91 
92 private:
93 	std::vector<CPattern> m_Patterns;
94 	CSoundFile &m_rSndFile;
95 };
96 
97 
98 template <class Func>
ForEachModCommand(PATTERNINDEX nStartPat,PATTERNINDEX nLastPat,Func func)99 Func CPatternContainer::ForEachModCommand(PATTERNINDEX nStartPat, PATTERNINDEX nLastPat, Func func)
100 {
101 	if (nStartPat > nLastPat || nLastPat >= Size())
102 		return func;
103 	for (PATTERNINDEX nPat = nStartPat; nPat <= nLastPat; nPat++) if (m_Patterns[nPat].IsValid())
104 		std::for_each(m_Patterns[nPat].begin(), m_Patterns[nPat].end(), func);
105 	return func;
106 }
107 
108 
109 const char FileIdPatterns[] = "mptPc";
110 
111 void ReadModPatterns(std::istream& iStrm, CPatternContainer& patc, const size_t nSize = 0);
112 void WriteModPatterns(std::ostream& oStrm, const CPatternContainer& patc);
113 
114 
115 OPENMPT_NAMESPACE_END
116