History

the only constant is change.

Ge Wang committed 9 years ago

Commit 009ac191 parent b1e2669181 files · +0 −3911Browse files

Showing the changes to src/core/util_string.cpp (1 of 181 files). Show all

Unified · Split

src/core/util_string.cpp+569−0
@@ -0,0 +1,569 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
9+ This program is free software; you can redistribute it and/or modify
10+ it under the terms of the GNU General Public License as published by
11+ the Free Software Foundation; either version 2 of the License, or
12+ (at your option) any later version.
13+
14+ This program is distributed in the hope that it will be useful,
15+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+ GNU General Public License for more details.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// name: util_string.cpp
27+// desc: string functions utility
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// Spencer Salazar (spencer@ccrma.stanford.edu)
31+// date: Summer 2005
32+//-----------------------------------------------------------------------------
33+#include "util_string.h"
34+#include "chuck_errmsg.h"
35+
36+#ifdef __PLATFORM_WIN32__
37+#include <Windows.h>
38+#endif // __PLATFORM_WIN32__
39+
40+#ifdef __PLATFORM_LINUX__
41+#include <linux/limits.h>
42+#endif // __PLATFORM_LINUX__
43+
44+#include <stdio.h>
45+using namespace std;
46+
47+
48+
49+//-----------------------------------------------------------------------------
50+// name: itoa()
51+// desc: ...
52+//-----------------------------------------------------------------------------
53+string itoa( t_CKINT val )
54+{
55+ char buffer[128];
56+ sprintf( buffer, "%li", val );
57+ return string(buffer);
58+}
59+
60+
61+
62+//-----------------------------------------------------------------------------
63+// name: ftoa()
64+// desc: ...
65+//-----------------------------------------------------------------------------
66+string ftoa( t_CKFLOAT val, t_CKUINT precision )
67+{
68+ char str[32];
69+ char buffer[128];
70+ if( precision > 32 ) precision = 32;
71+ sprintf( str, "%%.%lif", precision );
72+ sprintf( buffer, str, val );
73+ return string(buffer);
74+}
75+
76+
77+
78+
79+//-----------------------------------------------------------------------------
80+// name: tolower()
81+// desc: ...
82+//-----------------------------------------------------------------------------
83+string tolower( const string & str )
84+{
85+ string s = str;
86+ t_CKUINT len = s.length();
87+
88+ // loop
89+ for( t_CKUINT i = 0; i < len; i++ )
90+ if( s[i] >= 'A' && s[i] <= 'Z' )
91+ s[i] += 32;
92+
93+ return s;
94+}
95+
96+
97+
98+
99+//-----------------------------------------------------------------------------
100+// name: toupper()
101+// desc: ...
102+//-----------------------------------------------------------------------------
103+string toupper( const string & str )
104+{
105+ string s = str;
106+ t_CKUINT len = s.length();
107+
108+ // loop
109+ for( t_CKUINT i = 0; i < len; i++ )
110+ if( s[i] >= 'a' && s[i] <= 'z' )
111+ s[i] -= 32;
112+
113+ return s;
114+}
115+
116+
117+
118+
119+//-----------------------------------------------------------------------------
120+// name: trim()
121+// desc: ...
122+//-----------------------------------------------------------------------------
123+string trim( const string & val )
124+{
125+ // two ends
126+ t_CKINT start = 0;
127+ t_CKINT end = val.length() - 1;
128+
129+ // left trim
130+ for( start = 0; start < end; start++ )
131+ {
132+ // non-white space
133+ if( val[start] != ' ' && val[start] != '\t' )
134+ break;
135+ }
136+
137+ // if start > end, then all white space
138+ if( start > end ) return "";
139+
140+ // right trim
141+ for( ; end >= start; end-- )
142+ {
143+ // non-white space
144+ if( val[end] != ' ' && val[end] != '\t' )
145+ break;
146+ }
147+
148+ // cannot be
149+ assert( end >= start );
150+
151+ // return
152+ return val.substr( start, end - start + 1 );
153+}
154+
155+
156+
157+//-----------------------------------------------------------------------------
158+// name: ltrim()
159+// desc: ...
160+//-----------------------------------------------------------------------------
161+string ltrim( const string & val )
162+{
163+ // two ends
164+ t_CKINT start = 0;
165+ t_CKINT end = val.length() - 1;
166+
167+ // left trim
168+ for( start = 0; start < end; start++ )
169+ {
170+ // non-white space
171+ if( val[start] != ' ' && val[start] != '\t' )
172+ break;
173+ }
174+
175+ // if start > end, then all white space
176+ if( start > end ) return "";
177+
178+ // return
179+ return val.substr( start, end - start + 1 );
180+}
181+
182+
183+
184+
185+//-----------------------------------------------------------------------------
186+// name: rtrim()
187+// desc: ...
188+//-----------------------------------------------------------------------------
189+string rtrim( const string & val )
190+{
191+ // two ends
192+ t_CKINT start = 0;
193+ t_CKINT end = val.length() - 1;
194+
195+ // right trim
196+ for( ; end >= start; end-- )
197+ {
198+ // non-white space
199+ if( val[end] != ' ' && val[end] != '\t' )
200+ break;
201+ }
202+
203+ // if end < start, then all white space
204+ if( end < start ) return "";
205+
206+ // return
207+ return val.substr( start, end - start + 1 );
208+}
209+
210+
211+
212+
213+//-----------------------------------------------------------------------------
214+// name: extract_args()
215+// desc: extract argument from format filename:arg1:arg2:etc
216+//-----------------------------------------------------------------------------
217+t_CKBOOL extract_args( const string & token,
218+ string & filename, vector<string> & args )
219+{
220+ // clear vector
221+ args.clear();
222+ // clear filename
223+ filename = "";
224+
225+ // last : found pos
226+ t_CKINT prev_pos = 0;
227+ // curr : pos
228+ t_CKINT i = 0;
229+
230+ string tmp;
231+
232+ // copy and trim
233+ string s = trim( token );
234+
235+ // ignore second character as arg separator if its : on Windows
236+ t_CKBOOL ignoreSecond = FALSE;
237+#ifdef __PLATFORM_WIN32__
238+ ignoreSecond = TRUE;
239+#endif // __PLATFORM_WIN32__
240+
241+ // detect
242+ t_CKBOOL scan = FALSE;
243+ t_CKBOOL ret = TRUE;
244+ t_CKBOOL ignoreNext = FALSE;
245+ char * mask = NULL;
246+ for( i = 0; i < s.length(); i++ )
247+ if( s[i] == '\\' )
248+ {
249+ scan = TRUE;
250+ break;
251+ }
252+
253+ // mad...
254+ if( scan )
255+ {
256+ mask = new char[s.length()];
257+ // zero
258+ memset(mask, 0, s.length()*sizeof(char));
259+
260+ // loop through
261+ for( i = 0; i < s.length(); i++ )
262+ {
263+ // escape (tom and ge fixed this, which used to look for \\ then : and randomly incremented i)
264+ // added '/' 1.3.1.1
265+ // if( s[i] == ':' && (i+1) < s.length() && ( s[i+1] == '\\' || s[i+1] == '/' ) )
266+ // {
267+ // mask[i] = 1;
268+ // break; // added 1.3.1.1
269+ // }
270+
271+ // 1.3.2.0: spencer and ge fixed this, requiring \ to escape :
272+ if( s[i] == '\\' && (i+1) < s.length() )
273+ {
274+ // check next char
275+ if( s[i+1] == ':' || s[i+1] == '\\' )
276+ {
277+ // add
278+ mask[i] = 1;
279+ // skip next character
280+ i++;
281+ }
282+ else
283+ {
284+ // error: recognized escape target
285+ CK_FPRINTF_STDERR( "[chuck]: unrecognized escape sequence: \\%c", s[i+1] );
286+ // return false
287+ ret = FALSE;
288+ // go clean
289+ goto done;
290+ }
291+ }
292+ }
293+ }
294+
295+ // loop through
296+ for( i = 0; i < s.length(); i++ )
297+ {
298+ // check mask
299+ if( mask && mask[i] )
300+ {
301+ //CK_FPRINTF_STDERR( "skipping %c\n", s[i] );
302+ // mark the next as false
303+ ignoreNext = TRUE;
304+ // skip this one
305+ continue;
306+ }
307+
308+ // look for :
309+ if( !ignoreNext && s[i] == ':' && !(ignoreSecond && i == 1))
310+ {
311+ // sanity
312+ if( i == 0 )
313+ {
314+ ret = FALSE;
315+ goto done;
316+ }
317+
318+ // copy
319+ if( filename == "" )
320+ filename = tmp;
321+ else
322+ args.push_back( tmp );
323+
324+ tmp = "";
325+
326+ // update
327+ prev_pos = i + 1;
328+ }
329+ else
330+ {
331+ tmp.append(1, s[i]);
332+ }
333+
334+ // reset
335+ ignoreNext = FALSE;
336+ }
337+
338+ // get the remainder, if any
339+ if( tmp.length() )
340+ {
341+ // copy
342+ if( filename == "" )
343+ filename = tmp;
344+ else
345+ args.push_back( tmp );
346+ }
347+
348+ // testing code - spencer 1.3.2.0
349+// CK_FPRINTF_STDERR( "INPUT: %s\n", token.c_str() );
350+// CK_FPRINTF_STDERR( "FILENAME: %s\n", filename.c_str() );
351+// for(i = 0; i < args.size(); i++)
352+// CK_FPRINTF_STDERR( "ARG: %s\n", args[i].c_str() );
353+
354+done:
355+ // reclaim
356+ SAFE_DELETE_ARRAY( mask );
357+
358+ return ret;
359+}
360+
361+
362+/* from http://developer.apple.com/library/mac/#qa/qa1549/_index.html */
363+
364+#ifndef __PLATFORM_WIN32__
365+
366+#include <glob.h>
367+
368+char* CreatePathByExpandingTildePath(const char* path)
369+{
370+ glob_t globbuf;
371+ char **v;
372+ char *expandedPath = NULL, *result = NULL;
373+
374+ assert(path != NULL);
375+
376+ if (glob(path, GLOB_TILDE, NULL, &globbuf) == 0) //success
377+ {
378+ v = globbuf.gl_pathv; //list of matched pathnames
379+ expandedPath = v[0]; //number of matched pathnames, gl_pathc == 1
380+
381+ result = (char*)calloc(1, strlen(expandedPath) + 1); //the extra char is for the null-termination
382+ if(result)
383+ strncpy(result, expandedPath, strlen(expandedPath) + 1); //copy the null-termination as well
384+
385+ globfree(&globbuf);
386+ }
387+
388+ return result;
389+}
390+
391+#endif // __PLATFORM_WIN32__
392+
393+
394+// get full path to file
395+std::string get_full_path( const std::string & fp )
396+{
397+#ifndef __PLATFORM_WIN32__
398+
399+ char buf[PATH_MAX];
400+
401+ char * result = realpath(fp.c_str(), buf);
402+
403+ // try with .ck extension
404+ if(result == NULL && !str_endsin(fp.c_str(), ".ck"))
405+ result = realpath((fp + ".ck").c_str(), buf);
406+
407+ if(result == NULL)
408+ return fp;
409+ else
410+ return buf;
411+
412+#else //
413+
414+ char buf[MAX_PATH];
415+
416+ DWORD result = GetFullPathName(fp.c_str(), MAX_PATH, buf, NULL);
417+
418+ // try with .ck extension
419+ if(result == 0 && !str_endsin(fp.c_str(), ".ck"))
420+ result = GetFullPathName((fp + ".ck").c_str(), MAX_PATH, buf, NULL);
421+
422+ if(result == 0)
423+ return fp;
424+ else
425+ return normalize_directory_separator(buf);
426+
427+#endif // __PLATFORM_WIN32__
428+}
429+
430+
431+std::string expand_filepath( std::string & fp )
432+{
433+#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)
434+ // no expansion in Windows systems
435+ return fp;
436+#else
437+
438+ char * expanded_cstr = CreatePathByExpandingTildePath( fp.c_str() );
439+
440+ if(expanded_cstr == NULL)
441+ return fp;
442+
443+ std::string expanded_stdstr = expanded_cstr;
444+
445+ free(expanded_cstr);
446+
447+ return expanded_stdstr;
448+
449+#endif
450+}
451+
452+
453+std::string extract_filepath_dir(std::string &filepath)
454+{
455+ char path_separator = '/';
456+
457+//#ifdef __WINDOWS_DS__
458+// path_separator = '\\';
459+//#else
460+// path_separator = '/';
461+//#endif
462+
463+ // if the last character is a slash, skip it
464+ int i = filepath.rfind(path_separator);
465+
466+ if(i == std::string::npos)
467+ return std::string();
468+
469+ // skip any/all extra trailing slashes
470+ while( i > 0 && filepath[i-1] == path_separator )
471+ i--;
472+
473+ // change spencer 2014-7-17: include trailing slash
474+ return std::string(filepath, 0, i+1);
475+}
476+
477+// added: ge 1.3.2.0
478+string dir_go_up( const string & dir, t_CKINT numUp )
479+{
480+ // separator
481+ char path_separator = '/';
482+
483+ // sanity check
484+ if( numUp < 0 ) numUp = -numUp;
485+
486+ // pos
487+ size_t pos = dir.length();
488+
489+ // skip any trailing slashes
490+ while( pos > 0 && dir[pos-1] == path_separator )
491+ pos--;
492+
493+ // loop
494+ while( numUp > 0 )
495+ {
496+ // find the last slash
497+ pos = dir.rfind( path_separator, pos-1 );
498+ // skip any extra slashes
499+ while( pos > 0 && dir[pos-1] == path_separator )
500+ pos--;
501+
502+ // not there
503+ if( pos == string::npos )
504+ return "";
505+ else if( pos == 0 )
506+ return "/";
507+
508+ // TODO: what about windows?
509+ // TODO: what about windows network: with two backslashes? "\\\\"
510+
511+ // decrement
512+ numUp--;
513+ }
514+
515+
516+ // otherwise
517+ // change spencer 2014-7-17: include trailing slash
518+ string str = string( dir, 0, pos );
519+ if( str[str.length()-1] != '/' ) str = str + "/";
520+ return str;
521+}
522+
523+//-----------------------------------------------------------------------------
524+// name: parse_path_list()
525+// desc: split "x:y:z"-style path list into {"x","y","z"}
526+//-----------------------------------------------------------------------------
527+void parse_path_list( std::string & str, std::list<std::string> & lst )
528+{
529+#if defined(__PLATFORM_WIN32__)
530+ const char separator = ';';
531+#else
532+ const char separator = ':';
533+#endif
534+ std::string::size_type i = 0, last = 0;
535+ while( last < str.size() &&
536+ ( i = str.find( separator, last ) ) != std::string::npos )
537+ {
538+ lst.push_back( str.substr( last, i - last ) );
539+ last = i + 1;
540+ }
541+
542+ lst.push_back( str.substr( last, str.size() - last ) );
543+}
544+
545+
546+
547+std::string normalize_directory_separator(const std::string &filepath)
548+{
549+#ifdef __PLATFORM_WIN32__
550+ std::string new_filepath = filepath;
551+ int len = new_filepath.size();
552+ for(int i = 0; i < len; i++)
553+ {
554+ if(new_filepath[i] == '\\') new_filepath[i] = '/';
555+ }
556+
557+ return new_filepath;
558+#else
559+ return std::string(filepath);
560+#endif // __PLATFORM_WIN32__
561+}
562+
563+int str_endsin(const char *str, const char *end)
564+{
565+ size_t len = strlen(str);
566+ size_t endlen = strlen(end);
567+
568+ return strncmp(str+(len-endlen), end, endlen) == 0;
569+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t