File indexing completed on 2026-04-09 07:49:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <cstdio>
0021 #include <cassert>
0022 #include <cstdlib>
0023 #include <cstring>
0024 #include <csignal>
0025 #include <sstream>
0026 #include <fstream>
0027 #include <iostream>
0028 #include <algorithm>
0029
0030 #include <glm/glm.hpp>
0031
0032
0033 #include "SStr.hh"
0034 #include "SPath.hh"
0035 #include "spath.h"
0036 #include "SLOG.hh"
0037
0038
0039 const plog::Severity SStr::LEVEL = SLOG::EnvLevel("SStr", "DEBUG");
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 void SStr::Save(const char* path_, const std::vector<std::string>& a, char delim )
0064 {
0065 bool in_pwd = strchr(path_, '/' ) == nullptr ;
0066 int create_dirs = in_pwd ? NOOP : FILEPATH ;
0067 const char* path = SPath::Resolve(path_, create_dirs);
0068 LOG(info) << "SPath::Resolve " << path_ << " to " << path ;
0069 std::ofstream fp(path);
0070 for(std::vector<std::string>::const_iterator i = a.begin(); i != a.end(); ++i) fp << *i << delim ;
0071 }
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 void SStr::Save(const char* path_, const char* txt )
0086 {
0087 bool in_pwd = strchr(path_, '/' ) == nullptr ;
0088 int create_dirs = in_pwd ? NOOP : FILEPATH ;
0089
0090 const char* path = SPath::Resolve(path_, create_dirs );
0091 LOG(LEVEL) << "SPath::Resolve " << path_ << " to " << path << " create_dirs " << create_dirs << " in_pwd " << in_pwd ;
0092 std::ofstream fp(path);
0093 fp << txt ;
0094 }
0095
0096 const char* SStr::Load(const char* path_ )
0097 {
0098 int create_dirs = 0 ;
0099 const char* path = SPath::Resolve(path_, create_dirs);
0100 LOG(LEVEL) << "SPath::Resolve " << path_ << " to " << path ;
0101 std::ifstream fp(path);
0102
0103 std::stringstream ss ;
0104 ss << fp.rdbuf() ;
0105 std::string txt = ss.str();
0106 return strdup(txt.c_str()) ;
0107 }
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 void SStr::LoadList(const char* arg, std::vector<std::string>& lines, char delim )
0119 {
0120 if(arg == nullptr) return ;
0121
0122 if(spath::LooksLikePath(arg) && delim == '\n' )
0123 {
0124 std::ifstream ifs(arg);
0125 std::string line;
0126 while(std::getline(ifs, line)) lines.push_back(line) ;
0127 }
0128 else if( delim == ',' )
0129 {
0130 SStr::Split( arg, delim, lines );
0131 LOG(LEVEL) << "split " << arg << " into " << lines.size() ;
0132 }
0133 else
0134 {
0135 lines.push_back(arg);
0136 }
0137 }
0138
0139 std::vector<std::string>* SStr::LoadList( const char* arg, char delim )
0140 {
0141 if(arg == nullptr) return nullptr ;
0142 typedef std::vector<std::string> VS ;
0143 VS* lines = new VS ;
0144 LoadList(arg, *lines, delim );
0145 return lines ;
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 void SStr::FillFromULL( char* dest, unsigned long long value, char unprintable)
0157 {
0158 dest[8] = '\0' ;
0159 for( ULL w=0 ; w < 8 ; w++)
0160 {
0161 ULL ullc = (value & (0xffull << w*8)) >> w*8 ;
0162 char c = static_cast<char>(ullc) ;
0163 bool printable = c >= ' ' && c <= '~' ;
0164 dest[w] = printable ? c : unprintable ;
0165 }
0166 }
0167
0168 const char* SStr::FromULL( unsigned long long value, char unprintable)
0169 {
0170 assert( sizeof(ULL) == 8 );
0171 char* s = new char[8+1] ;
0172 FillFromULL(s, value, unprintable) ;
0173 return s ;
0174 }
0175
0176
0177 unsigned long long SStr::ToULL( const char* s )
0178 {
0179 assert( sizeof(ULL) == 8 );
0180
0181 unsigned len = s ? strlen(s) : 0 ;
0182 ULL mxw = len < 8 ? len : 8 ;
0183
0184 ULL v = 0ull ;
0185 for(ULL w=0 ; w < mxw ; w++)
0186 {
0187 ULL c = s[w] ;
0188 v |= ( c << 8ull*w ) ;
0189 }
0190 return v ;
0191 }
0192
0193
0194
0195
0196 template<size_t SIZE>
0197 const char* SStr::FormatInt( const char* fmt, int value )
0198 {
0199 char buf[SIZE];
0200 size_t cx = snprintf( buf, SIZE, fmt, value );
0201 bool expect = cx < SIZE ;
0202 if(!expect) std::cerr << "SStr::FormatInt TRUNCATION " << std::endl;
0203 assert( expect && "snprintf truncation detected" );
0204 return strdup(buf);
0205 }
0206
0207 template const char* SStr::FormatInt<8>( const char* , int );
0208 template const char* SStr::FormatInt<64>( const char* , int );
0209
0210
0211 const char* SStr::FormatIndex( int idx, bool prefix, int wid )
0212 {
0213 std::stringstream ss ;
0214 if(prefix) ss << ( idx == 0 ? "z" : ( idx < 0 ? "n" : "p" ) ) ;
0215 ss << std::setfill('0') << std::setw(wid) << std::abs(idx) ;
0216 std::string s = ss.str();
0217 return strdup(s.c_str());
0218 }
0219
0220
0221
0222
0223 template<size_t SIZE>
0224 const char* SStr::Format1( const char* fmt, const char* value )
0225 {
0226 char buf[SIZE];
0227 size_t cx = snprintf( buf, SIZE, fmt, value );
0228 bool expect = cx < SIZE ;
0229 if(!expect) std::cerr << "SStr::Format1 TRUNCATION " << std::endl;
0230 assert( expect && "snprintf truncation detected" );
0231 return strdup(buf);
0232 }
0233
0234 template<size_t SIZE>
0235 const char* SStr::Format2( const char* fmt, const char* value1, const char* value2 )
0236 {
0237 char buf[SIZE];
0238 size_t cx = snprintf( buf, SIZE, fmt, value1, value2 );
0239 bool expect = cx < SIZE ;
0240 if(!expect) std::cerr << "SStr::Format2 TRUNCATION " << std::endl;
0241 assert( expect && "snprintf truncation detected" );
0242 return strdup(buf);
0243 }
0244
0245 template<size_t SIZE>
0246 const char* SStr::Format3( const char* fmt, const char* value1, const char* value2, const char* value3 )
0247 {
0248 char buf[SIZE];
0249 size_t cx = snprintf( buf, SIZE, fmt, value1, value2, value3 );
0250 bool expect = cx < SIZE ;
0251 if(!expect) std::cerr << "SStr::Format3 TRUNCATION " << std::endl;
0252 assert( expect && "snprintf truncation detected" );
0253 return strdup(buf);
0254 }
0255
0256
0257
0258 template const char* SStr::Format1<256>( const char* , const char* );
0259 template const char* SStr::Format2<256>( const char* , const char*, const char* );
0260 template const char* SStr::Format3<256>( const char* , const char*, const char* , const char* );
0261
0262 template const char* SStr::Format1<16>( const char* , const char* );
0263
0264
0265 template<typename T>
0266 const char* SStr::FormatReal(const T value, int w, int p, char fill )
0267 {
0268 std::stringstream ss ;
0269 ss << std::fixed << std::setfill(fill) << std::setw(w) << std::setprecision(p) << value ;
0270 std::string s = ss.str();
0271 return strdup(s.c_str()) ;
0272 }
0273
0274 template const char* SStr::FormatReal<float>(const float, int, int, char );
0275 template const char* SStr::FormatReal<double>(const double, int, int, char );
0276
0277
0278 template<typename ... Args>
0279 std::string SStr::Format_( const char* fmt, Args ... args )
0280 {
0281
0282 int sz = std::snprintf( nullptr, 0, fmt, args ... ) + 1;
0283 assert( sz > 0 );
0284 std::vector<char> buf(sz) ;
0285 std::snprintf( buf.data(), sz, fmt, args ... );
0286 return std::string( buf.begin(), buf.begin() + sz - 1 );
0287 }
0288
0289 template std::string SStr::Format_( const char*, const char* );
0290 template std::string SStr::Format_( const char* , int, double );
0291 template std::string SStr::Format_( const char* , int );
0292 template std::string SStr::Format_( const char* , int, const char* );
0293 template std::string SStr::Format_( const char* , unsigned );
0294 template std::string SStr::Format_( const char*, const char* , const char* );
0295 template std::string SStr::Format_( const char*, const char* , int, const char* );
0296
0297
0298 template<typename ... Args>
0299 const char* SStr::Format( const char* fmt, Args ... args )
0300 {
0301 std::string s = Format_(fmt, args...) ;
0302 return strdup(s.c_str());
0303 }
0304
0305 template const char* SStr::Format( const char*, const char* );
0306 template const char* SStr::Format( const char* , int, double );
0307 template const char* SStr::Format( const char* , int );
0308 template const char* SStr::Format( const char* , int, const char* );
0309 template const char* SStr::Format( const char* , unsigned );
0310 template const char* SStr::Format( const char*, const char* , const char* );
0311 template const char* SStr::Format( const char*, const char* , int, const char* );
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337 bool SStr::Blank( const char* s )
0338 {
0339 unsigned n = strlen(s) ;
0340 return n == 0 || All(s, ' ') ;
0341 }
0342
0343 bool SStr::All( const char* s , char q )
0344 {
0345 unsigned n = strlen(s) ;
0346 return n > 0 && Count(s, q) == n ;
0347
0348 }
0349 unsigned SStr::Count( const char* s , char q )
0350 {
0351 unsigned n = strlen(s) ;
0352 unsigned count = 0 ;
0353 for(unsigned i=0 ; i < n ; i++) if( s[i] == q ) count += 1 ;
0354 return count ;
0355 }
0356
0357 bool SStr::Contains( const char* s_ , const char* q_ )
0358 {
0359 std::string s(s_);
0360 std::string q(q_);
0361 return s.find(q) != std::string::npos ;
0362 }
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 bool SStr::EndsWith( const char* s, const char* q)
0375 {
0376 int pos = strlen(s) - strlen(q) ;
0377 return pos > 0 && strncmp(s + pos, q, strlen(q)) == 0 ;
0378 }
0379
0380 const char* SStr::StripPrefix_(const char* s, const char* pfx )
0381 {
0382 const char* ss = pfx && StartsWith(s, pfx ) ? s + strlen(pfx) : s ;
0383 return strdup(ss);
0384 }
0385
0386
0387
0388
0389 const char* SStr::StripPrefix(const char* s, const char* pfx0, const char* pfx1, const char* pfx2 )
0390 {
0391 if( pfx0 && StartsWith(s,pfx0) ) return StripPrefix_(s, pfx0) ;
0392 else if( pfx1 && StartsWith(s,pfx1) ) return StripPrefix_(s, pfx1) ;
0393 else if( pfx2 && StartsWith(s,pfx2) ) return StripPrefix_(s, pfx2) ;
0394 return strdup(s);
0395 }
0396
0397 const char* SStr::MaterialBaseName(const char* s )
0398 {
0399 return StripPrefix(s, "/dd/Materials/", "_dd_Materials_" );
0400 }
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412 bool SStr::StartsWith( const char* s, const char* q)
0413 {
0414 return s && q && strlen(q) <= strlen(s) && strncmp(s, q, strlen(q)) == 0 ;
0415 }
0416
0417
0418
0419
0420 const char* SStr::AZaz = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
0421
0422 bool SStr::StartsWithLetterAZaz(const char* q )
0423 {
0424 const char* p = q != nullptr && strlen(q) > 0 ? strchr(AZaz, q[0]) : nullptr ;
0425 return p != nullptr ;
0426 }
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441 bool SStr::SimpleMatch(const char* s, const char* q )
0442 {
0443 unsigned ls = strlen(s);
0444 unsigned lq = strlen(q);
0445
0446 if(ls == 0 ) return false ;
0447 if(lq == 0 ) return false ;
0448
0449 bool qed = q[lq-1] == '$' || q[lq-1] == '@' ;
0450 bool qed_match = 0 == strncmp(s, q, lq - 1) && ls == lq - 1 ;
0451 return qed ? qed_match : StartsWith(s, q) ;
0452 }
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476 bool SStr::Match(const char* s, const char* q)
0477 {
0478 if (*q == '\0' && *s == '\0') return true;
0479
0480 if (*q == '*' && *(q+1) != '\0' && *s == '\0') return false;
0481
0482 if ( (*q == '$' || *q == '@') && *(q+1) == '\0' && *s == '\0' ) return true ;
0483
0484 if (*q == '?' || *q == *s) return SStr::Match(s+1, q+1);
0485
0486 if (*q == '*') return SStr::Match(s, q+1) || SStr::Match(s+1, q);
0487
0488 return false;
0489 }
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504 bool SStr::HasPointerSuffix( const char* name, unsigned hexdigits )
0505 {
0506
0507
0508
0509 std::string s(name);
0510 unsigned l = s.size() ;
0511 if(l < hexdigits+2 ) return false ;
0512
0513 for(unsigned i=0 ; i < hexdigits+2 ; i++)
0514 {
0515 char c = s[l-11+i] ;
0516 bool ok = false ;
0517 switch(i)
0518 {
0519 case 0: ok = c == '0' ; break ;
0520 case 1: ok = c == 'x' ; break ;
0521 default: ok = ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'f' ) ; break ;
0522 }
0523 if(!ok) return false ;
0524 }
0525 return true ;
0526 }
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541 int SStr::GetPointerSuffixDigits( const char* name )
0542 {
0543 if( name == NULL ) return -1 ;
0544 int l = strlen(name) ;
0545 int num = 0 ;
0546 for(int i=0 ; i < l ; i++ )
0547 {
0548 char c = *(name + l - 1 - i) ;
0549 bool hexdigit = ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'f' ) ;
0550 if(!hexdigit) break ;
0551 num += 1 ;
0552 }
0553
0554 if(l - num - 1 < 0 ) return -1 ;
0555 if(l - num - 2 < 0 ) return -1 ;
0556
0557 char c1 = *(name + l - num - 1);
0558 char c2 = *(name + l - num - 2);
0559
0560 return c1 == 'x' && c2 == '0' ? num : -1 ;
0561 }
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571 bool SStr::HasPointerSuffix( const char* name, unsigned min_hexdigits, unsigned max_hexdigits )
0572 {
0573 int num_hexdigits = GetPointerSuffixDigits( name );
0574 return num_hexdigits > -1 && num_hexdigits >= int(min_hexdigits) && num_hexdigits <= int(max_hexdigits) ;
0575 }
0576
0577
0578
0579
0580
0581
0582
0583
0584 const char* SStr::TrimPointerSuffix( const char* name )
0585 {
0586 int num_hexdigits = GetPointerSuffixDigits( name );
0587 char* trim = strdup(name);
0588
0589 if( num_hexdigits >= 6 && num_hexdigits <= 12 )
0590 {
0591 int ip = strlen(name) - num_hexdigits - 2 ;
0592 assert( ip >= 0 );
0593 char* p = trim + ip ;
0594 assert( *p == '0' );
0595 *p = '\0' ;
0596 }
0597 return trim ;
0598 }
0599
0600
0601
0602 const char* SStr::TrimLeading(const char* s)
0603 {
0604 char* p = strdup(s);
0605 while( *p && ( *p == ' ' || *p == '\n' )) p++ ;
0606 return p ;
0607 }
0608 const char* SStr::TrimTrailing(const char* s)
0609 {
0610 char* p = strdup(s);
0611 char* e = p + strlen(p) - 1 ;
0612 while(e > p && ( *e == ' ' || *e == '\n' )) e-- ;
0613 e[1] = '\0' ;
0614 return p ;
0615 }
0616 const char* SStr::Trim(const char* s)
0617 {
0618 char* p = strdup(s);
0619 char* e = p + strlen(p) - 1 ;
0620 while(e > p && ( *e == ' ' || *e == '\n' )) e-- ;
0621 *(e+1) = '\0' ;
0622 while( *p && ( *p == ' ' || *p == '\n')) p++ ;
0623 return p ;
0624 }
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639 const char* SStr::HeadFirst(const char* s_, char c )
0640 {
0641 char* s = strdup(s_);
0642 char* p = strchr(s, c );
0643 if(p) *p = '\0' ;
0644 return s ;
0645 }
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660 const char* SStr::HeadLast(const char* s_, char c )
0661 {
0662 char* s = strdup(s_);
0663 char* p = strrchr(s, c );
0664 if(p) *p = '\0' ;
0665 return s ;
0666 }
0667
0668
0669
0670 const char* SStr::Concat( const char* a, const char* b, const char* c )
0671 {
0672 std::stringstream ss ;
0673 if(a) ss << a ;
0674 if(b) ss << b ;
0675 if(c) ss << c ;
0676 std::string s = ss.str();
0677 return strdup(s.c_str());
0678 }
0679
0680 const char* SStr::Concat( const char* a, unsigned b, const char* c )
0681 {
0682 std::stringstream ss ;
0683 if(a) ss << a ;
0684 ss << b ;
0685 if(c) ss << c ;
0686 std::string s = ss.str();
0687 return strdup(s.c_str());
0688 }
0689
0690 const char* SStr::Concat( const char* a, unsigned b, const char* c, unsigned d, const char* e )
0691 {
0692 std::stringstream ss ;
0693
0694 if(a) ss << a ;
0695 ss << b ;
0696 if(c) ss << c ;
0697 ss << d ;
0698 if(e) ss << e ;
0699
0700 std::string s = ss.str();
0701 return strdup(s.c_str());
0702 }
0703
0704
0705 template<typename T>
0706 const char* SStr::Concat_( const char* a, T b, const char* c )
0707 {
0708 std::stringstream ss ;
0709 if(a) ss << a ;
0710 ss << b ;
0711 if(c) ss << c ;
0712 std::string s = ss.str();
0713 return strdup(s.c_str());
0714 }
0715
0716
0717
0718 const char* SStr::Replace( const char* s, char a, char b )
0719 {
0720 std::stringstream ss ;
0721 for(unsigned i=0 ; i < strlen(s) ; i++)
0722 {
0723 char c = *(s+i) ;
0724 ss << ( c == a ? b : c ) ;
0725 }
0726 std::string r = ss.str();
0727 return strdup(r.c_str());
0728 }
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740 const char* SStr::ReplaceEnd( const char* s, const char* q, const char* r )
0741 {
0742 int pos = strlen(s) - strlen(q) ;
0743 assert( pos > 0 && strncmp(s + pos, q, strlen(q)) == 0 );
0744
0745 std::stringstream ss ;
0746 for(int i=0 ; i < pos ; i++) ss << *(s+i) ;
0747 ss << r ;
0748
0749 std::string n = ss.str();
0750 return strdup(n.c_str());
0751 }
0752
0753
0754
0755
0756
0757
0758 void SStr::Split( const char* str, char delim, std::vector<std::string>& elem )
0759 {
0760 std::stringstream ss;
0761 ss.str(str) ;
0762 std::string s;
0763 while (std::getline(ss, s, delim)) elem.push_back(s) ;
0764 }
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781 int SStr::ISplit( const char* line, std::vector<int>& ivec, char delim )
0782 {
0783 std::stringstream ss;
0784 ss.str(line) ;
0785
0786 std::string s;
0787 while (std::getline(ss, s, delim)) ivec.push_back(std::atoi(s.c_str())) ;
0788
0789 return ivec.size();
0790 }
0791
0792 std::vector<int>* SStr::ISplit( const char* line, char delim )
0793 {
0794 std::vector<int>* ivec = new std::vector<int>() ;
0795 ISplit(line, *ivec, delim );
0796 return ivec ;
0797 }
0798
0799
0800
0801 template const char* SStr::Concat_<unsigned>( const char* , unsigned , const char* );
0802 template const char* SStr::Concat_<unsigned long long>( const char* , unsigned long long , const char* );
0803 template const char* SStr::Concat_<int>( const char* , int , const char* );
0804 template const char* SStr::Concat_<long>( const char* , long , const char* );
0805
0806
0807
0808
0809 void SStr::ParseGridSpec( std::array<int,9>& grid, const char* spec)
0810 {
0811 int idx = 0 ;
0812 std::stringstream ss(spec);
0813 std::string s;
0814 while (std::getline(ss, s, ','))
0815 {
0816 std::stringstream tt(s);
0817 std::string t;
0818 while (std::getline(tt, t, ':')) grid[idx++] = std::atoi(t.c_str()) ;
0819 }
0820
0821 std::stringstream uu ;
0822 uu << spec << " : " ;
0823 for(int i=0 ; i < 9 ; i++) uu << grid[i] << " " ;
0824 uu << std::endl ;
0825
0826 std::string u = ss.str();
0827 LOG(info) << u ;
0828 }
0829
0830
0831 void SStr::DumpGrid(const std::array<int,9>& cl)
0832 {
0833 int i0 = cl[0] ;
0834 int i1 = cl[1] ;
0835 int is = cl[2] ;
0836 int j0 = cl[3] ;
0837 int j1 = cl[4] ;
0838 int js = cl[5] ;
0839 int k0 = cl[6] ;
0840 int k1 = cl[7] ;
0841 int ks = cl[8] ;
0842
0843 unsigned num = 0 ;
0844 for(int i=i0 ; i < i1 ; i+=is )
0845 for(int j=j0 ; j < j1 ; j+=js )
0846 for(int k=k0 ; k < k1 ; k+=ks )
0847 {
0848 std::cout << std::setw(2) << num << " (i,j,k) " << "(" << i << "," << j << "," << k << ") " << std::endl ;
0849 num += 1 ;
0850 }
0851 }
0852
0853
0854
0855
0856
0857
0858 template <typename T>
0859 void SStr::GetEVector(std::vector<T>& vec, const char* key, const char* fallback )
0860 {
0861 const char* sval = getenv(key);
0862 std::stringstream ss(sval ? sval : fallback);
0863 std::string s ;
0864 while(getline(ss, s, ',')) vec.push_back(ato_<T>(s.c_str()));
0865 }
0866
0867 template void SStr::GetEVector<unsigned>(std::vector<unsigned>& vec, const char* key, const char* fallback );
0868 template void SStr::GetEVector<float>(std::vector<float>& vec, const char* key, const char* fallback );
0869
0870 void SStr::GetEVec(glm::vec3& v, const char* key, const char* fallback )
0871 {
0872 std::vector<float> vec ;
0873 SStr::GetEVector<float>(vec, key, fallback);
0874 std::cout << key << SStr::Present(vec) << std::endl ;
0875 assert( vec.size() == 3 );
0876 for(int i=0 ; i < 3 ; i++) v[i] = vec[i] ;
0877 }
0878
0879 void SStr::GetEVec(glm::vec4& v, const char* key, const char* fallback )
0880 {
0881 std::vector<float> vec ;
0882 SStr::GetEVector<float>(vec, key, fallback);
0883 std::cout << key << SStr::Present(vec) << std::endl ;
0884 assert( vec.size() == 4 );
0885 for(int i=0 ; i < 4 ; i++) v[i] = vec[i] ;
0886 }
0887
0888
0889
0890
0891 template <typename T>
0892 std::string SStr::Present(std::vector<T>& vec)
0893 {
0894 std::stringstream ss ;
0895 for(unsigned i=0 ; i < vec.size() ; i++) ss << vec[i] << " " ;
0896 return ss.str();
0897 }
0898
0899
0900 template std::string SStr::Present<float>(std::vector<float>& );
0901 template std::string SStr::Present<unsigned>(std::vector<unsigned>& );
0902 template std::string SStr::Present<int>(std::vector<int>& );
0903
0904
0905
0906 template <typename T>
0907 T SStr::GetEValue(const char* key, T fallback)
0908 {
0909 const char* sval = getenv(key);
0910 T val = sval ? ato_<T>(sval) : fallback ;
0911 return val ;
0912 }
0913
0914
0915
0916 unsigned SStr::Encode4(const char* s)
0917 {
0918 unsigned u4 = 0u ;
0919 for(unsigned i=0 ; i < std::min(4ul, strlen(s)) ; i++ )
0920 {
0921 unsigned u = unsigned(s[i]) ;
0922 u4 |= ( u << (i*8) ) ;
0923 }
0924 return u4 ;
0925 }
0926
0927
0928 template float SStr::GetEValue<float>(const char* key, float fallback);
0929 template int SStr::GetEValue<int>(const char* key, int fallback);
0930 template unsigned SStr::GetEValue<unsigned>(const char* key, unsigned fallback);
0931 template std::string SStr::GetEValue<std::string>(const char* key, std::string fallback);
0932 template bool SStr::GetEValue<bool>(const char* key, bool fallback);
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963 template <typename T>
0964 T SStr::ato_( const char* a )
0965 {
0966 std::string s(a);
0967 std::istringstream iss(s);
0968 T v ;
0969 iss >> v ;
0970 return v ;
0971 }
0972
0973
0974 template double SStr::ato_<double>( const char* );
0975 template float SStr::ato_<float>( const char* );
0976 template int SStr::ato_<int>( const char* );
0977 template unsigned SStr::ato_<unsigned>( const char* );
0978
0979
0980 void SStr::GridMinMax(const std::array<int,9>& grid, glm::ivec3&mn, glm::ivec3& mx)
0981 {
0982 mn.x = grid[0] ; mx.x = grid[1] ;
0983 mn.y = grid[3] ; mx.y = grid[4] ;
0984 mn.z = grid[6] ; mx.z = grid[7] ;
0985 }
0986
0987 void SStr::GridMinMax(const std::array<int,9>& grid, int&mn, int& mx)
0988 {
0989 for(int a=0 ; a < 3 ; a++)
0990 for(int i=grid[a*3+0] ; i < grid[a*3+1] ; i+=grid[a*3+2] )
0991 {
0992 if( i > mx ) mx = i ;
0993 if( i < mn ) mn = i ;
0994 }
0995 std::cout << "SStr::GridMinMax " << mn << " " << mx << std::endl ;
0996 }
0997
0998
0999
1000 int SStr::AsInt(const char* arg, int fallback )
1001 {
1002 char* end ;
1003 char** endptr = &end ;
1004 int base = 10 ;
1005 unsigned long ul = strtoul(arg, endptr, base);
1006 bool end_points_to_terminator = end == arg + strlen(arg) ;
1007 return end_points_to_terminator ? int(ul) : fallback ;
1008 }
1009
1010
1011 int SStr::ExtractInt(const char* arg, int start, unsigned num, int fallback)
1012 {
1013 unsigned pos = start < 0 ? strlen(arg) + start : start ;
1014 unsigned len = strlen(arg) ;
1015 if(pos > len) return fallback ;
1016 if(pos + num > len) return fallback ;
1017
1018 std::string s(arg+pos,num) ;
1019 return SStr::AsInt(s.c_str(), fallback);
1020 }
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031 const char* SStr::ReplaceChars(const char* str, const char* repl, char to )
1032 {
1033 char* s = strdup(str);
1034 for(unsigned i=0 ; i < strlen(s) ; i++) if(strchr(repl, s[i]) != nullptr) s[i] = to ;
1035 return s ;
1036 }
1037
1038 long SStr::ExtractLong( const char* s, long fallback )
1039 {
1040 std::vector<long> vals;
1041 Extract(vals, s);
1042 return vals.size() == 1 ? vals[0] : fallback ;
1043 }
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054 void SStr::Extract( std::vector<long>& vals, const char* s )
1055 {
1056 char* s0 = strdup(s);
1057 char* p = s0 ;
1058 while (*p)
1059 {
1060 if( (*p >= '0' && *p <= '9') || *p == '+' || *p == '-') vals.push_back(strtol(p, &p, 10)) ;
1061 else p++ ;
1062 }
1063 free(s0);
1064 }
1065
1066 void SStr::Extract_( std::vector<long>& vals, const char* s )
1067 {
1068 char* p = const_cast<char*>(s) ;
1069 while (*p)
1070 {
1071 if( (*p >= '0' && *p <= '9') || *p == '+' || *p == '-') vals.push_back(strtol(p, &p, 10)) ;
1072 else p++ ;
1073 }
1074 }
1075
1076 void SStr::Extract_( std::vector<float>& vals, const char* s )
1077 {
1078 char* p = const_cast<char*>(s) ;
1079 while (*p)
1080 {
1081 if( (*p >= '0' && *p <= '9') || *p == '+' || *p == '-' || *p == '.') vals.push_back(strtof(p, &p)) ;
1082 else p++ ;
1083 }
1084 }
1085
1086
1087
1088
1089 int SStr::ekv_split( std::vector<std::pair<std::string, std::string> > & ekv, const char* line_, char edelim, char kvdelim)
1090 {
1091 int err = 0 ;
1092 bool warn = true ;
1093 const char* line = strdup(line_);
1094 typedef std::pair<std::string,std::string> KV ;
1095 std::istringstream f(line);
1096 std::string s;
1097 while (getline(f, s, edelim))
1098 {
1099 std::vector<std::string> kv ;
1100 SStr::Split( s.c_str(), kvdelim, kv );
1101
1102 if(kv.size() == 2)
1103 {
1104 ekv.push_back(KV(kv[0],kv[1]));
1105 }
1106 else
1107 {
1108 if(warn)
1109 {
1110 LOG(error) << "ignoring malformed kv [" << s.c_str() << "]" ;
1111 LOG(error) << "line [" << line << "]" ;
1112 }
1113 err++ ;
1114 std::raise(SIGINT);
1115 }
1116 }
1117 return err ;
1118 }
1119
1120
1121
1122
1123 const char* SStr::ParseStringIntInt( const char* triplet, int& y, int& z, char delim )
1124 {
1125 std::stringstream ss;
1126 ss.str(triplet) ;
1127 std::string s;
1128 std::vector<std::string> elem ;
1129 while (std::getline(ss, s, delim)) elem.push_back(s) ;
1130 assert(elem.size() == 3 );
1131 y = AsInt( elem[1].c_str() );
1132 z = AsInt( elem[2].c_str() );
1133 return strdup(elem[0].c_str());
1134 }
1135
1136