File indexing completed on 2026-04-09 07:49:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <string>
0015 #include <vector>
0016 #include <iostream>
0017 #include <iomanip>
0018 #include "sstr.h"
0019 #include "ssys.h"
0020
0021
0022
0023
0024
0025 void test_HasTail_0()
0026 {
0027
0028 const char* lines = R"LIT(
0029 0x
0030 0xc0ffee
0031 World0xc0ffee
0032 World0xdeadbeef
0033 World0xdead0xbeef
0034 )LIT";
0035 std::stringstream ss(lines);
0036 std::string l ;
0037 std::vector<std::string> v ;
0038 while (std::getline(ss, l, '\n'))
0039 {
0040 if(l.empty()) continue ;
0041 assert( sstr::HasTail(l) == true );
0042 v.push_back(l);
0043 }
0044
0045 std::cout << "test_HasTail_0 v.size " << v.size() << "\n" ;
0046 assert( sstr::HasTail(v) == true );
0047 }
0048
0049
0050
0051 void test_HasTail_1()
0052 {
0053
0054 const char* lines = R"LIT(
0055 red
0056 green
0057 blue
0058 )LIT";
0059 std::stringstream ss(lines);
0060 std::string l ;
0061 std::vector<std::string> v ;
0062 while (std::getline(ss, l, '\n'))
0063 {
0064 if(l.empty()) continue ;
0065 assert( sstr::HasTail(l) == false );
0066 v.push_back(l);
0067 }
0068
0069 std::cout << "test_HasTail_1 v.size " << v.size() << "\n" ;
0070 assert( sstr::HasTail(v) == false );
0071 }
0072
0073
0074
0075 void test_HasTail()
0076 {
0077 test_HasTail_0();
0078 test_HasTail_1();
0079 }
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 void test_StripTail()
0094 {
0095
0096 const char* lines = R"LIT(
0097 0x
0098 0xc0ffee
0099 World0xc0ffee
0100 World0xdeadbeef
0101 World0xdead0xbeef
0102 )LIT";
0103 std::stringstream ss(lines);
0104 std::string l ;
0105 while (std::getline(ss, l, '\n'))
0106 {
0107 if(l.empty()) continue ;
0108 std::string s = sstr::StripTail(l, "0x") ;
0109 std::cout
0110 << " l:" << std::setw(30) << l
0111 << " s:" << std::setw(30) << s
0112 << " s.size: " << s.size()
0113 << " s.empty: " << s.empty()
0114 << std::endl
0115 ;
0116 }
0117 }
0118
0119
0120 void test_StripComment()
0121 {
0122 const char* lines = R"LIT(
0123 hello:27:-1
0124 hello:27:-1 ## some comment #
0125 )LIT";
0126 std::stringstream ss(lines);
0127 std::string l ;
0128 while (std::getline(ss, l, '\n'))
0129 {
0130 if(l.empty()) continue ;
0131 std::string s = sstr::StripComment(l) ;
0132 std::cout
0133 << " l:[" << l << "]\n"
0134 << " s:[" << s << "] "
0135 << " s.size: " << s.size()
0136 << " s.empty: " << s.empty()
0137 << std::endl
0138 ;
0139 }
0140 }
0141
0142 void test_TrimString()
0143 {
0144 const char* lines = R"LIT(
0145 hello:27:-1
0146 ( hello:27:-1 )
0147 hello:27:-1 ## some comment #
0148 )LIT";
0149 std::stringstream ss(lines);
0150 std::string l ;
0151 while (std::getline(ss, l, '\n'))
0152 {
0153 if(l.empty()) continue ;
0154 std::string s = sstr::TrimString(l) ;
0155 std::cout
0156 << " l:[" << l << "]\n"
0157 << " s:[" << s << "] "
0158 << " s.size: " << s.size()
0159 << " s.empty: " << s.empty()
0160 << std::endl
0161 ;
0162 }
0163 }
0164
0165
0166
0167
0168
0169
0170 struct fspec
0171 {
0172 static std::string Format(const std::vector<std::string>& fields );
0173 static void Init(std::vector<fspec>& fss, const std::vector<std::string>& fields );
0174 static fspec Init(const char* field);
0175
0176 std::vector<std::string> lines ;
0177 int linecount ;
0178 int maxlen ;
0179
0180 std::string desc() const ;
0181 };
0182
0183 inline std::string fspec::desc() const
0184 {
0185 std::stringstream ss ;
0186 ss << " fspec::desc linecount " << linecount << " maxlen " << maxlen ;
0187 std::string str = ss.str();
0188 return str ;
0189 }
0190
0191 inline fspec fspec::Init(const char* field)
0192 {
0193 std::stringstream ss(field);
0194 std::string l ;
0195
0196 fspec fs = {} ;
0197
0198 fs.linecount = 0 ;
0199 fs.maxlen = 0 ;
0200
0201 while (std::getline(ss, l, '\n'))
0202 {
0203 fs.lines.push_back(l);
0204 fs.linecount += 1 ;
0205 int len = l.size() ;
0206 fs.maxlen = std::max( fs.maxlen, len );
0207 }
0208 return fs ;
0209 }
0210
0211 inline void fspec::Init(std::vector<fspec>& fss, const std::vector<std::string>& fields )
0212 {
0213 int num_fields = fields.size();
0214 for(int i=0 ; i < num_fields ; i++)
0215 {
0216 const std::string& field = fields[i] ;
0217 fspec fs = fspec::Init(field.c_str());
0218 fss.push_back(fs);
0219 }
0220 }
0221
0222 inline std::string fspec::Format(const std::vector<std::string>& fields )
0223 {
0224 std::vector<fspec> fss ;
0225 Init(fss, fields);
0226
0227 int num_fields = fields.size();
0228 std::stringstream ss ;
0229 ss << " num_fields " << num_fields << std::endl ;
0230 for(int i=0 ; i < num_fields ; i++) ss << fss[i].desc() << std::endl ;
0231
0232 std::string str = ss.str();
0233 return str ;
0234 }
0235
0236
0237
0238
0239
0240
0241 void test_SideBySide()
0242 {
0243 const char* lines = R"LIT(
0244 0x
0245 0xc0ffee
0246 World0xc0ffee
0247 World0xdeadbeef
0248 World0xdead0xbeef
0249 )LIT";
0250
0251 std::vector<std::string> fields ;
0252 fields.push_back(lines);
0253 fields.push_back(lines);
0254 fields.push_back(lines);
0255
0256 std::cout << fspec::Format( fields ) << std::endl ;
0257
0258
0259 }
0260
0261
0262 void test_nullchar(bool flip)
0263 {
0264 char prefix = flip ? 'X' : '\0' ;
0265 std::string name ;
0266 name += prefix ;
0267 name += "hello" ;
0268
0269 std::cout << "[" << name << "]" << std::endl ;
0270 }
0271
0272 void test_Write()
0273 {
0274 const char* path = "/tmp/test_Write.txt" ;
0275 sstr::Write(path, "test_Write" );
0276 }
0277
0278
0279 void test_empty()
0280 {
0281 std::string empty ;
0282 std::cout << "empty [" << empty << "]" << std::endl ;
0283 std::cout << "empty.c_str() [" << empty.c_str() << "]" << std::endl ;
0284
0285 char c = empty.c_str()[0] ;
0286 std::cout << "c [" << c << "]" << std::endl ;
0287
0288 bool c_is_terminator = c == '\0' ;
0289 std::cout << " c_is_terminator " << ( c_is_terminator ? "YES" : "NO " ) << std::endl;
0290 }
0291
0292
0293 template<typename T>
0294 void test_ParseIntSpecList()
0295 {
0296 const char* _spec = "1,2,3,100,200,h1,h5,6,7,K1,K10,11,12,M1,2,3,K1,2,M1,H1,2,G2,T1,2,h1:4" ;
0297
0298 std::vector<T> expect = { 1,
0299 2,
0300 3,
0301 100,
0302 200,
0303 100,
0304 500,
0305 600,
0306 700,
0307 1'000,
0308 10'000,
0309 11'000,
0310 12'000,
0311 1'000'000,
0312 2'000'000,
0313 3'000'000,
0314 1'000,
0315 2'000,
0316 1'000'000,
0317 100'000,
0318 200'000,
0319 2'000'000'000,
0320 1'000'000'000'000,
0321 2'000'000'000'000,
0322 100,
0323 200,
0324 300,
0325 400
0326 };
0327 int num_expect = expect.size();
0328
0329 std::vector<std::string> spec ;
0330 sstr::Split( _spec, ',' , spec );
0331 int num_spec = spec.size();
0332
0333 std::vector<T> value ;
0334 sstr::ParseIntSpecList<T>(value, _spec);
0335 int num_value = value.size();
0336
0337 std::vector<T>* ls = sstr::ParseIntSpecList<T>(_spec) ;
0338 int num_ls = ls->size();
0339
0340 std::cout
0341 << " _spec " << std::endl
0342 << _spec
0343 << std::endl
0344 << " num_spec " << num_spec
0345 << " num_value " << num_value
0346 << " num_expect " << num_expect
0347 << " num_ls " << num_ls
0348 << std::endl
0349 ;
0350
0351 assert( num_spec <= num_expect );
0352 assert( num_value == num_expect );
0353 assert( num_ls == num_expect );
0354
0355 int pass = 0 ;
0356
0357 std::cout
0358 << std::setw(16) << "spec_input"
0359 << std::setw(16) << "expected"
0360 << std::setw(16) << "parsed"
0361 << std::setw(16) << "ls_parsed"
0362 << std::setw(20) << "match"
0363 << std::endl
0364 ;
0365
0366
0367 for(int i=0 ; i < num_value ; i++)
0368 {
0369 const char* s = i < num_spec ? spec[i].c_str() : nullptr ;
0370 T e = i < num_expect ? expect[i] : -1 ;
0371 T v = i < num_value ? value[i] : -1 ;
0372 T l = i < num_ls ? (*ls)[i] : -1 ;
0373
0374 bool match = e == v && e == l ;
0375
0376 pass += int(match) ;
0377 std::cout
0378 << std::setw(16) << ( s ? s : "-" )
0379 << std::setw(16) << e
0380 << std::setw(16) << v
0381 << std::setw(16) << l
0382 << std::setw(20) << ( match ? " YES " : " NO " )
0383 << std::endl
0384 ;
0385
0386 }
0387 assert( pass == num_value );
0388 }
0389
0390
0391 template<typename T>
0392 void test_ParseIntSpecList_demo()
0393 {
0394 std::vector<std::string> spec = {
0395 "M1:5,K1:2" ,
0396 "M1,2,3,4,5,K1,2",
0397 "h1:10",
0398 "K1:10",
0399 "H1:10",
0400 "M1:10",
0401 "M1x10",
0402 "1x5,2x5",
0403 "1001"
0404 };
0405 int num_spec = spec.size();
0406
0407 std::vector<T> value ;
0408 for(int i=0 ; i < num_spec ; i++)
0409 {
0410 const char* _spec = spec[i].c_str();
0411 sstr::ParseIntSpecList<T>(value, _spec);
0412 std::cout
0413 << std::setw(30) << _spec
0414 << " : "
0415 << " ["
0416 ;
0417
0418 int num_value = value.size();
0419 for(int i=0 ; i < num_value ; i++) std::cout << value[i] << " " ;
0420 std::cout << " ] " << std::endl ;
0421 }
0422 }
0423
0424
0425
0426
0427 void test_snprintf()
0428 {
0429 char buf[10];
0430 for(int i=0 ; i < 1010 ; i++)
0431 {
0432 int n = snprintf(buf, 10, "%0.3d", i) ;
0433 std::cout << buf << ":" << n << std::endl ;
0434 }
0435 }
0436
0437
0438 void test_Format()
0439 {
0440 const char* str_0 = sstr::Format("u_%d.npy", 214) ;
0441 const char* str_1 = sstr::Format("u_%llu.npy", 214ull ) ;
0442
0443 std::cout
0444 << "test_Format\n"
0445 << "str_0:[" << str_0 << "]\n"
0446 << "str_1:[" << str_1 << "]\n"
0447 ;
0448 }
0449
0450
0451
0452 struct Prof
0453 {
0454 static constexpr const char* FMT = "%0.3d" ;
0455 static constexpr const int N = 10 ;
0456 static char TAG[N] ;
0457 static int SetTag(int idx, const char* fmt=FMT );
0458 static void UnsetTag();
0459 };
0460
0461 char Prof::TAG[N] = {} ;
0462
0463 inline int Prof::SetTag(int idx, const char* fmt)
0464 {
0465 return snprintf(TAG, N, fmt, idx );
0466 }
0467 inline void Prof::UnsetTag()
0468 {
0469 TAG[0] = '\0' ;
0470 }
0471
0472 void test_TAG()
0473 {
0474 std::cout << __FUNCTION__ << std::endl;
0475 std::cout << "[" << Prof::TAG << "]" << std::endl ;
0476 for(int i=0 ; i < 100 ; i++)
0477 {
0478 Prof::SetTag(i,"A%0.3d");
0479 if( i % 10 == 0 ) Prof::UnsetTag();
0480 std::cout << "[" << Prof::TAG << "]" << std::endl ;
0481 }
0482 }
0483
0484 void test_StripTail_Unique_0()
0485 {
0486 std::vector<std::string> src = {{
0487 "red",
0488 "green",
0489 "blue",
0490 "cyan",
0491 "yellow",
0492 "magenta",
0493 "cyan",
0494 "cyan",
0495 "cyan",
0496 }};
0497
0498 std::vector<std::string> key ;
0499 sstr::StripTail_Unique( key, src );
0500 std::cout << sstr::DescKeySrc(key, src) ;
0501 }
0502
0503 void test_StripTail_Unique_1()
0504 {
0505 std::vector<std::string> src = {{
0506 "red0xbeef",
0507 "green0xbeef",
0508 "blue0xbeef",
0509 "red0xbeef",
0510 "red0xbeef",
0511 "cyan",
0512 "yellow",
0513 "red0xbeef",
0514 "green0xbeef",
0515 "green0xbeef",
0516 "green0xbeef",
0517 "magenta",
0518 "green0xbeef",
0519 "red0xbeef",
0520 "red0xbeef",
0521 "red0xbeef",
0522 "red0xbeef",
0523 "red0xbeef",
0524 "red0xbeef",
0525 }} ;
0526
0527 std::vector<std::string> key ;
0528 sstr::StripTail_Unique( key, src );
0529 std::cout << sstr::DescKeySrc(key, src) ;
0530 }
0531
0532 void test_Extract()
0533 {
0534 std::vector<std::string> src = {{
0535 "red0xbeef",
0536 "BoxGridMultiUnion10:30_YX",
0537 "BoxGridMultiUnion10_30_YX"
0538 }} ;
0539
0540 for(unsigned i=0 ; i < src.size() ; i++)
0541 {
0542 const char* st = src[i].c_str();
0543 std::vector<long> vals ;
0544 sstr::Extract(vals, st);
0545 std::cout
0546 << std::setw(20) << st
0547 << " : "
0548 << vals.size()
0549 << "\n"
0550 ;
0551 }
0552
0553 }
0554
0555 void test_Concat()
0556 {
0557 const char* s0 = sstr::Concat("aa","bb","cc","dd" );
0558 assert( strcmp(s0, "aabbccdd" ) == 0 );
0559 const char* s1 = sstr::Concat("aa","bb",nullptr,"dd" );
0560 assert( strcmp(s1, "aabbdd" ) == 0 );
0561 }
0562
0563 void test_IsInteger()
0564 {
0565 std::vector<std::string> src = {{
0566 "0",
0567 "1",
0568 "9",
0569 "10",
0570 "100",
0571 "1000",
0572 "",
0573 "-1",
0574 " 1"
0575 }} ;
0576
0577 for(unsigned i=0 ; i < src.size() ; i++)
0578 {
0579 const char* st = src[i].c_str();
0580 bool ii = sstr::IsInteger(st) ;
0581 std::cout
0582 << ( ii ? "YES" : "NO " )
0583 << " : "
0584 << "[" << st << "]"
0585 << "\n"
0586 ;
0587 }
0588 }
0589
0590
0591
0592 struct sstr_test
0593 {
0594 static constexpr const uint64_t M = 1000000 ;
0595 static constexpr const uint64_t G = 1000000000 ;
0596
0597 static constexpr const char* BLANK = "" ;
0598 static std::vector<std::string> STRS ;
0599 static std::vector<std::string> STRS2 ;
0600
0601 static int Chop();
0602 static int chop();
0603 static int prefix_suffix();
0604
0605 static int StartsWithElem();
0606 static int split();
0607 static int ParseInt();
0608 static int ExtractSize();
0609
0610
0611 static int Main();
0612 };
0613
0614
0615 std::vector<std::string> sstr_test::STRS = {{ "Hello__World", "Hello" , "Hello__" , "__World" }} ;
0616 std::vector<std::string> sstr_test::STRS2 = {{ "/tmp/w54.npy[0:1]", "/tmp/w54.npy[0:2]", "[0:1]" }} ;
0617
0618
0619 int sstr_test::Chop()
0620 {
0621 const char* str = "Hello__World" ;
0622 std::pair<std::string, std::string> head_tail ;
0623 sstr::Chop(head_tail, "__", str );
0624
0625 std::cout << " head " << head_tail.first << std::endl ;
0626 std::cout << " tail " << head_tail.second << std::endl ;
0627
0628 return 0;
0629 }
0630
0631 int sstr_test::chop()
0632 {
0633 for(unsigned i=0 ; i < STRS.size() ; i++ )
0634 {
0635 const char* str = STRS[i].c_str() ;
0636
0637 char* head ;
0638 char* tail ;
0639 sstr::chop(&head, &tail, "__", str );
0640
0641 bool head_blank = head && strcmp( head, BLANK ) == 0 ;
0642 bool tail_blank = tail && strcmp( tail, BLANK ) == 0 ;
0643
0644 std::cout
0645 << " i " << std::setw(3) << i
0646 << " str " << std::setw(30) << str
0647 << " head [" << ( head ? head : "-" ) << "]" << " head_blank " << head_blank
0648 << " tail [" << ( tail ? tail : "-" ) << "]" << " tail_blank " << tail_blank
0649 << std::endl
0650 ;
0651 }
0652 return 0;
0653 }
0654
0655
0656
0657 int sstr_test::prefix_suffix()
0658 {
0659
0660 for(unsigned i=0 ; i < STRS2.size() ; i++ )
0661 {
0662 const char* str = STRS2[i].c_str() ;
0663 char* pfx = nullptr ;
0664 char* sfx = nullptr ;
0665 bool has_suffix = sstr::prefix_suffix(&pfx, &sfx, "[", str );
0666 std::cout
0667 << "sstr_test::prefix_suffix\n"
0668 << " str [" << ( str ? str : "-" ) << "]\n"
0669 << " pfx [" << ( pfx ? pfx : "-" ) << "]\n"
0670 << " sfx [" << ( sfx ? sfx : "-" ) << "]\n"
0671 << " has_suffix " << ( has_suffix ? "YES" : "NO " ) << "\n"
0672 ;
0673 }
0674 return 0 ;
0675 }
0676
0677
0678 int sstr_test::StartsWithElem()
0679 {
0680 std::cout << "[StartsWithElem\n" ;
0681 const char* s = "TO BT BT BT BT BR BT BT BT BT BT BT SC BT BT BT BT SD" ;
0682
0683 bool starts_with_TO_CK_SI = sstr::StartsWithElem(s, "TO,CK,SI" );
0684 bool starts_with_XX_YY_ZZ = sstr::StartsWithElem(s, "XX,YY,ZZ" );
0685
0686 assert( starts_with_TO_CK_SI == true );
0687 assert( starts_with_XX_YY_ZZ == false );
0688 std::cout << "]StartsWithElem\n" ;
0689
0690 return 0;
0691 }
0692 int sstr_test::split()
0693 {
0694 const char* spec = "1.1,0,0,0,0,1.2,0,0,0,0,1.3,0,0,0,0,1.4" ;
0695 std::vector<double> elem ;
0696 sstr::split<double>( elem, spec, ',' );
0697
0698 std::cout << sstr::desc<double>(elem) ;
0699
0700 return 0;
0701 }
0702
0703
0704 int sstr_test::ParseInt()
0705 {
0706 std::vector<std::string> src = {{
0707 "M1",
0708 "G1",
0709 "G2",
0710 "G3",
0711 "X0",
0712 "X1",
0713 "X2",
0714 "X4",
0715 "X8",
0716 "X16",
0717 "X31",
0718 "X32",
0719 "X63",
0720 "X64"
0721 }} ;
0722
0723 for(unsigned i=0 ; i < src.size() ; i++)
0724 {
0725 const char* st = src[i].c_str();
0726 uint64_t value = sstr::ParseInt<uint64_t>(st) ;
0727 std::cout
0728 << " spec " << std::setw(5) << st
0729 << " value " << std::setw(20) << value
0730 << " value/M " << std::setw(20) << value/M
0731 << " value/G " << std::setw(20) << value/G
0732 << "\n"
0733 ;
0734 }
0735 return 0 ;
0736 }
0737
0738 int sstr_test::ExtractSize()
0739 {
0740 std::vector<std::string> src = {{
0741 "hello1",
0742 "hello2",
0743 "hello-1",
0744 "hello10world",
0745 "hello0world",
0746 "hello0world1",
0747 "helloworld",
0748 "0",
0749 "-1",
0750 "+1",
0751 "1",
0752 "-",
0753 "+",
0754 "----",
0755 "++++",
0756 "-+-+-+",
0757 "",
0758 }} ;
0759
0760 for(unsigned i=0 ; i < src.size() ; i++)
0761 {
0762 const char* st = src[i].c_str();
0763 size_t zval = sstr::ExtractSize(st, 0) ;
0764 long lval = sstr::ExtractLong(st, 0) ;
0765 std::cout
0766 << " st " << std::setw(40) << st
0767 << " zval " << std::setw(20) << zval
0768 << " lval " << std::setw(20) << lval
0769 << "\n"
0770 ;
0771 }
0772 return 0 ;
0773
0774
0775 }
0776
0777
0778 int sstr_test::Main()
0779 {
0780 //const char* test = "TrimString" ;
0781 //const char* test = "StripComment" ;
0782 //const char* test = "IsInteger" ;
0783 //const char* test = "StartsWithElem" ;
0784 const char* test = "split" ;
0785
0786 const char* TEST = ssys::getenvvar("TEST", test );
0787 bool ALL = strcmp(TEST, "ALL") == 0 ;
0788
0789
0790 if( strcmp(TEST, "HasTail")==0 ) test_HasTail();
0791 else if(strcmp(TEST, "StripTail")==0 ) test_StripTail();
0792 else if(strcmp(TEST, "StripComment")==0 ) test_StripComment();
0793 else if(strcmp(TEST, "TrimString")==0 ) test_TrimString();
0794 else if(strcmp(TEST, "SideBySide")==0 ) test_SideBySide();
0795 else if(strcmp(TEST, "nullchar")==0 ) test_nullchar(true);
0796 else if(strcmp(TEST, "Write")==0 ) test_Write();
0797 else if(strcmp(TEST, "ParseIntSpecList64")==0 ) test_ParseIntSpecList<int64_t>();
0798 //else if(strcmp(TEST, "ParseIntSpecList32")==0 ) test_ParseIntSpecList<int>();
0799 else if(strcmp(TEST, "ParseIntSpecListDemo")==0 ) test_ParseIntSpecList_demo<int64_t>();
0800 else if(strcmp(TEST, "snprintf")==0 ) test_snprintf();
0801 else if(strcmp(TEST, "Format") == 0 ) test_Format();
0802 else if(strcmp(TEST, "TAG")==0 ) test_TAG();
0803 else if(strcmp(TEST, "StripTailUnique")==0 ) test_StripTail_Unique_0();
0804 else if(strcmp(TEST, "Extract") == 0 ) test_Extract();
0805 else if(strcmp(TEST, "Concat") == 0 ) test_Concat();
0806 else if(strcmp(TEST, "IsInteger") == 0 ) test_IsInteger();
0807
0808
0809 int rc = 0 ;
0810 if(ALL||0==strcmp(TEST,"Chop")) rc += Chop();
0811 if(ALL||0==strcmp(TEST,"chop")) rc += chop();
0812 if(ALL||0==strcmp(TEST,"prefix_suffix")) rc += prefix_suffix();
0813 if(ALL||0==strcmp(TEST,"StartsWithElem")) rc += StartsWithElem();
0814 if(ALL||0==strcmp(TEST,"split")) rc += split();
0815 if(ALL||0==strcmp(TEST,"ParseInt")) rc += ParseInt();
0816 if(ALL||0==strcmp(TEST,"ExtractSize")) rc += ExtractSize();
0817
0818
0819 return rc ;
0820 }
0821
0822 int main(int argc, char** argv)
0823 {
0824 return sstr_test::Main() ;
0825 }
0826 // ~/opticks/sysrap/tests/sstr_test.sh
0827
0828