1 /*
2 * misc_util.h
3 * -----------
4 * Purpose: Various useful utility functions.
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 "mpt/base/span.hpp"
16 #include "mpt/exception_text/exception_text.hpp"
17
18 #include "mptAssert.h"
19 #include "mptBaseMacros.h"
20 #include "mptBaseTypes.h"
21 #include "mptBaseUtils.h"
22 #include "mptString.h"
23
24 // old
25 #include "mptBaseUtils.h"
26 #include "mptStringFormat.h"
27 #include "mptStringParse.h"
28 #include "mptTime.h"
29
30 #include <stdexcept>
31 #include <optional>
32 #include <vector>
33
34 #include <cstdlib>
35
36 #include <stdlib.h>
37
38
39
40 OPENMPT_NAMESPACE_BEGIN
41
42
43
44 namespace Util
45 {
46
47
48
49 // Insert a range of items [insStart, insEnd], and possibly shift item fix to the left.
50 template<typename T>
InsertItem(const T insStart,const T insEnd,T & fix)51 void InsertItem(const T insStart, const T insEnd, T &fix)
52 {
53 MPT_ASSERT(insEnd >= insStart);
54 if(fix >= insStart)
55 {
56 fix += (insEnd - insStart + 1);
57 }
58 }
59
60 // Insert a range of items [insStart, insEnd], and possibly shift items in range [fixStart, fixEnd] to the right.
61 template<typename T>
InsertRange(const T insStart,const T insEnd,T & fixStart,T & fixEnd)62 void InsertRange(const T insStart, const T insEnd, T &fixStart, T &fixEnd)
63 {
64 MPT_ASSERT(insEnd >= insStart);
65 const T insLength = insEnd - insStart + 1;
66 if(fixStart >= insEnd)
67 {
68 fixStart += insLength;
69 }
70 if(fixEnd >= insEnd)
71 {
72 fixEnd += insLength;
73 }
74 }
75
76 // Delete a range of items [delStart, delEnd], and possibly shift item fix to the left.
77 template<typename T>
DeleteItem(const T delStart,const T delEnd,T & fix)78 void DeleteItem(const T delStart, const T delEnd, T &fix)
79 {
80 MPT_ASSERT(delEnd >= delStart);
81 if(fix > delEnd)
82 {
83 fix -= (delEnd - delStart + 1);
84 }
85 }
86
87 // Delete a range of items [delStart, delEnd], and possibly shift items in range [fixStart, fixEnd] to the left.
88 template<typename T>
DeleteRange(const T delStart,const T delEnd,T & fixStart,T & fixEnd)89 void DeleteRange(const T delStart, const T delEnd, T &fixStart, T &fixEnd)
90 {
91 MPT_ASSERT(delEnd >= delStart);
92 const T delLength = delEnd - delStart + 1;
93 if(delStart < fixStart && delEnd < fixStart)
94 {
95 // cut part is before loop start
96 fixStart -= delLength;
97 fixEnd -= delLength;
98 } else if(delStart < fixStart && delEnd < fixEnd)
99 {
100 // cut part is partly before loop start
101 fixStart = delStart;
102 fixEnd -= delLength;
103 } else if(delStart >= fixStart && delEnd < fixEnd)
104 {
105 // cut part is in the loop
106 fixEnd -= delLength;
107 } else if(delStart >= fixStart && delStart < fixEnd && delEnd > fixEnd)
108 {
109 // cut part is partly before loop end
110 fixEnd = delStart;
111 }
112 }
113
114
115
116 template<typename T, std::size_t n>
117 class fixed_size_queue
118 {
119 private:
120 T buffer[n+1];
121 std::size_t read_position;
122 std::size_t write_position;
123 public:
fixed_size_queue()124 fixed_size_queue() : read_position(0), write_position(0)
125 {
126 return;
127 }
clear()128 void clear()
129 {
130 read_position = 0;
131 write_position = 0;
132 }
read_size()133 std::size_t read_size() const
134 {
135 if ( write_position > read_position )
136 {
137 return write_position - read_position;
138 } else if ( write_position < read_position )
139 {
140 return write_position - read_position + n + 1;
141 } else
142 {
143 return 0;
144 }
145 }
write_size()146 std::size_t write_size() const
147 {
148 if ( write_position > read_position )
149 {
150 return read_position - write_position + n;
151 } else if ( write_position < read_position )
152 {
153 return read_position - write_position - 1;
154 } else
155 {
156 return n;
157 }
158 }
push(const T & v)159 bool push( const T & v )
160 {
161 if ( !write_size() )
162 {
163 return false;
164 }
165 buffer[write_position] = v;
166 write_position = ( write_position + 1 ) % ( n + 1 );
167 return true;
168 }
pop()169 bool pop() {
170 if ( !read_size() )
171 {
172 return false;
173 }
174 read_position = ( read_position + 1 ) % ( n + 1 );
175 return true;
176 }
peek()177 T peek() {
178 if ( !read_size() )
179 {
180 return T();
181 }
182 return buffer[read_position];
183 }
peek_p()184 const T * peek_p()
185 {
186 if ( !read_size() )
187 {
188 return nullptr;
189 }
190 return &(buffer[read_position]);
191 }
peek_next_p()192 const T * peek_next_p()
193 {
194 if ( read_size() < 2 )
195 {
196 return nullptr;
197 }
198 return &(buffer[(read_position+1)%(n+1)]);
199 }
200 };
201
202
203
204 } // namespace Util
205
206
207
208 #if MPT_OS_WINDOWS
209
210 template <typename Tstring, typename Tbuf, typename Tsize>
ParseMaybeNullTerminatedStringFromBufferWithSizeInBytes(const Tbuf * buf,Tsize sizeBytes)211 Tstring ParseMaybeNullTerminatedStringFromBufferWithSizeInBytes(const Tbuf *buf, Tsize sizeBytes)
212 {
213 // REG_SZ may contain a single NUL terminator, multiple NUL terminators, or no NUL terminator at all
214 return Tstring(reinterpret_cast<const typename Tstring::value_type*>(buf), reinterpret_cast<const typename Tstring::value_type*>(buf) + (sizeBytes / sizeof(typename Tstring::value_type))).c_str();
215 }
216
217
218 #endif // MPT_OS_WINDOWS
219
220
221 OPENMPT_NAMESPACE_END
222