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 // #include "unistd.h"
14
15 #include <iostream>
16 #include <sstream>
17 #include <cassert>
18
19 #include <vector>
20 #include <map>
21
22 #include <iomanip> // setw, ...
23
24 #include "rational.h"
25 #include "utilities.h"
26
27 using namespace std;
28
29 namespace MusicXML2
30 {
31
32 //______________________________________________________________________________
createTimingItem(string activity,string description,timingItemKind kind,clock_t startClock,clock_t endClock)33 S_timingItem timingItem::createTimingItem (
34 string activity,
35 string description,
36 timingItemKind kind,
37 clock_t startClock,
38 clock_t endClock)
39 {
40 timingItem* o = new timingItem (
41 activity,
42 description,
43 kind,
44 startClock,
45 endClock);
46 assert(o!=0);
47 return o;
48 }
49
timingItem(string activity,string description,timingItemKind kind,clock_t startClock,clock_t endClock)50 timingItem::timingItem (
51 string activity,
52 string description,
53 timingItemKind kind,
54 clock_t startClock,
55 clock_t endClock)
56 {
57 fActivity = activity;
58 fDescription = description;
59 fKind = kind;
60 fStartClock = startClock;
61 fEndClock = endClock;
62 }
63
timing()64 timing::timing ()
65 {}
66
~timing()67 timing::~timing ()
68 {}
69
70
appendTimingItem(string activity,string description,timingItem::timingItemKind kind,clock_t startClock,clock_t endClock)71 void timing::appendTimingItem (
72 string activity,
73 string description,
74 timingItem::timingItemKind
75 kind,
76 clock_t startClock,
77 clock_t endClock)
78 {
79 S_timingItem
80 timingItem =
81 timingItem::createTimingItem (
82 activity,
83 description,
84 kind,
85 startClock,
86 endClock);
87
88 fTimingItemsList.push_back (timingItem);
89 }
90
operator <<(ostream & os,const timing & tim)91 ostream& operator<< (ostream& os, const timing& tim) {
92 tim.print(os);
93 return os;
94 }
95
print(ostream & os) const96 void timing::print (ostream& os) const
97 {
98 const int
99 activityWidth = 8,
100 descriptionWidth = 31,
101 kindWidth = 9,
102 secondsWidth = 9,
103 secondsPrecision = 6;
104
105 clock_t
106 totalClock = 0.0,
107 totalMandatoryClock = 0.0,
108 totalOptionalClock = 0.0;
109
110 os << endl << "Timing information:" << endl << endl <<
111 setw (activityWidth) << "Activity" << " " <<
112 setw (descriptionWidth) << "Description" << " " <<
113 setw (kindWidth) << "Kind" << " " <<
114 setw (secondsWidth) << "CPU (sec)" << endl <<
115 setw (activityWidth) << replicateString ("-", activityWidth) << " " <<
116 setw (descriptionWidth) << replicateString ("-", descriptionWidth) << " " <<
117 setw (kindWidth) << replicateString ("-", kindWidth) << " " <<
118 setw (secondsWidth) << replicateString ("-", secondsWidth) << endl << endl;
119
120 for ( list<S_timingItem>::const_iterator i=fTimingItemsList.begin (); i!=fTimingItemsList.end (); i++) {
121 clock_t timingItemClock = (*i)->fEndClock - (*i)->fStartClock;
122 totalClock += timingItemClock;
123
124 os << left <<
125 setw (activityWidth) << (*i)->fActivity << " " <<
126 setw (descriptionWidth) << (*i)->fDescription << " ";
127
128 switch ((*i)->fKind) {
129 case timingItem::kMandatory:
130 totalMandatoryClock += timingItemClock;
131 os << setw (kindWidth) << "mandatory";
132 break;
133 case timingItem::kOptional:
134 totalOptionalClock += timingItemClock;
135 os << setw (kindWidth) << "optional";
136 break;
137 } // switch
138
139 os << " " <<
140 setw (secondsWidth) << setprecision(secondsPrecision) <<
141 left << float(timingItemClock) / CLOCKS_PER_SEC << endl;
142 } // for
143
144 const int
145 totalClockWidth = 7,
146 totalMandatoryClockWidth = 9,
147 totalOptionalClockWidth = 10,
148 totalsPrecision = 6;
149
150 os << left <<
151 endl <<
152 setw (totalClockWidth) << "Total" <<
153 " " <<
154 setw (totalMandatoryClockWidth) << "Mandatory" <<
155 " " <<
156 setw (totalOptionalClockWidth) << "Optional" <<
157 endl <<
158
159 setw (totalClockWidth) <<
160 replicateString ("-", totalClockWidth) <<
161 " " <<
162 setw (totalMandatoryClockWidth) <<
163 replicateString ("-", totalMandatoryClockWidth) <<
164 " " <<
165 setw (secondsWidth) <<
166 replicateString ("-", secondsWidth) <<
167 setprecision(totalsPrecision) <<
168 endl <<
169
170 setw (totalClockWidth) <<
171 float(totalClock) / CLOCKS_PER_SEC <<
172 " " <<
173 setw (totalMandatoryClockWidth) <<
174 float(totalMandatoryClock) / CLOCKS_PER_SEC <<
175 " " <<
176 setw (totalOptionalClockWidth) <<
177 float(totalOptionalClock) / CLOCKS_PER_SEC <<
178 endl <<
179 endl;
180 }
181
182 timing timing::gTiming;
183
184 //______________________________________________________________________________
185 //#define DEBUG_INDENTER
186
187 indenter indenter::gIndenter;
188
indenter(string spacer)189 indenter::indenter (string spacer)
190 {
191 fIndent = 0;
192 fSpacer = spacer;
193 }
194
~indenter()195 indenter::~indenter ()
196 {}
197
operator ++(const int value)198 indenter& indenter::operator++ (const int value)
199 {
200 fIndent++;
201
202 #ifdef DEBUG_INDENTER
203 gLogOstream <<
204 "% INDENTER: " << fIndent <<
205 endl;
206 #endif
207
208 return *this;
209 }
210
operator --(const int value)211 indenter& indenter::operator-- (const int value)
212 {
213 fIndent--;
214
215 if (fIndent < 0) {
216 gLogOstream <<
217 endl <<
218 "% ### Indentation has become negative: " << fIndent <<
219 endl << endl;
220
221 #ifdef DEBUG_INDENTER
222 assert(false);
223 #endif
224 }
225
226 #ifdef DEBUG_INDENTER
227 else {
228 gLogOstream <<
229 "% INDENTER: " << fIndent <<
230 endl;
231 }
232 #endif
233
234 return *this;
235 }
236
increment(int value)237 indenter& indenter::increment (int value)
238 {
239 fIndent += value;
240
241 if (fIndent < 0) {
242 gLogOstream <<
243 endl <<
244 "% ### Indentation has become negative: " << fIndent <<
245 endl << endl;
246
247 #ifdef DEBUG_INDENTER
248 assert(false);
249 #endif
250 }
251
252 #ifdef DEBUG_INDENTER
253 else {
254 gLogOstream <<
255 "% INDENTER: " << fIndent <<
256 endl;
257 }
258 #endif
259
260 return *this;
261 }
262
decrement(int value)263 indenter& indenter::decrement (int value)
264 {
265 fIndent -= value;
266
267 if (fIndent < 0) {
268 gLogOstream <<
269 endl <<
270 "% ### Indentation has become negative: " << fIndent <<
271 endl << endl;
272
273 #ifdef DEBUG_INDENTER
274 assert(false);
275 #endif
276 }
277
278 #ifdef DEBUG_INDENTER
279 else {
280 gLogOstream <<
281 "% INDENTER: " << fIndent <<
282 endl;
283 }
284 #endif
285
286 return *this;
287 }
288
indentMultiLineString(string value)289 string indenter::indentMultiLineString (string value)
290 {
291 stringstream s;
292
293 // add indentation ahead of all lines inside 'value'
294 istringstream inputStream (value);
295 string line;
296
297 while (getline (inputStream, line)) {
298 s << line;
299
300 if (inputStream.eof()) break;
301
302 s << endl;
303 this->print (s);
304 } // while
305
306 return s.str ();
307 }
308
operator <<(ostream & os,const indenter & idtr)309 ostream& operator<< (ostream& os, const indenter& idtr) {
310 idtr.print(os);
311 return os;
312 }
313
print(ostream & os) const314 void indenter::print (ostream& os) const
315 {
316 int i = fIndent;
317
318 while (i-- > 0) os << fSpacer;
319 }
320
321 //______________________________________________________________________________
sync()322 int indentedStreamBuf::sync ()
323 {
324 // When we sync the stream with fOutputSteam:
325 // 1) output the indentation then the buffer
326 // 2) reset the buffer
327 // 3) flush the actual output stream we are using.
328
329 std::size_t strSize = str ().size ();
330
331 // fetch the last non-space character in the buffer
332 // caution: the '\n' is present as the last character!
333 std::size_t found = str ().find_last_not_of(' ', strSize - 2);
334
335 // this can be uncommented to see low level informations
336 // fOutputSteam << "% strSize: " << strSize << ", found: " << found << '\n';
337
338 // output the indenter
339 fOutputSteam << fIndenter;
340
341 // output the buffer
342 if (found == strSize - 3) {
343 // don't output the trailing spaces, but output the end of line
344 fOutputSteam << str ().substr (0, found + 1) << '\n';
345 }
346 else {
347 // output the whole buffer
348 fOutputSteam << str ();
349 }
350
351 // reset the buffer
352 str ("");
353
354 // flush the output stream
355 fOutputSteam.flush ();
356
357 return 0;
358 }
359
360 //______________________________________________________________________________
361 indentedOstream indentedOstream::gOutputIndentedOstream (
362 cout, indenter::gIndenter);
363
364 indentedOstream indentedOstream::gLogIndentedOstream (
365 cerr, indenter::gIndenter);
366
367 // code taken from:
368 // http://comp.lang.cpp.moderated.narkive.com/fylLGJgp/redirect-output-to-dev-null
369 template<typename Ch, typename Traits = std::char_traits<Ch> >
370 struct basic_nullbuf : std::basic_streambuf<Ch, Traits>
371 {
372 typedef std::basic_streambuf<Ch, Traits> base_type;
373 typedef typename base_type::int_type int_type;
374 typedef typename base_type::traits_type traits_type;
375
overflowMusicXML2::basic_nullbuf376 virtual int_type overflow (int_type c) {
377 return traits_type::not_eof (c);
378 }
379 };
380
381 // convenient typedefs
382 typedef basic_nullbuf <char> nullbuf;
383 //typedef basic_nullbuf <wchar_t> wnullbuf;
384
385 // buffers and streams
386 nullbuf cnull_obj;
387 //wnullbuf wcnull_obj;
388
389 std::ostream cnull (& cnull_obj);
390 //std::wostream wcnull (& wcnull_obj);
391
392 indentedOstream indentedOstream::gNullIndentedOstream (
393 cnull, indenter::gIndenter);
394
395 //______________________________________________________________________________
replicateString(string str,int times)396 string replicateString (
397 string str,
398 int times)
399 {
400 string result;
401
402 for (int i = 0; i < times; i++)
403 result += str;
404
405 return result;
406 }
407
408 //______________________________________________________________________________
replaceSubstringInString(std::string str,std::string subString,std::string ersatz)409 string replaceSubstringInString (
410 std::string str,
411 std::string subString,
412 std::string ersatz)
413 {
414 string result = str;
415
416 size_t found = result.find (subString);
417
418 if (found != string::npos) {
419 result.replace (found, subString.size (), ersatz);
420 }
421
422 return result;
423 }
424
425 //______________________________________________________________________________
int2EnglishWord(int n)426 string int2EnglishWord (int n)
427 {
428 stringstream s;
429
430 if (n < 0) {
431 s << "Minus_";
432 n = -n;
433
434 // assert(false); // JMI
435 }
436
437 if (n >= 1000) {
438 int nDiv1000 = n / 1000;
439 int nModulo1000 = n % 1000;
440
441 return
442 int2EnglishWord (nDiv1000) +
443 "Thousand" +
444 int2EnglishWord (nModulo1000);
445 }
446
447 else if (n >= 100) {
448 //return "LargerThanNinetyNine";
449 int nDiv100 = n / 100;
450 int nModulo100 = n % 100;
451
452 return
453 int2EnglishWord (nDiv100) +
454 "HundredAnd" +
455 int2EnglishWord (nModulo100);
456 }
457
458 else {
459 switch (n) {
460 case 0:
461 s << "Zero";
462 break;
463 case 1:
464 s << "One";
465 break;
466 case 2:
467 s << "Two";
468 break;
469 case 3:
470 s << "Three";
471 break;
472 case 4:
473 s << "Four";
474 break;
475 case 5:
476 s << "Five";
477 break;
478 case 6:
479 s << "Six";
480 break;
481 case 7:
482 s << "Seven";
483 break;
484 case 8:
485 s << "Eight";
486 break;
487 case 9:
488 s << "Nine";
489 break;
490 case 10:
491 s << "Ten";
492 break;
493 case 11:
494 s << "Eleven";
495 break;
496 case 12:
497 s << "Twelve";
498 break;
499 case 13:
500 s << "Thirteen";
501 break;
502 case 14:
503 s << "Fourteen";
504 break;
505 case 15:
506 s << "Fifteen";
507 break;
508 case 16:
509 s << "Sixteen";
510 break;
511 case 17:
512 s << "Seventeen";
513 break;
514 case 18:
515 s << "Eighteen";
516 break;
517 case 19:
518 s << "Nineteen";
519 break;
520
521 default: {
522 // n >= 20
523 int nDiv10 = n / 10;
524 int nModulo10 = n % 10;
525
526 switch (nDiv10) {
527 case 2:
528 s << "Twenty";
529 break;
530 case 3:
531 s << "Thirty";
532 break;
533 case 4:
534 s << "Fourty";
535 break;
536 case 5:
537 s << "Fifty";
538 break;
539 case 6:
540 s << "Sixty";
541 break;
542 case 7:
543 s << "Seventy";
544 break;
545 case 8:
546 s << "Eighty";
547 break;
548 case 9:
549 s << "Ninety";
550 break;
551 } // switch
552 s << int2EnglishWord (nModulo10);
553 } // default
554 } // switch
555 }
556
557 return s.str ();
558 }
559
560 //______________________________________________________________________________
stringNumbersToEnglishWords(string str)561 string stringNumbersToEnglishWords (string str)
562 {
563 if (! str.size ()) {
564 return "NONE";
565 }
566
567 enum workState {
568 kInitialState, kWorkingOnDigits, kWorkingOnNonDigits };
569
570 vector<string> chunks;
571 vector<int> states;
572
573 workState state = kInitialState;
574
575 string::const_iterator
576 iBegin = str.begin (),
577 iEnd = str.end (),
578 i = iBegin;
579
580 for ( ; ; ) {
581 char ch = (*i);
582
583 if( isdigit(ch)) {
584 // digit
585 if (state != kWorkingOnDigits) {
586 // create a new chunck for digits
587 chunks.push_back ("");
588 states.push_back (kWorkingOnDigits);
589 state = kWorkingOnDigits;
590 }
591 chunks.back().push_back(ch);
592 }
593 else {
594 // non digit
595 if (state != kWorkingOnNonDigits) {
596 // create a new chunck for non digits
597 chunks.push_back ("");
598 states.push_back (kWorkingOnNonDigits);
599 state = kWorkingOnNonDigits;
600 }
601 chunks.back().push_back(ch);
602 }
603 if (++i == iEnd) break;
604 } // for
605
606 string result = "";
607
608 for (unsigned int i = 0; i < chunks.size (); i++) {
609 if (states[i] == kWorkingOnDigits) {
610 int integerValue;
611
612 istringstream inputStream (chunks[i]);
613
614 inputStream >> integerValue;
615
616 result += int2EnglishWord (integerValue);
617 }
618 else {
619 result += chunks[i];
620 }
621 } // for
622
623 return result;
624 };
625
626 //______________________________________________________________________________
consumeDecimalNumber(string::const_iterator theStringIterator,string::const_iterator & remainingStringIterator,bool debugMode)627 int consumeDecimalNumber (
628 string::const_iterator theStringIterator,
629 string::const_iterator& remainingStringIterator,
630 bool debugMode)
631 {
632 string::const_iterator cursor = theStringIterator;
633 int result = 0;
634
635 if (! isdigit (*cursor)) {
636 gLogOstream <<
637 "consumeDecimalNumber (" << *cursor <<
638 "), " << *cursor << " is no decimal digit!" <<
639 endl;
640 }
641
642 while (isdigit (*cursor)) {
643 if (debugMode) {
644 gLogOstream <<
645 "--> consumeDecimalNumber: cursor = |" <<
646 *cursor <<
647 "|" <<
648 endl;
649 }
650
651 result = result*10 + (*cursor-'0');
652
653 cursor++;
654 } // while
655
656 remainingStringIterator = cursor;
657
658 if (debugMode) {
659 gLogOstream <<
660 "--> consumeDecimalNumber: result = " << result <<
661 ", *remainingStringIterator = |" << *remainingStringIterator <<
662 "|" <<
663 endl;
664 }
665
666 return result;
667 }
668
669 //______________________________________________________________________________
decipherNaturalNumbersSetSpecification(string theString,bool debugMode)670 set<int> decipherNaturalNumbersSetSpecification (
671 string theString,
672 bool debugMode)
673 {
674 // A naturalNumbersSetSpecification sample is: "7,15-19,^16-17"
675
676 set<int> result;
677
678 if (debugMode) {
679 gLogOstream <<
680 "--> decipherNaturalNumbersSetSpecification, theString = |" << theString <<
681 "|" <<
682 endl;
683 }
684
685 if (theString.size ()) {
686 string::const_iterator
687 cursor = theString.begin ();
688
689 while (1) {
690 if (debugMode) {
691 gLogOstream <<
692 "--> decipherNaturalNumbersSetSpecification: cursor = |" <<
693 *cursor << "|" <<
694 endl;
695 }
696
697 int negated = 0;
698
699 if (*cursor == '^') {
700 cursor++;
701 negated = 1;
702 }
703
704 int
705 intervalStartNumber =
706 consumeDecimalNumber (cursor, cursor, debugMode),
707 intervalEndNumber;
708
709 if (*cursor == '-') {
710 cursor++;
711
712 if (debugMode) {
713 gLogOstream <<
714 "--> decipherNaturalNumbersSetSpecification after '-' : cursor = |" <<
715 *cursor <<
716 "|" <<
717 endl <<
718 endl;
719 }
720
721 intervalEndNumber =
722 consumeDecimalNumber (cursor, cursor, debugMode);
723 }
724
725 else {
726 intervalEndNumber = intervalStartNumber;
727 }
728
729 if (debugMode) {
730 gLogOstream <<
731 "--> decipherNaturalNumbersSetSpecification" <<
732 ", intervalStartNumber = " << intervalStartNumber <<
733 ", intervalEndNumber = " << intervalEndNumber <<
734 ": *cursor = |" << *cursor << "|" <<
735 endl;
736 }
737
738 for (int i = intervalStartNumber; i <= intervalEndNumber; i ++) {
739 if (negated) {
740 result.erase (i);
741 }
742 else {
743 result.insert (i);
744 }
745 } // for
746
747 if (*cursor != ',') {
748 if (debugMode) {
749 gLogOstream <<
750 "--> decipherNaturalNumbersSetSpecification, after non ',' : cursor = |" <<
751 *cursor <<
752 "|" <<
753 endl <<
754 endl;
755 }
756 break;
757 }
758
759 cursor++;
760
761 if (debugMode) {
762 gLogOstream <<
763 "--> decipherNaturalNumbersSetSpecification after ',' : cursor = |" <<
764 *cursor <<
765 "|"
766 << endl <<
767 endl;
768 }
769 } // while
770
771 if (* cursor != '\0') {
772 gLogOstream <<
773 "--> Extraneous characters |" << *cursor <<
774 "| in numbers spec" <<
775 endl << endl;
776 }
777 }
778
779 return result;
780 }
781
782 //______________________________________________________________________________
consumeString(string::const_iterator theStringIterator,string::const_iterator & remainingStringIterator,bool debugMode)783 string consumeString (
784 string::const_iterator theStringIterator,
785 string::const_iterator& remainingStringIterator,
786 bool debugMode)
787 {
788 string result;
789
790 /* JMI
791 string::const_iterator cursor = theStringIterator;
792
793 while ((*cursor) != ',') {
794 if (debugMode) {
795 gLogOstream <<
796 "--> consumeString: cursor = |" <<
797 *cursor <<
798 "|" <<
799 endl;
800 }
801
802 result += (*cursor);
803
804 if (++cursor == theString.end ()) break;
805 } // while
806
807 remainingStringIterator = cursor;
808
809 if (debugMode) {
810 gLogOstream <<
811 "--> consumeString: result = " << result <<
812 ", *remainingStringIterator = |" << *remainingStringIterator <<
813 "|" <<
814 endl;
815 }
816 */
817
818 return result;
819 }
820
821 //______________________________________________________________________________
decipherStringsSetSpecification(string theString,bool debugMode)822 std::set<string> decipherStringsSetSpecification (
823 string theString,
824 bool debugMode)
825 {
826 // A integersSetSpecification sample is: "FOO,159,haLLo"
827
828 set<string> result;
829
830 /* JMI
831 if (debugMode) {
832 gLogOstream <<
833 "--> decipherStringsSetSpecification, theString = |" << theString <<
834 "|" <<
835 endl;
836 }
837
838 string::const_iterator
839 cursor = theString.begin ();
840
841 while (1) {
842 if (debugMode) {
843 gLogOstream <<
844 "--> decipherStringsSetSpecification: cursor = |" <<
845 *cursor << "|" <<
846 endl;
847 }
848
849 string
850 currentString =
851 consumeString (cursor, theString.end (), debugMode);
852
853 if (debugMode) {
854 gLogOstream <<
855 "--> decipherStringsSetSpecification" <<
856 ", currentString = " << currentString <<
857 ": *cursor = |" << *cursor << "|" <<
858 endl;
859 }
860
861 result.insert (currentString);
862
863 if (*cursor != ',') {
864 if (debugMode) {
865 gLogOstream <<
866 "--> decipherStringsSetSpecification, after non ',' : cursor = |" <<
867 *cursor <<
868 "|" <<
869 endl <<
870 endl;
871 }
872 break;
873 }
874
875 if (++cursor == theString.end ()) break;
876
877 if (debugMode) {
878 gLogOstream <<
879 "--> decipherStringsSetSpecification after ',' : cursor = |" <<
880 *cursor <<
881 "|"
882 << endl <<
883 endl;
884 }
885 } // while
886
887 if (* cursor != '\0') {
888 gLogOstream <<
889 "--> Extraneous characters |" << *cursor <<
890 "| in numbers spec" <<
891 endl << endl;
892 }
893 */
894
895 return result;
896 }
897
898 //______________________________________________________________________________
extractNumbersFromString(string theString,bool debugMode)899 list<int> extractNumbersFromString (
900 string theString, // can contain "1, 2, 17"
901 bool debugMode)
902 {
903 list<int> foundNumbers;
904
905 if (debugMode) {
906 gLogOstream <<
907 "--> extractNumbersFromString, theString = |" << theString <<
908 "|" <<
909 endl;
910 }
911
912 if (theString.size ()) {
913 string::const_iterator
914 cursor = theString.begin ();
915
916 while (1) {
917 if (cursor == theString.end ())
918 break;
919
920 if (debugMode) {
921 gLogOstream <<
922 "--> extractNumbersFromString: cursor = |" <<
923 *cursor << "|" <<
924 endl;
925 }
926
927 if (isdigit (*cursor)) {
928 // consume a decimal number
929 int n = 0;
930 while (isdigit (*cursor)) {
931 n = n * 10 + (*cursor - '0');
932 cursor++;
933 } // while
934
935 // append the number to the list
936 foundNumbers.push_back (n);
937 }
938 else {
939 cursor++;
940 }
941 } // while
942 }
943
944 return foundNumbers;
945 }
946
947
948 //______________________________________________________________________________
extractNamesPairFromString(string theString,char separator,bool debugMode)949 pair<string, string> extractNamesPairFromString (
950 string theString, // can contain "P1 = Bassoon"
951 char separator,
952 bool debugMode)
953 {
954 string name1;
955 string name2;
956
957 if (debugMode) {
958 gLogOstream <<
959 "--> extractNamesPairFromString, theString = |" << theString <<
960 "|" <<
961 endl;
962 }
963
964 if (theString.size ()) {
965 string::const_iterator
966 cursor = theString.begin ();
967
968 // fetch name1
969 while (1) {
970 if (cursor == theString.end ())
971 break;
972
973 if (debugMode) {
974 gLogOstream <<
975 "--> extractNamesPairFromString: cursor = |" <<
976 *cursor << "|" <<
977 endl;
978 }
979
980 if ((*cursor) == separator) {
981 // found the separator
982 break;
983 }
984
985 // append the character to name1
986 name1 += *cursor;
987 cursor++;
988 } // while
989
990 name1 = trim (name1);
991 if (! name1.size ()) {
992 // found an empty name1
993 gLogOstream <<
994 "### ERROR: the first name before the " << separator <<
995 " separator is empty in '" << theString << "'" <<
996 endl;
997 }
998
999 if (cursor == theString.end ())
1000 gLogOstream <<
1001 "### ERROR: the " << separator <<
1002 " separator is missing in string '" <<
1003 theString << "'" <<
1004 endl;
1005 else
1006 // overtake the separator
1007 cursor++;
1008
1009 // fetch name2
1010 while (1) {
1011 if (cursor == theString.end ())
1012 break;
1013
1014 if (debugMode) {
1015 gLogOstream <<
1016 "--> extractNamesPairFromString: cursor = |" <<
1017 *cursor << "|" <<
1018 endl;
1019 }
1020
1021 if ((*cursor) == '=') {
1022 // found the separator
1023 gLogOstream <<
1024 "### ERROR: the " << separator <<
1025 " separator occurs more than once in string '" <<
1026 theString << "'" <<
1027 endl;
1028 break;
1029 }
1030
1031 // append the character to name2
1032 name2 += *cursor;
1033 cursor++;
1034 } // while
1035
1036 name2 = trim (name2);
1037 if (! name2.size ()) {
1038 // found an empty name2
1039 gLogOstream <<
1040 "### ERROR: the second name after the " << separator <<
1041 " separator is empty in '" << theString << "'" <<
1042 endl;
1043 }
1044 }
1045
1046 return make_pair (name1, name2);
1047 }
1048
1049 //______________________________________________________________________________
doubleQuoteStringIfNonAlpha(string theString)1050 string doubleQuoteStringIfNonAlpha (
1051 string theString)
1052 {
1053 string result;
1054
1055 bool stringShouldBeDoubleQuoted = false;
1056
1057 if (theString.size ()) {
1058 for (
1059 string::const_iterator i = theString.begin ();
1060 i != theString.end ();
1061 i++
1062 ) {
1063
1064 if (
1065 ((*i) >= 'a' && (*i) <= 'z')
1066 ||
1067 ((*i) >= 'A' && (*i) <= 'Z')) {
1068 // (*i) is a letter
1069 result += (*i);
1070 }
1071
1072 else {
1073 // (*i) is not a letter
1074 if ((*i) == ' ')
1075 result += ' '; // TEMP JMI
1076 else
1077 result += (*i);
1078
1079 stringShouldBeDoubleQuoted = true;
1080 }
1081 } // for
1082 }
1083
1084 if (stringShouldBeDoubleQuoted) {
1085 return "\"" + result + "\"";
1086 }
1087 else {
1088 return result;
1089 }
1090 }
1091
1092 //______________________________________________________________________________
quoteStringIfNonAlpha(string theString)1093 string quoteStringIfNonAlpha (
1094 string theString)
1095 {
1096 string result;
1097
1098 bool stringShouldBeQuoted = false;
1099
1100 if (theString.size ()) {
1101 for (
1102 string::const_iterator i = theString.begin ();
1103 i != theString.end ();
1104 i++
1105 ) {
1106
1107 if (
1108 ((*i) >= 'a' && (*i) <= 'z')
1109 ||
1110 ((*i) >= 'A' && (*i) <= 'Z')) {
1111 // (*i) is a letter
1112 result += (*i);
1113 }
1114
1115 else {
1116 // (*i) is not a letter
1117 if ((*i) == ' ')
1118 result += ' '; // TEMP JMI
1119 else
1120 result += (*i);
1121
1122 stringShouldBeQuoted = true;
1123 }
1124 } // for
1125 }
1126
1127 if (stringShouldBeQuoted) {
1128 return "'" + result + "'";
1129 }
1130 else {
1131 return result;
1132 }
1133 }
1134
1135 //______________________________________________________________________________
doubleQuoteString(string theString)1136 string doubleQuoteString (
1137 string theString)
1138 {
1139 string result;
1140
1141 if (theString.size ()) {
1142 for (
1143 string::const_iterator i = theString.begin ();
1144 i != theString.end ();
1145 i++
1146 ) {
1147
1148 if (
1149 ((*i) >= 'a' && (*i) <= 'z')
1150 ||
1151 ((*i) >= 'A' && (*i) <= 'Z')) {
1152 // (*i) is a letter
1153 result += (*i);
1154 }
1155
1156 else {
1157 // (*i) is not a letter
1158 if ((*i) == ' ') {
1159 result += ' '; // TEMP JMI
1160 }
1161 else if ((*i) == '"') {
1162 result += "\\\"";
1163 }
1164 else {
1165 result += (*i);
1166 }
1167 }
1168 } // for
1169 }
1170
1171 return "\"" + result + "\"";
1172 }
1173
1174 //______________________________________________________________________________
quoteString(string theString)1175 string quoteString (
1176 string theString)
1177 {
1178 string result;
1179
1180 if (theString.size ()) {
1181 for (
1182 string::const_iterator i = theString.begin ();
1183 i != theString.end ();
1184 i++
1185 ) {
1186
1187 if (
1188 ((*i) >= 'a' && (*i) <= 'z')
1189 ||
1190 ((*i) >= 'A' && (*i) <= 'Z')) {
1191 // (*i) is a letter
1192 result += (*i);
1193 }
1194
1195 else {
1196 // (*i) is not a letter
1197 if ((*i) == ' ') {
1198 result += ' '; // TEMP JMI
1199 }
1200 else if ((*i) == '\'') {
1201 result += "\\\'";
1202 }
1203 else {
1204 result += (*i);
1205 }
1206 }
1207 } // for
1208 }
1209
1210 return "'" + result + "'";
1211 }
1212
1213 //______________________________________________________________________________
booleanAsString(bool value)1214 string booleanAsString (bool value)
1215 {
1216 return
1217 string (
1218 value
1219 ? "true"
1220 : "false");
1221 }
1222
1223 //______________________________________________________________________________
singularOrPlural(int number,string singularName,string pluralName)1224 string singularOrPlural (
1225 int number, string singularName, string pluralName)
1226 {
1227 stringstream s;
1228
1229 s <<
1230 number << ' ';
1231
1232 if (number <= 1) {
1233 s <<
1234 singularName;
1235 }
1236 else {
1237 s <<
1238 pluralName;
1239 }
1240
1241 return s.str ();
1242 }
1243
singularOrPluralWithoutNumber(int number,string singularName,string pluralName)1244 string singularOrPluralWithoutNumber (
1245 int number, string singularName, string pluralName)
1246 {
1247 stringstream s;
1248
1249 if (number <= 1) {
1250 s <<
1251 singularName;
1252 }
1253 else {
1254 s <<
1255 pluralName;
1256 }
1257
1258 return s.str ();
1259 }
1260
1261 //______________________________________________________________________________
oahWarning(string warningMessage)1262 void oahWarning (string warningMessage)
1263 {
1264 gLogOstream <<
1265 "*** WARNING in the options and help: " <<
1266 warningMessage <<
1267 endl;
1268 }
1269
oahError(string errorMessage)1270 void oahError (string errorMessage)
1271 {
1272 gLogOstream <<
1273 "### ERROR in the options and help: " <<
1274 errorMessage <<
1275 endl;
1276
1277 exit (33);
1278 }
1279
1280 //______________________________________________________________________________
escapeDoubleQuotes(string s)1281 string escapeDoubleQuotes (string s)
1282 {
1283 string result;
1284
1285 for_each (
1286 s.begin (),
1287 s.end (),
1288 stringQuoteEscaper (result));
1289
1290 // replace occurrences of '\\"' by '\"',
1291 // in case there were already double quotes in string
1292 string
1293 lookedFor = "\\\\\"",
1294 ersatz = "\\\"";
1295
1296 for ( ; ; ) {
1297 size_t found = result.find (lookedFor);
1298
1299 if (found == string::npos)
1300 break;
1301
1302 result.replace (found, lookedFor.size (), ersatz);
1303 } // for
1304
1305 return result;
1306 }
1307
1308 //______________________________________________________________________________
convertHTMLEntitiesToPlainCharacters(string & s)1309 void convertHTMLEntitiesToPlainCharacters (string& s)
1310 {
1311 map<string, string> conversionMap;
1312
1313 conversionMap ["&"] = "&";
1314 conversionMap ["\""] = """;
1315 conversionMap ["'"] = "'";
1316 conversionMap ["<"] = "<";
1317 conversionMap [">"] = ">";
1318
1319 map<string, string>::const_iterator i;
1320
1321 for (i = conversionMap.begin (); i != conversionMap.end (); ++i) {
1322 string
1323 lookedFor = i->second,
1324 ersatz = i->first;
1325
1326 // replace all occurrences of lookedFor by ersatz
1327 for ( ; ; ) {
1328 size_t found = s.find (lookedFor);
1329
1330 if (found == string::npos)
1331 break;
1332
1333 s.replace (found, lookedFor.size (), ersatz);
1334 } // for
1335
1336 } // for
1337 }
1338
1339 //______________________________________________________________________________
splitStringIntoChunks(std::string theString,std::string theSeparator,std::list<std::string> & chunksList)1340 void splitStringIntoChunks (
1341 std::string theString,
1342 std::string theSeparator,
1343 std::list<std::string>& chunksList)
1344 {
1345 //#define DEBUG_SPLITTING
1346
1347 #ifdef DEBUG_SPLITTING
1348 gLogOstream <<
1349 "---> splitting |" << theString << "|" <<
1350 endl <<
1351 endl;
1352 #endif
1353
1354 int theStringSize = theString.size ();
1355
1356 size_t currentPosition = 0;
1357
1358 #ifdef DEBUG_SPLITTING
1359 string remainder = theString;
1360 #endif
1361
1362 int theSeparatorSize = theSeparator.size ();
1363
1364 map<string, string>::const_iterator i;
1365
1366 while (1) {
1367 size_t found =
1368 theString.find (theSeparator, currentPosition);
1369
1370 if (found == string::npos) {
1371 // fetch the last chunk
1372 // we have a last chunk
1373 // from currentPosition to theStringSize
1374 int chunkLength = theStringSize - currentPosition;
1375
1376 string
1377 chunk =
1378 theString.substr (
1379 currentPosition,
1380 chunkLength);
1381
1382 chunksList.push_back (
1383 chunk);
1384
1385 #ifdef DEBUG_SPLITTING
1386 gLogOstream <<
1387 "theStringSize = " << theStringSize <<
1388 endl <<
1389 "currentPosition = " << currentPosition <<
1390 endl <<
1391 "remainder = |" << remainder << "|" <<
1392 endl <<
1393 "chunkLength = " << chunkLength <<
1394 endl <<
1395 "chunk = \"" << chunk << "\"" <<
1396 endl <<
1397 endl;
1398 #endif
1399
1400 break;
1401 }
1402
1403 else {
1404 // we have a chunk from currentPosition to found
1405 int chunkLength = found - currentPosition;
1406
1407 string
1408 chunk =
1409 theString.substr (
1410 currentPosition,
1411 chunkLength);
1412
1413 // append it to the chunks list
1414 chunksList.push_back (
1415 chunk);
1416
1417 // advance the cursor
1418 currentPosition +=
1419 chunkLength + theSeparatorSize;
1420
1421 // there can be an end of line JMI
1422 if (theString [currentPosition] == '\n')
1423 currentPosition++;
1424
1425 #ifdef DEBUG_SPLITTING
1426 // set remainder
1427 remainder =
1428 theString.substr (
1429 currentPosition);
1430
1431 gLogOstream <<
1432 "theStringSize = " << theStringSize <<
1433 endl <<
1434 "currentPosition = " << currentPosition <<
1435 endl <<
1436 "remainder = |" << remainder << "|" <<
1437 endl <<
1438 "found = " << found <<
1439 endl <<
1440 "chunkLength = " << chunkLength <<
1441 endl <<
1442 "chunk = \"" << chunk << "\"" <<
1443 endl <<
1444 endl;
1445 #endif
1446 }
1447 } // while
1448 }
1449
1450 //______________________________________________________________________________
splitRegularStringAtEndOfLines(string theString,list<string> & chunksList)1451 void splitRegularStringAtEndOfLines (
1452 string theString,
1453 list<string>& chunksList)
1454 {
1455 //#define DEBUG_SPLITTING
1456
1457 #ifdef DEBUG_SPLITTING
1458 gLogOstream <<
1459 "---> splitting |" << theString << "|" <<
1460 endl <<
1461 endl;
1462 #endif
1463
1464 splitStringIntoChunks (
1465 theString,
1466 "\n",
1467 chunksList);
1468
1469 /* JMI
1470 int theStringSize = theString.size ();
1471
1472 size_t currentPosition = 0;
1473
1474 #ifdef DEBUG_SPLITTING
1475 string remainder = theString;
1476 #endif
1477
1478 string lookedFor = "\n";
1479 int lookedForSize = lookedFor.size ();
1480
1481 map<string, string>::const_iterator i;
1482
1483 while (1) {
1484 size_t found =
1485 theString.find (lookedFor, currentPosition);
1486
1487 if (found == string::npos) {
1488 // fetch the last chunk
1489 // we have a last chunk
1490 // from currentPosition to theStringSize
1491 int chunkLength = theStringSize - currentPosition;
1492
1493 string
1494 chunk =
1495 theString.substr (
1496 currentPosition,
1497 chunkLength);
1498
1499 chunksList.push_back (
1500 chunk);
1501
1502 #ifdef DEBUG_SPLITTING
1503 gLogOstream <<
1504 "theStringSize = " << theStringSize <<
1505 endl <<
1506 "currentPosition = " << currentPosition <<
1507 endl <<
1508 "remainder = |" << remainder << "|" <<
1509 endl <<
1510 "chunkLength = " << chunkLength <<
1511 endl <<
1512 "chunk = \"" << chunk << "\"" <<
1513 endl <<
1514 endl;
1515 #endif
1516
1517 break;
1518 }
1519
1520 else {
1521 // we have a chunk from currentPosition to found
1522 int chunkLength = found - currentPosition;
1523
1524 string
1525 chunk =
1526 theString.substr (
1527 currentPosition,
1528 chunkLength);
1529
1530 // append it to the chunks list
1531 chunksList.push_back (
1532 chunk);
1533
1534 // advance the cursor
1535 currentPosition +=
1536 chunkLength + lookedForSize;
1537
1538 // there can be an end of line JMI
1539 if (theString [currentPosition] == '\n')
1540 currentPosition++;
1541
1542 #ifdef DEBUG_SPLITTING
1543 // set remainder
1544 remainder =
1545 theString.substr (
1546 currentPosition);
1547
1548 gLogOstream <<
1549 "theStringSize = " << theStringSize <<
1550 endl <<
1551 "currentPosition = " << currentPosition <<
1552 endl <<
1553 "remainder = |" << remainder << "|" <<
1554 endl <<
1555 "found = " << found <<
1556 endl <<
1557 "chunkLength = " << chunkLength <<
1558 endl <<
1559 "chunk = \"" << chunk << "\"" <<
1560 endl <<
1561 endl;
1562 #endif
1563 }
1564 } // while
1565 */
1566 }
1567
1568 //______________________________________________________________________________
splitHTMLStringContainingEndOfLines(string theString,list<string> & chunksList)1569 void splitHTMLStringContainingEndOfLines (
1570 string theString,
1571 list<string>& chunksList)
1572 {
1573 //#define DEBUG_SPLITTING
1574
1575 #ifdef DEBUG_SPLITTING
1576 gLogOstream <<
1577 "---> splitting |" << theString << "|" <<
1578 endl <<
1579 endl;
1580 #endif
1581
1582 int theStringSize = theString.size ();
1583
1584 map<string, string> conversionMap; // JMI
1585
1586 conversionMap ["&"] = "&";
1587 conversionMap ["\""] = """;
1588 conversionMap ["'"] = "'";
1589 conversionMap ["<"] = "<";
1590 conversionMap [">"] = ">";
1591
1592 size_t currentPosition = 0;
1593
1594 #ifdef DEBUG_SPLITTING
1595 string remainder = theString;
1596 #endif
1597
1598 // JMI string lookedFor = "
";
1599 string lookedFor = "\n";
1600 int lookedForSize = lookedFor.size ();
1601
1602 map<string, string>::const_iterator i;
1603
1604 /*
1605 for (i = conversionMap.begin (); i != conversionMap.end (); ++i) {
1606 string
1607 lookedFor = i->second,
1608 ersatz = i->first;
1609 // replace all occurrences of lookedFor by ersatz
1610 } // for
1611 */
1612
1613 while (1) {
1614 size_t found =
1615 theString.find (lookedFor, currentPosition);
1616
1617 if (found == string::npos) {
1618 // fetch the last chunk
1619 // we have a last chunk
1620 // from currentPosition to theStringSize
1621 int chunkLength = theStringSize - currentPosition;
1622
1623 string
1624 chunk =
1625 theString.substr (
1626 currentPosition,
1627 chunkLength);
1628
1629 chunksList.push_back (
1630 chunk);
1631
1632 #ifdef DEBUG_SPLITTING
1633 gLogOstream <<
1634 "theStringSize = " << theStringSize <<
1635 endl <<
1636 "currentPosition = " << currentPosition <<
1637 endl <<
1638 "remainder = |" << remainder << "|" <<
1639 endl <<
1640 "chunkLength = " << chunkLength <<
1641 endl <<
1642 "chunk = \"" << chunk << "\"" <<
1643 endl <<
1644 endl;
1645 #endif
1646
1647 break;
1648 }
1649
1650 else {
1651 // we have a chunk from currentPosition to found
1652 int chunkLength = found - currentPosition;
1653
1654 string
1655 chunk =
1656 theString.substr (
1657 currentPosition,
1658 chunkLength);
1659
1660 // append it to the chunks list
1661 chunksList.push_back (
1662 chunk);
1663
1664 // advance the cursor
1665 currentPosition +=
1666 chunkLength + lookedForSize;
1667
1668 // there can be an end of line JMI
1669 if (theString [currentPosition] == '\n')
1670 currentPosition++;
1671
1672 #ifdef DEBUG_SPLITTING
1673 // set remainder
1674 remainder =
1675 theString.substr (
1676 currentPosition);
1677
1678 gLogOstream <<
1679 "theStringSize = " << theStringSize <<
1680 endl <<
1681 "currentPosition = " << currentPosition <<
1682 endl <<
1683 "remainder = |" << remainder << "|" <<
1684 endl <<
1685 "found = " << found <<
1686 endl <<
1687 "chunkLength = " << chunkLength <<
1688 endl <<
1689 "chunk = \"" << chunk << "\"" <<
1690 endl <<
1691 endl;
1692 #endif
1693 }
1694 } // while
1695 }
1696
1697 //______________________________________________________________________________
baseName(const string & filename)1698 string baseName (const string &filename)
1699 {
1700 if (! filename.size ()) {
1701 return {};
1702 }
1703
1704 auto len = filename.length ();
1705 auto index = filename.find_last_of ("/\\");
1706
1707 if (index == string::npos) {
1708 return filename;
1709 }
1710
1711 if (index + 1 >= len) {
1712 len--;
1713 index = filename.substr (0, len).find_last_of ("/\\");
1714
1715 if (len == 0) {
1716 return filename;
1717 }
1718
1719 if (index == 0) {
1720 return filename.substr (1, len - 1);
1721 }
1722
1723 if (index == string::npos) {
1724 return filename.substr (0, len);
1725 }
1726
1727 return filename.substr (index + 1, len - index - 1);
1728 }
1729
1730 return filename.substr (index + 1, len - index);
1731 }
1732
1733 //______________________________________________________________________________
makeSingleWordFromString(const string & theString)1734 string makeSingleWordFromString (const string& theString)
1735 {
1736 string result;
1737
1738 if (theString.size ()) {
1739 for (
1740 string::const_iterator i = theString.begin ();
1741 i != theString.end ();
1742 i++
1743 ) {
1744 if (isalnum (*i)) {
1745 result.push_back ((*i));
1746 }
1747 } // for
1748 }
1749
1750 return result;
1751 }
1752
1753
1754 }
1755
1756 /* JMI
1757 //______________________________________________________________________________
1758 class EXP segmentedLinesOstream
1759 {
1760 / * JMI NOT DONE
1761 // in order to avoid spaces at the end of a line,
1762 // an end of segment causes a space to be output later,
1763 // by the next '<<' operator
1764
1765 --
1766 *
1767 Reference for this class:
1768 https://stackoverflow.com/questions/2212776/overload-handling-of-stdendl
1769
1770 Usage:
1771 segmentedLinesOstream myStream (std::cout);
1772
1773 myStream <<
1774 1 << 2 << 3 << std::endl <<
1775 5 << 6 << std::endl <<
1776 7 << 8 << std::endl;
1777 * /
1778
1779 private:
1780 // segmentedLinesOstream just uses an indentedOstream
1781 indentedOstream& fIndentedOstream;
1782
1783 // an end of segment causes a space to be output by the next '<<' operator
1784 bool fAtEndOfSegment;
1785
1786 public:
1787
1788 // constructor
1789 segmentedLinesOstream (
1790 indentedOstream& indentedOstream)
1791 : fIndentedOstream (indentedOstream)
1792 { fAtEndOfSegment = false; }
1793
1794 // destructor
1795 virtual ~segmentedLinesOstream ()
1796 {};
1797
1798 // flush
1799 void flush ()
1800 { fIndentedOstream.flush (); }
1801
1802 // set and get
1803 indentedOstream& getIndentedOstream ()
1804 { return fIndentedOstream; }
1805
1806 // indentation
1807 indenter& getIndenter ()
1808 { return fIndentedOstream.getIndenter (); }
1809
1810 void incrIdentation ()
1811 { fIndentedOstream.incrIdentation (); }
1812
1813 void decrIdentation ()
1814 { fIndentedOstream.decrIdentation (); }
1815
1816 // segments
1817 void setAtEndOfSegment (bool value)
1818 { fAtEndOfSegment = value; }
1819 bool getAtEndOfSegment ()
1820 { return fAtEndOfSegment; }
1821 };
1822
1823 // '<<' operators to implement segments
1824 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, char ch);
1825 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, int i);
1826 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, unsigned int i);
1827 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, float f);
1828 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, const std::string& str);
1829 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, char * str);
1830
1831 // the manipulators
1832 segmentedLinesOstream& endline (segmentedLinesOstream& os);
1833 segmentedLinesOstream& endseg (segmentedLinesOstream& os);
1834 */
1835
1836
1837 /* JMI
1838 segmentedLinesOstream
1839 testSegmentedLinesOstream (fLogOutputStream);
1840
1841 fLogOutputStream <<
1842 "getAtEndOfSegment: " <<
1843 booleanAsString (
1844 testSegmentedLinesOstream.getAtEndOfSegment ()) <<
1845 endl;
1846
1847 testSegmentedLinesOstream.setAtEndOfSegment (true);
1848
1849 fLogOutputStream <<
1850 "getAtEndOfSegment: " <<
1851 booleanAsString (
1852 testSegmentedLinesOstream.getAtEndOfSegment ()) <<
1853 endl;
1854
1855 testSegmentedLinesOstream <<
1856 "FOO" << endl; // <<
1857 // endline;
1858
1859 testSegmentedLinesOstream.getIndentedOstream () << flush;
1860 */
1861
1862
1863 /* JMI
1864 //______________________________________________________________________________
1865 // the manipulators
1866 segmentedLinesOstream& endline (segmentedLinesOstream& os)
1867 {
1868 if (! os.getAtEndOfSegment ()) {
1869 // don't output multiple spaces after a segment
1870 os.setAtEndOfSegment (true);
1871 }
1872
1873 os.getIndentedOstream () << endl;
1874
1875 return os;
1876 }
1877
1878 segmentedLinesOstream& endseg (segmentedLinesOstream& os)
1879 {
1880 if (! os.getAtEndOfSegment ()) {
1881 // don't output multiple spaces after a segment
1882 os.setAtEndOfSegment (true);
1883 }
1884
1885 return os;
1886 }
1887
1888 // '<<' operators to implement segments
1889 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, char ch)
1890 {
1891 if (os.getAtEndOfSegment ()) {
1892 os << ' ';
1893 os.setAtEndOfSegment (false);
1894 }
1895
1896 os.getIndentedOstream () << ch;
1897
1898 return os;
1899 }
1900
1901 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, int i)
1902 {
1903 if (os.getAtEndOfSegment ()) {
1904 os << ' ';
1905 os.setAtEndOfSegment (false);
1906 }
1907
1908 os.getIndentedOstream () << i;
1909
1910 return os;
1911 }
1912
1913 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, unsigned int i)
1914 {
1915 if (os.getAtEndOfSegment ()) {
1916 os << ' ';
1917 os.setAtEndOfSegment (false);
1918 }
1919
1920 os.getIndentedOstream () << i;
1921
1922 return os;
1923 }
1924
1925 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, float f)
1926 {
1927 if (os.getAtEndOfSegment ()) {
1928 os << ' ';
1929 os.setAtEndOfSegment (false);
1930 }
1931
1932 os.getIndentedOstream () << f;
1933
1934 return os;
1935 }
1936
1937 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, const string& str)
1938 {
1939 if (os.getAtEndOfSegment ()) {
1940 os << ' ';
1941 os.setAtEndOfSegment (false);
1942 }
1943
1944 os.getIndentedOstream () << str;
1945
1946 return os;
1947 }
1948
1949 EXP segmentedLinesOstream& operator<< (segmentedLinesOstream& os, char * str)
1950 {
1951 if (os.getAtEndOfSegment ()) {
1952 os << ' ';
1953 os.setAtEndOfSegment (false);
1954 }
1955
1956 os.getIndentedOstream () << str;
1957
1958 return os;
1959 }
1960 */
1961
1962