/src/libutil/pystring.cpp

https://github.com/mgmt1969/oiio · C++ · 1056 lines · 682 code · 210 blank · 164 comment · 197 complexity · 649991131fc7b3c7f293f9e403b9065e MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) 2008, Sony Pictures Imageworks
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // Redistributions of source code must retain the above copyright notice,
  10. // this list of conditions and the following disclaimer.
  11. // Redistributions in binary form must reproduce the above copyright
  12. // notice, this list of conditions and the following disclaimer in the
  13. // documentation and/or other materials provided with the distribution.
  14. // Neither the name of the organization Sony Pictures Imageworks nor the
  15. // names of its contributors
  16. // may be used to endorse or promote products derived from this software
  17. // without specific prior written permission.
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. // "AS
  20. // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  21. // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  22. // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER
  24. // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. // SPECIAL,
  26. // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28. // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29. // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30. // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ///////////////////////////////////////////////////////////////////////////////
  33. #include <ctype.h>
  34. #include <string.h>
  35. #include <iostream>
  36. #include <algorithm>
  37. #include "pystring.h"
  38. OIIO_NAMESPACE_ENTER
  39. {
  40. namespace pystring
  41. {
  42. namespace {
  43. //////////////////////////////////////////////////////////////////////////////////////////////
  44. /// why doesn't the std::reverse work?
  45. ///
  46. void reverse_strings( std::vector< std::string > & result)
  47. {
  48. for (std::vector< std::string >::size_type i = 0; i < result.size() / 2; i++ )
  49. {
  50. std::swap(result[i], result[result.size() - 1 - i]);
  51. }
  52. }
  53. //////////////////////////////////////////////////////////////////////////////////////////////
  54. ///
  55. ///
  56. void split_whitespace( const std::string & str, std::vector< std::string > & result, int maxsplit )
  57. {
  58. std::string::size_type i, j, len = str.size();
  59. for (i = j = 0; i < len; )
  60. {
  61. while ( i < len && ::isspace( str[i] ) ) i++;
  62. j = i;
  63. while ( i < len && ! ::isspace( str[i]) ) i++;
  64. if (j < i)
  65. {
  66. if ( maxsplit-- <= 0 ) break;
  67. result.push_back( str.substr( j, i - j ));
  68. while ( i < len && ::isspace( str[i])) i++;
  69. j = i;
  70. }
  71. }
  72. if (j < len)
  73. {
  74. result.push_back( str.substr( j, len - j ));
  75. }
  76. }
  77. //////////////////////////////////////////////////////////////////////////////////////////////
  78. ///
  79. ///
  80. void rsplit_whitespace( const std::string & str, std::vector< std::string > & result, int maxsplit )
  81. {
  82. std::string::size_type len = str.size();
  83. std::string::size_type i, j;
  84. for (i = j = len; i > 0; )
  85. {
  86. while ( i > 0 && ::isspace( str[i - 1] ) ) i--;
  87. j = i;
  88. while ( i > 0 && ! ::isspace( str[i - 1]) ) i--;
  89. if (j > i)
  90. {
  91. if ( maxsplit-- <= 0 ) break;
  92. result.push_back( str.substr( i, j - i ));
  93. while ( i > 0 && ::isspace( str[i - 1])) i--;
  94. j = i;
  95. }
  96. }
  97. if (j > 0)
  98. {
  99. result.push_back( str.substr( 0, j ));
  100. }
  101. //std::reverse( result, result.begin(), result.end() );
  102. reverse_strings( result );
  103. }
  104. } //anonymous namespace
  105. //////////////////////////////////////////////////////////////////////////////////////////////
  106. ///
  107. ///
  108. void split( const std::string & str, std::vector< std::string > & result, const std::string & sep, int maxsplit )
  109. {
  110. result.clear();
  111. if ( maxsplit < 0 ) maxsplit = MAX_32BIT_INT;//result.max_size();
  112. if ( sep.size() == 0 )
  113. {
  114. split_whitespace( str, result, maxsplit );
  115. return;
  116. }
  117. std::string::size_type i,j, len = str.size(), n = sep.size();
  118. i = j = 0;
  119. while ( i+n <= len )
  120. {
  121. if ( str[i] == sep[0] && str.substr( i, n ) == sep )
  122. {
  123. if ( maxsplit-- <= 0 ) break;
  124. result.push_back( str.substr( j, i - j ) );
  125. i = j = i + n;
  126. }
  127. else
  128. {
  129. i++;
  130. }
  131. }
  132. result.push_back( str.substr( j, len-j ) );
  133. }
  134. //////////////////////////////////////////////////////////////////////////////////////////////
  135. ///
  136. ///
  137. void rsplit( const std::string & str, std::vector< std::string > & result, const std::string & sep, int maxsplit )
  138. {
  139. if ( maxsplit < 0 )
  140. {
  141. split( str, result, sep, 0 );
  142. return;
  143. }
  144. result.clear();
  145. if ( sep.size() == 0 )
  146. {
  147. rsplit_whitespace( str, result, maxsplit );
  148. return;
  149. }
  150. std::string::size_type i,j, len = str.size(), n = sep.size();
  151. i = j = len;
  152. while ( i > n )
  153. {
  154. if ( str[i - 1] == sep[n - 1] && str.substr( i - n, n ) == sep )
  155. {
  156. if ( maxsplit-- <= 0 ) break;
  157. result.push_back( str.substr( i, j - i ) );
  158. i = j = i - n;
  159. }
  160. else
  161. {
  162. i--;
  163. }
  164. }
  165. result.push_back( str.substr( 0, j ) );
  166. reverse_strings( result );
  167. }
  168. //////////////////////////////////////////////////////////////////////////////////////////////
  169. ///
  170. ///
  171. #define LEFTSTRIP 0
  172. #define RIGHTSTRIP 1
  173. #define BOTHSTRIP 2
  174. //////////////////////////////////////////////////////////////////////////////////////////////
  175. ///
  176. ///
  177. bool __substrcmp( const std::string & str, const std::string & str2, std::string::size_type pos )
  178. {
  179. std::string::size_type len = str.size(), len2 = str2.size();
  180. if ( pos + len2 > len )
  181. {
  182. return false;
  183. }
  184. for ( std::string::size_type i = 0; i < len2; ++i )
  185. {
  186. if ( str[pos + i] != str2[i] )
  187. {
  188. return false;
  189. }
  190. }
  191. return true;
  192. }
  193. //////////////////////////////////////////////////////////////////////////////////////////////
  194. ///
  195. ///
  196. std::string do_strip( const std::string & str, int striptype, const std::string & chars )
  197. {
  198. std::string::size_type len = str.size(), i, j, charslen = chars.size();
  199. if ( charslen == 0 )
  200. {
  201. i = 0;
  202. if ( striptype != RIGHTSTRIP )
  203. {
  204. while ( i < len && ::isspace( str[i] ) )
  205. {
  206. i++;
  207. }
  208. }
  209. j = len;
  210. if ( striptype != LEFTSTRIP )
  211. {
  212. do
  213. {
  214. j--;
  215. }
  216. while (j >= i && ::isspace(str[j]));
  217. j++;
  218. }
  219. }
  220. else
  221. {
  222. const char * sep = chars.c_str();
  223. i = 0;
  224. if ( striptype != RIGHTSTRIP )
  225. {
  226. while ( i < len && memchr(sep, str[i], charslen) )
  227. {
  228. i++;
  229. }
  230. }
  231. j = len;
  232. if (striptype != LEFTSTRIP)
  233. {
  234. do
  235. {
  236. j--;
  237. }
  238. while (j >= i && memchr(sep, str[j], charslen) );
  239. j++;
  240. }
  241. }
  242. if ( i == 0 && j == len )
  243. {
  244. return str;
  245. }
  246. else
  247. {
  248. return str.substr( i, j - i );
  249. }
  250. }
  251. //////////////////////////////////////////////////////////////////////////////////////////////
  252. ///
  253. ///
  254. void partition( const std::string & str, const std::string & sep, std::vector< std::string > & result )
  255. {
  256. result.resize(3);
  257. int index = find( str, sep );
  258. if ( index < 0 )
  259. {
  260. result[0] = str;
  261. result[1] = "";
  262. result[2] = "";
  263. }
  264. else
  265. {
  266. result[0] = str.substr( 0, index );
  267. result[1] = sep;
  268. result[2] = str.substr( index + sep.size(), str.size() );
  269. }
  270. }
  271. //////////////////////////////////////////////////////////////////////////////////////////////
  272. ///
  273. ///
  274. void rpartition( const std::string & str, const std::string & sep, std::vector< std::string > & result )
  275. {
  276. result.resize(3);
  277. int index = rfind( str, sep );
  278. if ( index < 0 )
  279. {
  280. result[0] = "";
  281. result[1] = "";
  282. result[2] = str;
  283. }
  284. else
  285. {
  286. result[0] = str.substr( 0, index );
  287. result[1] = sep;
  288. result[2] = str.substr( index + sep.size(), str.size() );
  289. }
  290. }
  291. //////////////////////////////////////////////////////////////////////////////////////////////
  292. ///
  293. ///
  294. std::string strip( const std::string & str, const std::string & chars )
  295. {
  296. return do_strip( str, BOTHSTRIP, chars );
  297. }
  298. //////////////////////////////////////////////////////////////////////////////////////////////
  299. ///
  300. ///
  301. std::string lstrip( const std::string & str, const std::string & chars )
  302. {
  303. return do_strip( str, LEFTSTRIP, chars );
  304. }
  305. //////////////////////////////////////////////////////////////////////////////////////////////
  306. ///
  307. ///
  308. std::string rstrip( const std::string & str, const std::string & chars )
  309. {
  310. return do_strip( str, RIGHTSTRIP, chars );
  311. }
  312. //////////////////////////////////////////////////////////////////////////////////////////////
  313. ///
  314. ///
  315. std::string join( const std::string & str, const std::vector< std::string > & seq )
  316. {
  317. std::vector< std::string >::size_type seqlen = seq.size(), i;
  318. if ( seqlen == 0 ) return "";
  319. if ( seqlen == 1 ) return seq[0];
  320. std::string result( seq[0] );
  321. for ( i = 1; i < seqlen; ++i )
  322. {
  323. result += str + seq[i];
  324. }
  325. return result;
  326. }
  327. //////////////////////////////////////////////////////////////////////////////////////////////
  328. ///
  329. ///
  330. int __adjustslicepos( std::string::size_type len, int pos )
  331. {
  332. int intlen = len, value;
  333. if ( pos < 0 )
  334. {
  335. value = intlen + pos;
  336. }
  337. else
  338. {
  339. value = pos;
  340. }
  341. if ( value < 0 )
  342. {
  343. value = 0;
  344. }
  345. else if ( value > ( int ) len )
  346. {
  347. value = len;
  348. }
  349. return value;
  350. }
  351. //////////////////////////////////////////////////////////////////////////////////////////////
  352. ///
  353. ///
  354. bool startswith( const std::string & str, const std::string & prefix, int start, int end )
  355. {
  356. std::string::size_type startp, endp;
  357. startp = __adjustslicepos( str.size(), start );
  358. endp = __adjustslicepos( str.size(), end );
  359. if ( start > (int) str.size() ) return false;
  360. if ( endp - startp < prefix.size() ) return false;
  361. return __substrcmp( str, prefix, startp );
  362. }
  363. //////////////////////////////////////////////////////////////////////////////////////////////
  364. ///
  365. ///
  366. bool endswith( const std::string & str, const std::string & suffix, int start, int end )
  367. {
  368. std::string::size_type startp, endp;
  369. startp = __adjustslicepos( str.size(), start );
  370. endp = __adjustslicepos( str.size(), end );
  371. int upper = endp;
  372. int lower = ( upper - suffix.size() ) > startp ? ( upper - suffix.size() ) : startp;
  373. if ( start > (int) str.size() ) return false;
  374. if ( upper - lower < ( int ) suffix.size() )
  375. {
  376. return false;
  377. }
  378. return __substrcmp(str, suffix, lower );
  379. }
  380. //////////////////////////////////////////////////////////////////////////////////////////////
  381. ///
  382. ///
  383. bool isalnum( const std::string & str )
  384. {
  385. std::string::size_type len = str.size(), i;
  386. if ( len == 0 ) return false;
  387. if( len == 1 )
  388. {
  389. return ::isalnum( str[0] );
  390. }
  391. for ( i = 0; i < len; ++i )
  392. {
  393. if ( !::isalnum( str[i] ) ) return false;
  394. }
  395. return true;
  396. }
  397. //////////////////////////////////////////////////////////////////////////////////////////////
  398. ///
  399. ///
  400. bool isalpha( const std::string & str )
  401. {
  402. std::string::size_type len = str.size(), i;
  403. if ( len == 0 ) return false;
  404. if( len == 1 ) return ::isalpha( (int) str[0] );
  405. for ( i = 0; i < len; ++i )
  406. {
  407. if ( !::isalpha( (int) str[i] ) ) return false;
  408. }
  409. return true;
  410. }
  411. //////////////////////////////////////////////////////////////////////////////////////////////
  412. ///
  413. ///
  414. bool isdigit( const std::string & str )
  415. {
  416. std::string::size_type len = str.size(), i;
  417. if ( len == 0 ) return false;
  418. if( len == 1 ) return ::isdigit( str[0] );
  419. for ( i = 0; i < len; ++i )
  420. {
  421. if ( ! ::isdigit( str[i] ) ) return false;
  422. }
  423. return true;
  424. }
  425. //////////////////////////////////////////////////////////////////////////////////////////////
  426. ///
  427. ///
  428. bool islower( const std::string & str )
  429. {
  430. std::string::size_type len = str.size(), i;
  431. if ( len == 0 ) return false;
  432. if( len == 1 ) return ::islower( str[0] );
  433. for ( i = 0; i < len; ++i )
  434. {
  435. if ( !::islower( str[i] ) ) return false;
  436. }
  437. return true;
  438. }
  439. //////////////////////////////////////////////////////////////////////////////////////////////
  440. ///
  441. ///
  442. bool isspace( const std::string & str )
  443. {
  444. std::string::size_type len = str.size(), i;
  445. if ( len == 0 ) return false;
  446. if( len == 1 ) return ::isspace( str[0] );
  447. for ( i = 0; i < len; ++i )
  448. {
  449. if ( !::isspace( str[i] ) ) return false;
  450. }
  451. return true;
  452. }
  453. //////////////////////////////////////////////////////////////////////////////////////////////
  454. ///
  455. ///
  456. bool istitle( const std::string & str )
  457. {
  458. std::string::size_type len = str.size(), i;
  459. if ( len == 0 ) return false;
  460. if ( len == 1 ) return ::isupper( str[0] );
  461. bool cased = false, previous_is_cased = false;
  462. for ( i = 0; i < len; ++i )
  463. {
  464. if ( ::isupper( str[i] ) )
  465. {
  466. if ( previous_is_cased )
  467. {
  468. return false;
  469. }
  470. previous_is_cased = true;
  471. cased = true;
  472. }
  473. else if ( ::islower( str[i] ) )
  474. {
  475. if (!previous_is_cased)
  476. {
  477. return false;
  478. }
  479. previous_is_cased = true;
  480. cased = true;
  481. }
  482. else
  483. {
  484. previous_is_cased = false;
  485. }
  486. }
  487. return cased;
  488. }
  489. //////////////////////////////////////////////////////////////////////////////////////////////
  490. ///
  491. ///
  492. bool isupper( const std::string & str )
  493. {
  494. std::string::size_type len = str.size(), i;
  495. if ( len == 0 ) return false;
  496. if( len == 1 ) return ::isupper( str[0] );
  497. for ( i = 0; i < len; ++i )
  498. {
  499. if ( !::isupper( str[i] ) ) return false;
  500. }
  501. return true;
  502. }
  503. //////////////////////////////////////////////////////////////////////////////////////////////
  504. ///
  505. ///
  506. std::string capitalize( const std::string & str )
  507. {
  508. std::string s( str );
  509. std::string::size_type len = s.size(), i;
  510. if ( len > 0)
  511. {
  512. if (::islower(s[0])) s[0] = ::toupper( s[0] );
  513. }
  514. for ( i = 1; i < len; ++i )
  515. {
  516. if (::isupper(s[i])) s[i] = ::tolower( s[i] );
  517. }
  518. return s;
  519. }
  520. //////////////////////////////////////////////////////////////////////////////////////////////
  521. ///
  522. ///
  523. std::string lower( const std::string & str )
  524. {
  525. std::string s( str );
  526. std::string::size_type len = s.size(), i;
  527. for ( i = 0; i < len; ++i )
  528. {
  529. if ( ::isupper( s[i] ) ) s[i] = ::tolower( s[i] );
  530. }
  531. return s;
  532. }
  533. //////////////////////////////////////////////////////////////////////////////////////////////
  534. ///
  535. ///
  536. std::string upper( const std::string & str )
  537. {
  538. std::string s( str ) ;
  539. std::string::size_type len = s.size(), i;
  540. for ( i = 0; i < len; ++i )
  541. {
  542. if ( ::islower( s[i] ) ) s[i] = ::toupper( s[i] );
  543. }
  544. return s;
  545. }
  546. //////////////////////////////////////////////////////////////////////////////////////////////
  547. ///
  548. ///
  549. std::string swapcase( const std::string & str )
  550. {
  551. std::string s( str );
  552. std::string::size_type len = s.size(), i;
  553. for ( i = 0; i < len; ++i )
  554. {
  555. if ( ::islower( s[i] ) ) s[i] = ::toupper( s[i] );
  556. else if (::isupper( s[i] ) ) s[i] = ::tolower( s[i] );
  557. }
  558. return s;
  559. }
  560. //////////////////////////////////////////////////////////////////////////////////////////////
  561. ///
  562. ///
  563. std::string title( const std::string & str )
  564. {
  565. std::string s( str );
  566. std::string::size_type len = s.size(), i;
  567. bool previous_is_cased = false;
  568. for ( i = 0; i < len; ++i )
  569. {
  570. int c = s[i];
  571. if ( ::islower(c) )
  572. {
  573. if ( !previous_is_cased )
  574. {
  575. s[i] = ::toupper(c);
  576. }
  577. previous_is_cased = true;
  578. }
  579. else if ( ::isupper(c) )
  580. {
  581. if ( previous_is_cased )
  582. {
  583. s[i] = ::tolower(c);
  584. }
  585. previous_is_cased = true;
  586. }
  587. else
  588. {
  589. previous_is_cased = false;
  590. }
  591. }
  592. return s;
  593. }
  594. //////////////////////////////////////////////////////////////////////////////////////////////
  595. ///
  596. ///
  597. std::string translate( const std::string & str, const std::string & table, const std::string & deletechars )
  598. {
  599. std::string s;
  600. std::string::size_type len = str.size(), dellen = deletechars.size();
  601. if ( table.size() != 256 )
  602. {
  603. //raise exception instead
  604. return str;
  605. }
  606. //if nothing is deleted, use faster code
  607. if ( dellen == 0 )
  608. {
  609. s = str;
  610. for ( std::string::size_type i = 0; i < len; ++i )
  611. {
  612. s[i] = table[ s[i] ];
  613. }
  614. return s;
  615. }
  616. int trans_table[256];
  617. for ( int i = 0; i < 256; i++)
  618. {
  619. trans_table[i] = table[i];
  620. }
  621. for ( std::string::size_type i = 0; i < dellen; i++)
  622. {
  623. trans_table[(int) deletechars[i] ] = -1;
  624. }
  625. for ( std::string::size_type i = 0; i < len; ++i )
  626. {
  627. if ( trans_table[ (int) str[i] ] != -1 )
  628. {
  629. s += table[ s[i] ];
  630. }
  631. }
  632. return s;
  633. }
  634. //////////////////////////////////////////////////////////////////////////////////////////////
  635. ///
  636. ///
  637. std::string zfill( const std::string & str, int width )
  638. {
  639. std::string::size_type len = str.size();
  640. if ( ( int ) len >= width )
  641. {
  642. return str;
  643. }
  644. std::string s( str );
  645. int fill = width - len;
  646. s = std::string( fill, '0' ) + s;
  647. if ( s[fill] == '+' || s[fill] == '-' )
  648. {
  649. s[0] = s[fill];
  650. s[fill] = '0';
  651. }
  652. return s;
  653. }
  654. //////////////////////////////////////////////////////////////////////////////////////////////
  655. ///
  656. ///
  657. std::string ljust( const std::string & str, int width )
  658. {
  659. std::string::size_type len = str.size();
  660. if ( (( int ) len ) >= width ) return str;
  661. return str + std::string( width - len, ' ' );
  662. }
  663. //////////////////////////////////////////////////////////////////////////////////////////////
  664. ///
  665. ///
  666. std::string rjust( const std::string & str, int width )
  667. {
  668. std::string::size_type len = str.size();
  669. if ( (( int ) len ) >= width ) return str;
  670. return std::string( width - len, ' ' ) + str;
  671. }
  672. //////////////////////////////////////////////////////////////////////////////////////////////
  673. ///
  674. ///
  675. std::string center( const std::string & str, int width )
  676. {
  677. std::string::size_type len = str.size();
  678. int marg, left;
  679. if ( (( int ) len ) >= width ) return str;
  680. marg = width - len;
  681. left = marg / 2 + (marg & width & 1);
  682. return std::string( left, ' ' ) + str + std::string( marg - left, ' ' );
  683. }
  684. //////////////////////////////////////////////////////////////////////////////////////////////
  685. ///
  686. ///
  687. int find( const std::string & str, const std::string & sub, int start, int end )
  688. {
  689. std::string::size_type startp, endp;
  690. startp = __adjustslicepos( str.size(), start );
  691. endp = __adjustslicepos( str.size(), end );
  692. std::string::size_type result;
  693. result = str.find( sub, startp );
  694. if( result == std::string::npos || result >= endp)
  695. {
  696. return -1;
  697. }
  698. return result;
  699. }
  700. //////////////////////////////////////////////////////////////////////////////////////////////
  701. ///
  702. ///
  703. int index( const std::string & str, const std::string & sub, int start, int end )
  704. {
  705. return find( str, sub, start, end );
  706. }
  707. //////////////////////////////////////////////////////////////////////////////////////////////
  708. ///
  709. ///
  710. int rfind( const std::string & str, const std::string & sub, int start, int end )
  711. {
  712. std::string::size_type startp, endp;
  713. startp = __adjustslicepos( str.size(), start );
  714. endp = __adjustslicepos( str.size(), end );
  715. std::string::size_type result;
  716. result = str.rfind( sub, endp );
  717. if( result == std::string::npos || result < startp ) return -1;
  718. return result;
  719. }
  720. //////////////////////////////////////////////////////////////////////////////////////////////
  721. ///
  722. ///
  723. int rindex( const std::string & str, const std::string & sub, int start, int end )
  724. {
  725. return rfind( str, sub, start, end );
  726. }
  727. //////////////////////////////////////////////////////////////////////////////////////////////
  728. ///
  729. ///
  730. std::string expandtabs( const std::string & str, int tabsize )
  731. {
  732. std::string s( str );
  733. std::string::size_type len = str.size(), i = 0;
  734. int offset = 0;
  735. int j = 0;
  736. for ( i = 0; i < len; ++i )
  737. {
  738. if ( str[i] == '\t' )
  739. {
  740. if ( tabsize > 0 )
  741. {
  742. int fillsize = tabsize - (j % tabsize);
  743. j += fillsize;
  744. s.replace( i + offset, 1, std::string( fillsize, ' ' ));
  745. offset += fillsize - 1;
  746. }
  747. else
  748. {
  749. s.replace( i + offset, 1, "" );
  750. offset -= 1;
  751. }
  752. }
  753. else
  754. {
  755. j++;
  756. if (str[i] == '\n' || str[i] == '\r')
  757. {
  758. j = 0;
  759. }
  760. }
  761. }
  762. return s;
  763. }
  764. //////////////////////////////////////////////////////////////////////////////////////////////
  765. ///
  766. ///
  767. int count( const std::string & str, const std::string & substr, int start, int end )
  768. {
  769. int nummatches = 0;
  770. int cursor = start;
  771. while ( 1 )
  772. {
  773. cursor = find( str, substr, cursor, end );
  774. if ( cursor < 0 ) break;
  775. cursor += substr.size();
  776. nummatches += 1;
  777. }
  778. return nummatches;
  779. }
  780. //////////////////////////////////////////////////////////////////////////////////////////////
  781. ///
  782. ///
  783. std::string replace( const std::string & str, const std::string & oldstr, const std::string & newstr, int count )
  784. {
  785. int sofar = 0;
  786. int cursor = 0;
  787. std::string s( str );
  788. std::string::size_type oldlen = oldstr.size(), newlen = newstr.size();
  789. while ( ( cursor = find( s, oldstr, cursor ) ) != -1 )
  790. {
  791. if ( count > -1 && sofar >= count )
  792. {
  793. break;
  794. }
  795. s.replace( cursor, oldlen, newstr );
  796. cursor += newlen;
  797. ++sofar;
  798. }
  799. return s;
  800. }
  801. //////////////////////////////////////////////////////////////////////////////////////////////
  802. ///
  803. ///
  804. void splitlines( const std::string & str, std::vector< std::string > & result, bool keepends )
  805. {
  806. result.clear();
  807. std::string::size_type len = str.size(), i, j, eol;
  808. for (i = j = 0; i < len; )
  809. {
  810. while (i < len && str[i] != '\n' && str[i] != '\r') i++;
  811. eol = i;
  812. if (i < len)
  813. {
  814. if (str[i] == '\r' && i + 1 < len && str[i+1] == '\n')
  815. {
  816. i += 2;
  817. }
  818. else
  819. {
  820. i++;
  821. }
  822. if (keepends)
  823. eol = i;
  824. }
  825. result.push_back( str.substr( j, eol - j ) );
  826. j = i;
  827. }
  828. if (j < len)
  829. {
  830. result.push_back( str.substr( j, len - j ) );
  831. }
  832. }
  833. //////////////////////////////////////////////////////////////////////////////////////////////
  834. ///
  835. ///
  836. std::string slice( const std::string & str, int start, int end )
  837. {
  838. std::string::size_type startp, endp;
  839. startp = __adjustslicepos( str.size(), start );
  840. endp = __adjustslicepos( str.size(), end );
  841. if ( startp >= endp ) return "";
  842. return str.substr( startp, endp - startp );
  843. }
  844. }//namespace pystring
  845. }
  846. OIIO_NAMESPACE_EXIT