1 /*
2 MusicXML Library
3 Copyright (C) Grame 2006-2013
4
5 This Source Code Form is subject to the terms of the Mozilla Public
6 License, v. 2.0. If a copy of the MPL was not distributed with this
7 file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
9 Grame Research Laboratory, 11, cours de Verdun Gensoul 69002 Lyon - France
10 research@grame.fr
11 */
12
13 #ifndef ___utilities___
14 #define ___utilities___
15
16 #include <string>
17 #include <cassert>
18
19 #include <iostream>
20 #include <sstream>
21
22 #include <ctime>
23
24 #include <set>
25 #include <list>
26
27 #include <functional>
28 #include <algorithm>
29
30 #include <string.h>
31
32 /* JMI
33 #ifdef WIN32
34 // JMI
35 #else
36 #include <iconv.h>
37 #endif
38 */
39
40 #include "smartpointer.h"
41 #include "basevisitor.h"
42
43
44 namespace MusicXML2
45 {
46
47 //______________________________________________________________________________
48 class EXP timingItem : public smartable
49 {
50 public:
51 enum timingItemKind { kMandatory, kOptional };
52
53 static SMARTP<timingItem> createTimingItem (
54 std::string activity,
55 std::string description,
56 timingItemKind kind,
57 std::clock_t startClock,
58 std::clock_t endClock);
59
60 timingItem (
61 std::string activity,
62 std::string description,
63 timingItemKind kind,
64 std::clock_t startClock,
65 std::clock_t endClock);
66
67 std::string fActivity;
68 std::string fDescription;
69 timingItemKind fKind;
70 clock_t fStartClock;
71 clock_t fEndClock;
72 };
73
74 typedef SMARTP<timingItem> S_timingItem;
75
76 class EXP timing {
77 public:
78 timing ();
79 virtual ~timing ();
80
81 // global variable for general use
82 static timing gTiming;
83
84 // add an item
85 void appendTimingItem (
86 std::string activity,
87 std::string description,
88 timingItem::timingItemKind
89 kind,
90 clock_t startClock,
91 clock_t endClock);
92
93 // print
94 void print (std::ostream& os) const;
95
96 private:
97
98 std::list<S_timingItem>
99 fTimingItemsList;
100 };
101 EXP std::ostream& operator<< (std::ostream& os, const timing& tim);
102
103 //______________________________________________________________________________
104 class EXP indenter
105 {
106 public:
107
108 indenter (std::string spacer = " ");
109 virtual ~indenter ();
110
111 // get the indent
getIndent()112 int getIndent () const
113 { return fIndent; }
114
115 // increase the indentation by 1
116 indenter& operator++ (const int value);
117
118 // decrease the indentation by 1
119 indenter& operator-- (const int value);
120
121 indenter& increment (int value);
122 indenter& decrement (int value);
123
124 // reset the indentation
resetToZero()125 void resetToZero ()
126 { fIndent = 0; }
127
128 // check indentation value
129 bool operator == (const int &value) const
130 { return fIndent == value; }
131 bool operator != (const int &value) const
132 { return fIndent != value; }
133
134 // output as much space as specified
135 void print (std::ostream& os) const;
136
137 // get a spacer for adhoc uses, without increasing the indentation
getSpacer()138 std::string getSpacer () const
139 { return fSpacer; }
140
141 // indent a multiline 'R"(...)"' std::string
142 std::string indentMultiLineString (std::string value);
143
144 // global variable for general use
145 static indenter gIndenter;
146
147 private:
148 int fIndent;
149 std::string fSpacer;
150 };
151
152 EXP std::ostream& operator<< (std::ostream& os, const indenter& idtr);
153
154 // useful shortcut macros
155 #define gIndenter indenter::gIndenter
156 #define gTab indenter::gIndenter.getSpacer ()
157
158 //______________________________________________________________________________
159 // a stream buffer that prefixes each line
160 // with the current indentation, i.e. spaces
161
162 /*
163 std::endl declaration:
164
165 std::endl for ostream
166 ostream& endl (ostream& os);
167
168 basic template
169 template <class charT, class traits>
170 basic_ostream<charT,traits>& endl (basic_ostream<charT,traits>& os);
171
172 Insert newline and flush
173 Inserts a new-line character and flushes the stream.
174
175 Its behavior is equivalent to calling os.put('\n') (or os.put(os.widen('\n')) for character types other than char), and then os.flush().
176
177 --
178
179 Reference for this class:
180 https://stackoverflow.com/questions/2212776/overload-handling-of-stdendl
181 */
182
183 class indentedStreamBuf: public std::stringbuf
184 {
185 private:
186
187 std::ostream& fOutputSteam;
188 indenter& fIndenter;
189
190 public:
191
192 // constructor
indentedStreamBuf(std::ostream & outputStream,indenter & idtr)193 indentedStreamBuf (
194 std::ostream& outputStream,
195 indenter& idtr)
196 : fOutputSteam (outputStream),
197 fIndenter (idtr)
198 {}
199
200 // indentation
getIndenter()201 indenter& getIndenter ()
202 { return fIndenter; }
203
204 // flush
flush()205 void flush ()
206 { fOutputSteam.flush (); }
207
208 virtual int sync ();
209 };
210
211 //______________________________________________________________________________
212 class EXP indentedOstream: public std::ostream
213 {
214 /*
215 Reference for this class:
216 https://stackoverflow.com/questions/2212776/overload-handling-of-stdendl
217
218 Usage:
219 indentedOstream myStream (std::cout);
220
221 myStream <<
222 1 << 2 << 3 << std::endl <<
223 5 << 6 << std::endl <<
224 7 << 8 << std::endl;
225 */
226
227 private:
228 // indentedOstream just uses an indentedStreamBuf
229 indentedStreamBuf fIndentedStreamBuf;
230
231 public:
232
233 // constructor
indentedOstream(std::ostream & str,indenter & idtr)234 indentedOstream (
235 std::ostream& str,
236 indenter& idtr)
237 : std::ostream (&fIndentedStreamBuf),
238 fIndentedStreamBuf (str, idtr)
239 {}
240
241 // destructor
~indentedOstream()242 virtual ~indentedOstream ()
243 {};
244
245 // flush
flush()246 void flush ()
247 { fIndentedStreamBuf.flush (); }
248
249 // indentation
getIndenter()250 indenter& getIndenter ()
251 { return fIndentedStreamBuf.getIndenter (); }
252
incrIdentation()253 void incrIdentation ()
254 { fIndentedStreamBuf.getIndenter ()++; }
255
decrIdentation()256 void decrIdentation ()
257 { fIndentedStreamBuf.getIndenter ()--; }
258
259 // global variables for general use
260 static indentedOstream
261 gOutputIndentedOstream;
262 static indentedOstream
263 gLogIndentedOstream;
264 static indentedOstream
265 gNullIndentedOstream;
266 };
267
268 // useful shortcut macros
269 #define gOutputOstream indentedOstream::gOutputIndentedOstream
270 #define gLogOstream indentedOstream::gLogIndentedOstream
271 #define gNullOstream indentedOstream::gNullIndentedOstream
272
273 //______________________________________________________________________________
274 struct stringQuoteEscaper
275 {
276 /* usage:
277 string dest = "";
278 for_each( source.begin (), source.end (), stringQuoteEscaper (dest));
279 */
280
281 std::string& target;
282
stringQuoteEscaperstringQuoteEscaper283 explicit stringQuoteEscaper (std::string& t)
284 : target (t)
285 {}
286
operatorstringQuoteEscaper287 void operator() (char ch) const
288 {
289 if( ch == '"') {
290 // or switch on any character that
291 // needs escaping like '\' itself
292 target.push_back ('\\');
293 }
294 target.push_back (ch);
295 }
296 };
297
298 //______________________________________________________________________________
299 struct stringSpaceRemover
300 {
301 /* usage:
302 std::string dest = "";
303 for_each (
304 source.begin (),
305 source.end (),
306 stringSpaceRemover (dest));
307 */
308
309 std::string& target;
310
stringSpaceRemoverstringSpaceRemover311 explicit stringSpaceRemover (std::string& t)
312 : target (t)
313 {}
314
operatorstringSpaceRemover315 void operator() (char ch) const
316 {
317 if (ch != ' ') {
318 target.push_back (ch);
319 }
320 }
321 };
322
323 //______________________________________________________________________________
324 struct stringSpaceReplacer
325 {
326 /* usage:
327 std::string dest = "";
328 for_each (
329 source.begin (),
330 source.end (),
331 stringSpaceReplacer (dest, ersatz));
332 */
333
334 std::string& target;
335 char ersatz;
336
stringSpaceReplacerstringSpaceReplacer337 explicit stringSpaceReplacer (std::string& t, char ch)
338 : target (t), ersatz (ch)
339 {}
340
operatorstringSpaceReplacer341 void operator() (char ch) const
342 {
343 if (ch == ' ')
344 target.push_back (ersatz);
345 else
346 target.push_back (ch);
347 }
348 };
349
350 //______________________________________________________________________________
351 std::string replicateString (
352 std::string str,
353 int times);
354
355 //______________________________________________________________________________
356 std::string replaceSubstringInString (
357 std::string str,
358 std::string subString,
359 std::string ersatz);
360
361 //______________________________________________________________________________
362 std::string int2EnglishWord (int n);
363
364 //______________________________________________________________________________
365 std::string stringNumbersToEnglishWords (std::string str);
366
367 //______________________________________________________________________________
368 std::set<int> decipherNaturalNumbersSetSpecification (
369 std::string theSpecification,
370 bool debugMode = false);
371
372 //______________________________________________________________________________
373 std::set<std::string> decipherStringsSetSpecification (
374 std::string theSpecification,
375 bool debugMode = false);
376
377 //______________________________________________________________________________
378 std::list<int> extractNumbersFromString (
379 std::string theString, // can contain "1, 2, 17"
380 bool debugMode = false);
381
382 //______________________________________________________________________________
383 // from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
384 // trim string from start
ltrim(std::string & s)385 inline std::string <rim (std::string &s) {
386 std::function <int (int)>
387 checkSpace =
388 [] (int x) { return isspace (x); };
389
390 s.erase (
391 s.begin (),
392 find_if (
393 s.begin (),
394 s.end (),
395 std::not1 (checkSpace)
396 )
397 );
398
399 return s;
400 }
401
402 // trim string from end
rtrim(std::string & s)403 inline std::string &rtrim (std::string &s) {
404 std::function <int (int)>
405 checkSpace =
406 [] (int x) { return isspace (x); };
407
408 s.erase (
409 find_if (
410 s.rbegin (),
411 s.rend (),
412 std::not1 (checkSpace)
413 ).base(),
414 s.end ()
415 );
416
417 return s;
418 }
419
420 // trim string from both ends
trim(std::string & s)421 inline std::string &trim (std::string &s) {
422 return ltrim (rtrim (s));
423 }
424
425 //______________________________________________________________________________
426 std::pair<std::string, std::string> extractNamesPairFromString (
427 std::string theString, // may contain "P1 = Bassoon"
428 char separator,
429 bool debugMode = false);
430
431 //______________________________________________________________________________
432 std::string doubleQuoteStringIfNonAlpha (
433 std::string theString);
434
435 std::string quoteStringIfNonAlpha (
436 std::string theString);
437
438 std::string doubleQuoteString (
439 std::string theString);
440
441 std::string quoteString (
442 std::string theString);
443
444 //______________________________________________________________________________
445 std::string booleanAsString (bool value);
446
447 //______________________________________________________________________________
448 std::string singularOrPlural (
449 int number, std::string singularName, std::string pluralName);
450
451 std::string singularOrPluralWithoutNumber (
452 int number, std::string singularName, std::string pluralName);
453
454 //______________________________________________________________________________
455 void oahWarning (std::string warningMessage);
456
457 void oahError (std::string errorMessage);
458
459 //______________________________________________________________________________
460 std::string escapeDoubleQuotes (std::string s);
461
462 //______________________________________________________________________________
463 void convertHTMLEntitiesToPlainCharacters (std::string& s);
464
465 //______________________________________________________________________________
466 void splitStringIntoChunks (
467 std::string theString,
468 std::string theSeparator,
469 std::list<std::string>& chunksList);
470
471 void splitRegularStringAtEndOfLines (
472 std::string theString,
473 std::list<std::string>& chunksList);
474
475 void splitHTMLStringContainingEndOfLines ( // JMI
476 std::string theString,
477 std::list<std::string>& chunksList);
478
479 //______________________________________________________________________________
480 std::string baseName (const std::string &filename);
481 // wait until c++17 for a standard library containing basename()...
482
483 //______________________________________________________________________________
484 std::string makeSingleWordFromString (const std::string& theString);
485
486
487 } // namespace MusicXML2
488
489
490 #endif
491