1 /*
2     FormatFuncs.h
3 
4     Copyright 2010, Alan Calvert
5     Copyright 2014-2021, Will Godfrey and others.
6 
7     This file is part of yoshimi, which is free software: you can
8     redistribute it and/or modify it under the terms of the GNU General
9     Public License as published by the Free Software Foundation, either
10     version 2 of the License, or (at your option) any later version.
11 
12     yoshimi is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with yoshimi.  If not, see <http://www.gnu.org/licenses/>.
19 
20 */
21 
22 #ifndef FORMATFUNCS_H
23 #define FORMATFUNCS_H
24 
25 #include <cmath>
26 #include <string>
27 #include <sstream>
28 #include <cstring>
29 #include <list>
30 
31 namespace func {
32 
33 inline std::string asString(int n)
34 {
35    std::ostringstream oss;
36    oss << n;
37    return std::string(oss.str());
38 }
39 
40 
41 inline std::string asString(long long n)
42 {
43    std::ostringstream oss;
44    oss << n;
45    return std::string(oss.str());
46 }
47 
48 
49 inline std::string asString(unsigned long n)
50 {
51     std::ostringstream oss;
52     oss << n;
53     return std::string(oss.str());
54 }
55 
56 
57 inline std::string asString(long n)
58 {
59    std::ostringstream oss;
60    oss << n;
61    return std::string(oss.str());
62 }
63 
64 
65 inline std::string asString(unsigned int n)
66 {
67    std::ostringstream oss;
68    oss << n;
69    return std::string(oss.str());
70 }
71 
72 
73 inline std::string asString(unsigned int n, unsigned int width)
74 {
75     std::ostringstream oss;
76     oss << n;
77     std::string val = std::string(oss.str());
78     if (width && val.size() < width)
79     {
80         val = std::string("000000000") + val;
81         return val.substr(val.size() - width);
82     }
83     return val;
84 }
85 
86 
87 inline std::string asString(unsigned char c)
88 {
89     std::ostringstream oss;
90     oss.width(1);
91     oss << c;
92     return oss.str();
93 }
94 
95 
96 inline std::string asString(float n)
97 {
98    std::ostringstream oss;
99    oss.precision(3);
100    oss.width(3);
101    oss << n;
102    return oss.str();
103 }
104 
105 
106 inline std::string asLongString(float n)
107 {
108    std::ostringstream oss;
109    oss.precision(9);
110    oss.width(9);
111    oss << n;
112    return oss.str();
113 }
114 
115 
116 inline std::string asCompactString(float n)
117 {
118    std::ostringstream oss;
119    oss.setf(std::ios_base::fixed, std::ios_base::floatfield);
120    oss.precision(1);
121    oss.width(1);
122    oss << n;
123    return oss.str();
124 }
125 
126 
127 inline std::string asHexString(int x)
128 {
129    std::ostringstream oss;
130    oss << std::hex << x;
131    std::string res = std::string(oss.str());
132    if (res.length() & 1)
133        return "0"+res;
134    return res;
135 }
136 
137 
138 inline std::string asHexString(unsigned int x)
139 {
140    std::ostringstream oss;
141    oss << std::hex << x;
142    std::string res = std::string(oss.str());
143    if (res.length() & 1)
144        return "0"+res;
145    return res;
146 }
147 
148 
149 inline std::string asMidiNoteString(unsigned char n)
150 {
151     static std::string note[] = {
152         "C","C#","D","D#","E","F","F#","G","G#","A","B","B#"
153     };
154     int octave = -1 + n/12;
155     int key   = n % 12;
156     return "("+note[key]+asString(octave)+")";
157 }
158 
159 
160 
161 inline float string2float(std::string str)
162 {
163     std::istringstream machine(str);
164     float fval;
165     machine >> fval;
166     return fval;
167 }
168 
169 
170 inline double string2double(std::string str)
171 {
172     std::istringstream machine(str);
173     double dval;
174     machine >> dval;
175     return dval;
176 }
177 
178 
179 inline bool isDigits(std::string str)
180 {
181     if (str.empty())
182         return false;
183     char c = str.at(0);
184     if (c < '0' or c > '9')
185         return false;
186     return true;
187 }
188 
189 inline int string2int(std::string str)
190 {
191     std::istringstream machine(str);
192     int intval;
193     machine >> intval;
194     return intval;
195 }
196 
197 inline int string2long(std::string str)
198 {
199     std::istringstream machine(str);
200     long longval;
201     machine >> longval;
202     return longval;
203 }
204 
205 
206 /* ensures MIDI compatible numbers without errors */
207 inline int string2int127(std::string str)
208 {
209     std::istringstream machine(str);
210     int intval;
211     machine >> intval;
212     if (intval < 0)
213         intval = 0;
214     else if (intval > 127)
215         intval = 127;
216     return intval;
217 }
218 
219 
220 inline unsigned int string2uint(std::string str)
221 {
222     std::istringstream machine(str);
223     unsigned int intval;
224     machine >> intval;
225     return intval;
226 }
227 
228 /*
229  * turns the 1st count mumber to upper case
230  * all the rest to lower case
231  */
232 inline std::string stringCaps(std::string str, int count)
233 {
234     int idx = 0;
235     char c;
236     while (str[idx])
237     {
238         c = str[idx];
239         if (idx < count)
240             str.replace(idx, 1, 1, toupper(c));
241         else
242             str.replace(idx, 1, 1, tolower(c));
243         idx ++;
244     }
245     return str;
246 }
247 
248 
249 /* this is not actually a file operation so we keep it here */
250 inline int findSplitPoint(std::string name)
251 {
252     unsigned int chk = 0;
253     char ch = name.at(chk);
254     unsigned int len =  name.length() - 1;
255     while (ch >= '0' and ch <= '9' and chk < len)
256     {
257         chk += 1;
258         ch = name.at(chk);
259     }
260     if (chk >= len)
261         return 0;
262     if (ch != '-')
263         return 0;
264     return chk;
265 }
266 
267 /*
268  * This is principally used to format strings for the GUI
269  * where they are fitted into windows with limited width.
270  * However, it may be useful elsewhere.
271  */
272 inline std::string formatTextLines(std::string text, size_t maxLen)
273 {
274     size_t totalLen = text.length();
275     if (totalLen < maxLen)
276         return text;
277     size_t pos = 0;
278     size_t ref = 0;
279     while (pos < totalLen) // split overlong words first
280     {
281         if (text.at(pos) < '!')
282         {
283             ++ pos;
284             ref = pos;
285         }
286         if ((pos - ref) > maxLen)
287         {
288             text.insert(pos, 1, '\n');
289             ++ totalLen;
290             ++ pos;
291             ref = pos;
292         }
293         ++pos;
294     }
295 
296     pos = 0;
297     ref = 0;
298     size_t lastSpace = 0;
299     while (pos < text.length())
300     {
301         if (text.at(pos) == '\n') // skip over existing line ends
302         {
303             ++ pos;
304             ref = pos;
305             lastSpace = 0;
306         }
307         else if (text.at(pos) == ' ')
308             lastSpace = pos;
309         if ((pos - ref) >= maxLen)
310         {
311             if (lastSpace == 0)
312                 pos = text.length();
313             else
314             {
315                 text.at(lastSpace)= '\n';
316                 ref = lastSpace;
317                 lastSpace = 0;
318             }
319         }
320         ++ pos;
321     }
322     while (text.at(text.length() - 1) < '!') // tidy up
323         text.pop_back();
324     return text;
325 }
326 
327 
328 inline std::string nextLine(std::string& list) // this is destructive
329 { // currently only used in main
330     size_t pos = list.find('\n');
331     std::string line = "";
332     if (pos == std::string::npos)
333     {
334         line = list;
335         list = "";
336     }
337     else
338     {
339         line = list.substr(0, pos);
340         ++pos;
341         if (pos > list.size())
342             list = "";
343         else
344             list = list.substr(pos);
345     }
346     return line;
347 }
348 
349 }//(End)namespace func
350 #endif /*FORMATFUNCS_H*/
351