home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 July / macformat-026.iso / mac / Shareware City / Developers / NString 1.0 beta / Sources / NString_Substring.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-21  |  18.2 KB  |  776 lines  |  [TEXT/KAHL]

  1.  
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <limits.h>
  5.  
  6. #include "NString.h"
  7. #include "NString_Misc.h"
  8.  
  9. //_________________________________________________________________________________
  10.  
  11. char *NString::string (void) const
  12. {
  13.     char *result;
  14.     
  15.     if ((result = (char *)malloc(sb->len+1)) == NULL)
  16.         OUT_OF_MEM("string (void) const");
  17.     strcpy(result, sb->str);
  18.     return (result);
  19. }
  20.  
  21. //_________________________________________________________________________________
  22.  
  23. NString NString::fromto (unsigned long int from, unsigned long int to) const
  24. {
  25.     unsigned long int new_length;
  26.     
  27.     if (sb->len == 0)                                                    // am I an empty string ?
  28.         return (*this);
  29.     if ((from > to) || (from > sb->len))                            //    empty range specified or range outside of NString ?
  30.         return NString();
  31.     if (to > sb->len)                                                        // "to" too big ?
  32.         to = sb->len - 1;
  33.     else
  34.         if (to > 0)
  35.             to--;
  36.         else
  37.             return NString();
  38.  
  39.     if (from > 0)
  40.         from--;
  41.         
  42.     if ((new_length = to - from + 1) == sb->len)
  43.         return (*this);
  44.     else
  45.     {
  46.         NString result(new_length);
  47.         
  48.         strncpy(result.sb->str, sb->str+from, new_length);
  49.         return (result);
  50.     }
  51. }
  52.  
  53. //_________________________________________________________________________________
  54.  
  55. NString& NString::cut(unsigned long int at, unsigned long int n)
  56. {    
  57.     const char *fname = "cut (unsigned long int, unsigned long int)";
  58.     unsigned long int final_part;
  59.     unsigned long int new_length;
  60.  
  61.     if (at > 0)
  62.         at--;
  63.     else
  64.         if (n > 0)
  65.             n--;
  66.  
  67.     if ((sb->len == 0) || (n == 0) || (at >= sb->len))
  68.         return (*this);
  69.     
  70.     if ((final_part = at + n) < at)                                                    // test for overflow
  71.     {
  72.         final_part = ULONG_MAX;
  73.         new_length = at;
  74.     }
  75.     else
  76.         new_length = (final_part >= sb->len) ? at : sb->len - n;
  77.     
  78.     if (sb->refs > 1)
  79.     {
  80.         strbody *old_sb = sb;
  81.         
  82.         if (! GetNewSB(new_length))
  83.             OUT_OF_MEM(fname);
  84.         if (at > 0)
  85.             memcpy(sb->str, old_sb->str, at);                                    // copy initial remaining part of string
  86.         if (final_part < old_sb->len)
  87.             strcpy(sb->str + at, old_sb->str + final_part);                // copy final remaining part of string
  88.     }
  89.     else
  90.     {
  91.         if (final_part < sb->len)                                                        // there is a final part to move
  92.             memmove(sb->str + at, sb->str + final_part, sb->len - final_part + 1);
  93.         else
  94.             sb->str[at] = '\0';                                                            // otherwise terminate string after initial part
  95.  
  96.         sb->len = new_length;
  97.  
  98.         if (! ReallocStrBuf(new_length))                                            // shrink string's memory block
  99.             OUT_OF_MEM(fname);                                                    // this "Out of Memory" should never happen ...
  100.     }
  101.     return (*this);
  102. }
  103.  
  104. //_________________________________________________________________________________
  105.  
  106. unsigned long int NString::leftpos(const char *s) const
  107. {
  108.     char *pos;
  109.     
  110.     if ((pos = strstr(sb->str, s)) != NULL)
  111.         return (unsigned long int)(pos - sb->str + 1);
  112.     else
  113.         return (0);
  114. }
  115.  
  116. //_________________________________________________________________________________
  117.  
  118. unsigned long int NString::leftpos(const char c) const
  119. {
  120.     unsigned long int i, pos = 0;
  121.     
  122.     if (sb->len == 0)
  123.         return (0);                                                                        // no character can be found in an empty string
  124.  
  125.     for (i=0; (i < sb->len) && (pos == 0); i++)
  126.         if (sb->str[i] == c)
  127.             pos = i+1;
  128.             
  129.     return (pos);
  130. }
  131.  
  132. //_________________________________________________________________________________
  133.  
  134. unsigned long int NString::leftpos (const Alphabet& a) const
  135. {
  136.     unsigned long int i, pos = 0;
  137.  
  138.     if (sb->len == 0)
  139.         return (0);                                                                        // no character can be found in an empty string
  140.     
  141.     for (i=0; (i < sb->len) && (pos == 0); i++)
  142.         if (a.contains(sb->str[i]))
  143.             pos = i+1;
  144.             
  145.     return (pos);
  146. }
  147.  
  148. //_________________________________________________________________________________
  149.  
  150. unsigned long int NString::rightpos(const char *s) const
  151. {
  152.     unsigned long int i, pos = 0, s_len = strlen(s);
  153.     
  154.     if (s_len == 0)
  155.         return (sb->len + 1);                                                            // an empty substring can be found everywhere
  156.     if (s_len > sb->len)
  157.         return (0);                                                                        // substring longer than entire NString
  158.     for (i=sb->len - s_len + 1; (i > 0) && (pos == 0); i--)            // Note: (i >= 0) is always TRUE for unsigned int,
  159.         if (sb->str[i-1] == s[0])                                                    //        so the range for i has been offset by +1
  160.             if (strncmp(sb->str + i-1, s, s_len) == 0)
  161.                 pos = i;
  162.             
  163.     return (pos);
  164. }
  165.  
  166. //_________________________________________________________________________________
  167.  
  168. unsigned long int NString::rightpos(const char c) const
  169. {
  170.     unsigned long int i, pos = 0;
  171.     
  172.     if (sb->len == 0)
  173.         return (0);                                                                        // no character can be found in an empty string
  174.         
  175.     for (i=sb->len; (i > 0) && (pos == 0); i--)                                // Note: (i >= 0) is always TRUE for unsigned int,
  176.         if (sb->str[i-1] == c)                                                        //        so the range for i has been offset by +1
  177.             pos = i;
  178.             
  179.     return (pos);
  180. }
  181.  
  182. //_________________________________________________________________________________
  183.  
  184. unsigned long int NString::rightpos(const Alphabet& a) const
  185. {
  186.     unsigned long int i, pos = 0;
  187.     
  188.     if (sb->len == 0)
  189.         return (0);                                                                        // no character can be found in an empty string
  190.         
  191.     for (i=sb->len; (i > 0) && (pos == 0); i--)                                // Note: (i >= 0) is always TRUE for unsigned int,
  192.         if (a.contains(sb->str[i-1]))                                                //        so the range for i has been offset by +1
  193.             pos = i;
  194.             
  195.     return (pos);
  196. }
  197.  
  198. //_________________________________________________________________________________
  199.  
  200. NString NString::leftof (const char *context) const
  201. {
  202.     unsigned long int pos = leftpos(context);
  203.     
  204.     if (pos == 0)
  205.         return (*this);
  206.  
  207.     return (to(pos-1));
  208. }
  209.  
  210. //_________________________________________________________________________________
  211.  
  212. NString NString::leftof (const char context) const
  213. {
  214.     unsigned long int pos = leftpos(context);
  215.     
  216.     if (pos == 0)
  217.         return (*this);
  218.  
  219.     return (to(pos-1));
  220. }
  221.  
  222. //_________________________________________________________________________________
  223.  
  224. NString NString::leftof (const NString& context) const
  225. {
  226.     unsigned long int pos = leftpos(context);
  227.     
  228.     if (pos == 0)
  229.         return (*this);
  230.  
  231.     return (to(pos-1));
  232. }
  233.  
  234. //_________________________________________________________________________________
  235.  
  236. NString NString::leftof (const Alphabet& context) const
  237. {
  238.     unsigned long int pos = leftpos(context);
  239.     
  240.     if (pos == 0)
  241.         return (*this);
  242.  
  243.     return (to(pos-1));
  244. }
  245.  
  246. //_________________________________________________________________________________
  247.  
  248. NString NString::atleft (const char *context) const
  249. {
  250.     unsigned long int pos = leftpos(context);
  251.     
  252.     if (pos == 0)
  253.         return NString();
  254.     
  255.     return (from(pos));
  256. }
  257.  
  258. //_________________________________________________________________________________
  259.  
  260. NString NString::atleft (const char context) const
  261. {
  262.     unsigned long int pos = leftpos(context);
  263.     
  264.     if (pos == 0)
  265.         return NString();
  266.     
  267.     return (from(pos));
  268. }
  269.  
  270. //_________________________________________________________________________________
  271.  
  272. NString NString::atleft (const NString& context) const
  273. {
  274.     unsigned long int pos = leftpos(context);
  275.     
  276.     if (pos == 0)
  277.         return NString();
  278.     
  279.     return (from(pos));
  280. }
  281.  
  282. //_________________________________________________________________________________
  283.  
  284. NString NString::atleft (const Alphabet& context) const
  285. {
  286.     unsigned long int pos = leftpos(context);
  287.     
  288.     if (pos == 0)
  289.         return NString();
  290.     
  291.     return (from(pos));
  292. }
  293.  
  294. //_________________________________________________________________________________
  295.  
  296. NString NString::toleft (const char *context) const
  297. {
  298.     unsigned long int pos = leftpos(context);
  299.     
  300.     if (pos == 0)
  301.         return (*this);
  302.         
  303.     return (to(pos + strlen(context) - 1));
  304. }
  305.  
  306. //_________________________________________________________________________________
  307.  
  308. NString NString::toleft (const char context) const
  309. {
  310.     unsigned long int pos = leftpos(context);
  311.     
  312.     if (pos == 0)
  313.         return (*this);
  314.         
  315.     return (to(pos));
  316. }
  317.  
  318. //_________________________________________________________________________________
  319.  
  320. NString NString::toleft (const NString& context) const
  321. {
  322.     unsigned long int pos = leftpos(context);
  323.     
  324.     if (pos == 0)
  325.         return (*this);
  326.         
  327.     return (to(pos + context.sb->len - 1));
  328. }
  329.  
  330. //_________________________________________________________________________________
  331.  
  332. NString NString::toleft (const Alphabet& context) const
  333. {
  334.     unsigned long int pos = leftpos(context);
  335.     
  336.     if (pos == 0)
  337.         return (*this);
  338.     
  339.     return (to(pos));                // the length of an alphabet-context is always 1 letter
  340. }
  341.  
  342. //_________________________________________________________________________________
  343.  
  344. NString NString::leftcut (const char *context) const
  345. {
  346.     unsigned long int pos = leftpos(context);
  347.     
  348.     if (pos == 0)
  349.         return NString();
  350.     
  351.     return (from(pos + strlen(context)));
  352. }
  353.  
  354. //_________________________________________________________________________________
  355.  
  356. NString NString::leftcut (const char context) const
  357. {
  358.     unsigned long int pos = leftpos(context);
  359.     
  360.     if (pos == 0)
  361.         return NString();
  362.     
  363.     return (from(pos + 1));
  364. }
  365.  
  366. //_________________________________________________________________________________
  367.  
  368. NString NString::leftcut (const NString& context) const
  369. {
  370.     unsigned long int pos = leftpos(context);
  371.     
  372.     if (pos == 0)
  373.         return NString();
  374.     
  375.     return (from(pos + context.sb->len));
  376. }
  377.  
  378. //_________________________________________________________________________________
  379.  
  380. NString NString::leftcut (const Alphabet& context) const
  381. {
  382.     unsigned long int pos = leftpos(context);
  383.     
  384.     if (pos == 0)
  385.         return NString();
  386.     
  387.     return (from(pos + 1));
  388. }
  389.  
  390. //_________________________________________________________________________________
  391.  
  392. NString NString::rightof (const char *context) const
  393. {
  394.     unsigned long int pos = rightpos(context);
  395.     
  396.     if (pos == 0)
  397.         return (*this);
  398.  
  399.     return (from(pos + strlen(context)));
  400. }
  401.  
  402. //_________________________________________________________________________________
  403.  
  404. NString NString::rightof (const char context) const
  405. {
  406.     unsigned long int pos = rightpos(context);
  407.     
  408.     if (pos == 0)
  409.         return (*this);
  410.  
  411.     return (from(pos + 1));
  412. }
  413.  
  414. //_________________________________________________________________________________
  415.  
  416. NString NString::rightof (const NString& context) const
  417. {
  418.     unsigned long int pos = rightpos(context);
  419.     
  420.     if (pos == 0)
  421.         return (*this);
  422.  
  423.     return (from(pos + context.sb->len));
  424. }
  425.  
  426. //_________________________________________________________________________________
  427.  
  428. NString NString::rightof (const Alphabet& context) const
  429. {
  430.     unsigned long int pos = rightpos(context);
  431.     
  432.     if (pos == 0)
  433.         return (*this);
  434.  
  435.     return (from(pos + 1));
  436. }
  437.  
  438. //_________________________________________________________________________________
  439.  
  440. NString NString::atright (const char *context) const
  441. {
  442.     unsigned long int pos = rightpos(context);
  443.     
  444.     if (pos == 0)
  445.         return (*this);
  446.     
  447.     return (from(pos));
  448. }
  449.  
  450. //_________________________________________________________________________________
  451.  
  452. NString NString::atright (const char context) const
  453. {
  454.     unsigned long int pos = rightpos(context);
  455.     
  456.     if (pos == 0)
  457.         return (*this);
  458.     
  459.     return (from(pos));
  460. }
  461.  
  462. //_________________________________________________________________________________
  463.  
  464. NString NString::atright (const NString& context) const
  465. {
  466.     unsigned long int pos = rightpos(context);
  467.     
  468.     if (pos == 0)
  469.         return (*this);
  470.     
  471.     return (from(pos));
  472. }
  473.  
  474. //_________________________________________________________________________________
  475.  
  476. NString NString::atright (const Alphabet& context) const
  477. {
  478.     unsigned long int pos = rightpos(context);
  479.     
  480.     if (pos == 0)
  481.         return (*this);
  482.     
  483.     return (from(pos));
  484. }
  485.  
  486. //_________________________________________________________________________________
  487.  
  488. NString NString::toright (const char *context) const
  489. {
  490.     unsigned long int pos = rightpos(context);
  491.     
  492.     if (pos == 0)
  493.         return NString();
  494.         
  495.     return (to(pos + strlen(context) - 1));
  496. }
  497.  
  498. //_________________________________________________________________________________
  499.  
  500. NString NString::toright (const char context) const
  501. {
  502.     unsigned long int pos = rightpos(context);
  503.     
  504.     if (pos == 0)
  505.         return NString();
  506.         
  507.     return (to(pos));
  508. }
  509.  
  510. //_________________________________________________________________________________
  511.  
  512. NString NString::toright (const NString& context) const
  513. {
  514.     unsigned long int pos = rightpos(context);
  515.     
  516.     if (pos == 0)
  517.         return NString();
  518.         
  519.     return (to(pos + context.sb->len - 1));
  520. }
  521.  
  522. //_________________________________________________________________________________
  523.  
  524. NString NString::toright (const Alphabet& context) const
  525. {
  526.     unsigned long int pos = rightpos(context);
  527.     
  528.     if (pos == 0)
  529.         return NString();
  530.         
  531.     return (to(pos));
  532. }
  533.  
  534. //_________________________________________________________________________________
  535.  
  536. NString NString::rightcut (const char *context) const
  537. {
  538.     unsigned long int pos = rightpos(context);
  539.     
  540.     if (pos == 0)
  541.         return NString();
  542.     
  543.     return (to(pos -1));
  544. }
  545.  
  546. //_________________________________________________________________________________
  547.  
  548. NString NString::rightcut (const char context) const
  549. {
  550.     unsigned long int pos = rightpos(context);
  551.     
  552.     if (pos == 0)
  553.         return NString();
  554.     
  555.     return (to(pos -1));
  556. }
  557.  
  558. //_________________________________________________________________________________
  559.  
  560. NString NString::rightcut (const NString& context) const
  561. {
  562.     unsigned long int pos = rightpos(context);
  563.     
  564.     if (pos == 0)
  565.         return NString();
  566.     
  567.     return (to(pos -1));
  568. }
  569.  
  570. //_________________________________________________________________________________
  571.  
  572. NString NString::rightcut (const Alphabet& context) const
  573. {
  574.     unsigned long int pos = rightpos(context);
  575.     
  576.     if (pos == 0)
  577.         return NString();
  578.     
  579.     return (to(pos -1));
  580. }
  581.  
  582. //_________________________________________________________________________________
  583.  
  584. int NString::endswith(const char *context) const
  585. {
  586.     unsigned long int ctx_len = strlen(context);
  587.     
  588.     if (ctx_len == 0)
  589.         return (1);                                                                        // an empty substring can be found everywhere
  590.     if (ctx_len > sb->len)
  591.         return (0);                                                                        // context longer than entire NString
  592.     return ((strncmp(sb->str + (sb->len - ctx_len), context, ctx_len)) ? 0 : 1);
  593. }
  594.  
  595. //_________________________________________________________________________________
  596.  
  597. NString span (const char context, const NString& s)
  598. {
  599.     char *ctx = "x";
  600.     
  601.     ctx[0] = context;
  602.     return (s.to(strspn(s.sb->str, ctx)));
  603. }
  604.  
  605. //_________________________________________________________________________________
  606.  
  607. NString span (const Alphabet& context, const NString& s)
  608. {
  609.     unsigned long int i;
  610.     
  611.     for (i = 0; (i < s.sb->len) && (context.contains(s.sb->str[i])); i++);
  612.     return (s.to(i));
  613. }
  614.  
  615. //_________________________________________________________________________________
  616.  
  617. NString span (const NString& s, const char context)
  618. {
  619.     unsigned long int i, pos = 0;
  620.     
  621.     if (s.sb->len == 0)
  622.         return (s);                                                                        // no character can be found in an empty string
  623.         
  624.     for (i=s.sb->len; (i > 0) && (pos == 0); i--)                            // Note: (i >= 0) is always TRUE for unsigned int,
  625.         if (s.sb->str[i-1] != context)                                                //        so the range for i has been offset by +1
  626.             pos = i;
  627.             
  628.     return (s.from(pos+1));
  629. }
  630.  
  631. //_________________________________________________________________________________
  632.  
  633. NString span (const NString& s, const Alphabet& context)
  634. {
  635.     unsigned long int i, pos = 0;
  636.     
  637.     if (s.sb->len == 0)
  638.         return (s);                                                                        // no character can be found in an empty string
  639.         
  640.     for (i=s.sb->len; (i > 0) && (pos == 0); i--)                            // Note: (i >= 0) is always TRUE for unsigned int,
  641.         if (! context.contains(s.sb->str[i-1]))                                    //        so the range for i has been offset by +1
  642.             pos = i;
  643.             
  644.     return (s.from(pos+1));
  645. }
  646.  
  647. //_________________________________________________________________________________
  648.  
  649. NString operator- (const char c, const NString& s)
  650. {
  651.     char *ctx = "x";
  652.     
  653.     ctx[0] = c;
  654.     return (s.from(strspn(s.sb->str, ctx)+1));
  655. }
  656.  
  657. //_________________________________________________________________________________
  658.  
  659. NString operator- (const Alphabet& ctx, const NString& s)
  660. {
  661.     unsigned long int i;
  662.     
  663.     for (i=0; (i < s.sb->len) && (ctx.contains(s.sb->str[i])); i++);
  664.     return (s.from(i+1));
  665. }
  666.  
  667. //_________________________________________________________________________________
  668.  
  669. NString NString::operator- (const char c) const
  670. {
  671.     unsigned long int i, pos = 0;
  672.     
  673.     if (sb->len == 0)
  674.         return (*this);                                                                        // no character can be found in an empty string
  675.         
  676.     for (i=sb->len; (i > 0) && (pos == 0); i--)                                    // Note: (i >= 0) is always TRUE for unsigned int,
  677.         if (sb->str[i-1] != c)                                                                //        so the range for i has been offset by +1
  678.             pos = i;
  679.             
  680.     return (to(pos));
  681. }
  682.  
  683. //_________________________________________________________________________________
  684.  
  685. NString NString::operator- (const Alphabet& ctx) const
  686. {
  687.     unsigned long int i, pos = 0;
  688.     
  689.     if (sb->len == 0)
  690.         return (*this);                                                                        // no character can be found in an empty string
  691.         
  692.     for (i=sb->len; (i > 0) && (pos == 0); i--)                                    // Note: (i >= 0) is always TRUE for unsigned int,
  693.         if (! ctx.contains(sb->str[i-1]))                                                //        so the range for i has been offset by +1
  694.             pos = i;
  695.             
  696.     return (to(pos));
  697. }
  698.  
  699. //_________________________________________________________________________________
  700.  
  701. NString& NString::operator-= (const char c)
  702. {
  703.     const char *fname = "operator-= (const char)";
  704.     char *ctx = "x";
  705.     unsigned long int newstart;
  706.     
  707.     ctx[0] = c;
  708.     if ((newstart = strspn(sb->str, ctx)) == 0)
  709.         return (*this);
  710.     
  711.     if (sb->refs > 1)
  712.     {
  713.         strbody *old_sb = sb;
  714.         
  715.         if (! GetNewSB(sb->len - newstart))
  716.             OUT_OF_MEM(fname);
  717.         if (sb->len == 0)
  718.             return (*this);
  719.         strcpy(sb->str, old_sb->str + newstart);
  720.     }
  721.     else
  722.     {    
  723.         unsigned long int new_len = sb->len - newstart;
  724.         
  725.         memmove(sb->str, sb->str + newstart, new_len + 1);
  726.         if (! ReallocStrBuf(new_len))                                                // shrink string buffer
  727.         {
  728.             sb->len = new_len;                                                            // necessary to keep the NString in a coherent state
  729.             OUT_OF_MEM(fname);                                                    // this "Out of Memory" should never happen ...
  730.         }
  731.         
  732.         sb->len = new_len;
  733.     }
  734.     
  735.     return (*this);
  736. }
  737.  
  738. //_________________________________________________________________________________
  739.  
  740. NString& NString::operator-= (const Alphabet& ctx)
  741. {
  742.     const char *fname = "operator-= (const Alphabet&)";
  743.     unsigned long int newstart;
  744.     
  745.     for (newstart=0; (newstart < sb->len) && (ctx.contains(sb->str[newstart])); newstart++);
  746.  
  747.     if (newstart == 0)
  748.         return (*this);
  749.     
  750.     if (sb->refs > 1)
  751.     {
  752.         strbody *old_sb = sb;
  753.         
  754.         if (! GetNewSB(sb->len - newstart))
  755.             OUT_OF_MEM(fname);
  756.         if (sb->len == 0)
  757.             return (*this);
  758.         strcpy(sb->str, old_sb->str + newstart);
  759.     }
  760.     else
  761.     {    
  762.         unsigned long int new_len = sb->len - newstart;
  763.         
  764.         memmove(sb->str, sb->str + newstart, new_len + 1);
  765.         if (! ReallocStrBuf(new_len))                                                // shrink string buffer
  766.         {
  767.             sb->len = new_len;                                                            // necessary to keep the NString in a coherent state
  768.             OUT_OF_MEM(fname);                                                    // this "Out of Memory" should never happen ...
  769.         }
  770.         
  771.         sb->len = new_len;
  772.     }
  773.     
  774.     return (*this);
  775. }
  776.