mstring.cxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:21k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /* ====================================================================
  2.  * The Vovida Software License, Version 1.0 
  3.  * 
  4.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  * 
  18.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  19.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  20.  *    not be used to endorse or promote products derived from this
  21.  *    software without prior written permission. For written
  22.  *    permission, please contact vocal@vovida.org.
  23.  *
  24.  * 4. Products derived from this software may not be called "VOCAL", nor
  25.  *    may "VOCAL" appear in their name, without prior written
  26.  *    permission of Vovida Networks, Inc.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  29.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  31.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  32.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  33.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  34.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  36.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  37.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  39.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  40.  * DAMAGE.
  41.  * 
  42.  * ====================================================================
  43.  * 
  44.  * This software consists of voluntary contributions made by Vovida
  45.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  46.  * Inc.  For more information on Vovida Networks, Inc., please see
  47.  * <http://www.vovida.org/>.
  48.  *
  49.  */
  50. static const char* const mstring_cxx_Version =
  51.     "$Id: mstring.cxx,v 1.8 2000/12/18 23:49:08 bko Exp $";
  52. #include <stdio.h>
  53. #include "mstring.hxx"
  54. #include "vsock.hxx"
  55. namespace std
  56. {
  57. //--------------------------------------------------------------------------
  58. mstring & mstring::assigni(int val, const char *format)
  59. {
  60.     char buf[64];
  61.     sprintf(buf, format, val);
  62.     return *this = buf;
  63. }
  64. //--------------------------------------------------------------------------
  65. mstring & mstring::assignd(double val, const char *format)
  66. {
  67.     char buf[64];
  68.     sprintf(buf, format, val);
  69.     return *this = buf;
  70. }
  71. //--------------------------------------------------------------------------
  72. mstring & mstring::ltrims(const string &s)
  73. {
  74.     erase(0, find_first_not_of(s));
  75.     return *this;
  76. }
  77. //--------------------------------------------------------------------------
  78. mstring & mstring::rtrims(const string &s)
  79. {
  80.     size_type pos = find_last_not_of(s);
  81.     if (pos == string::npos) pos = 0;
  82.     else pos++;
  83.     erase(pos);
  84.     return *this;
  85. }
  86. //--------------------------------------------------------------------------
  87. mstring & mstring::toleft(unsigned newlen, char fill, bool cut)
  88. {
  89.     unsigned lstr = length();
  90.     if (lstr < newlen)
  91.     {
  92.         insert(lstr, newlen - lstr, fill);
  93.     }
  94.     if (cut && newlen < lstr)
  95.     {
  96.         erase(newlen, string::npos);
  97.     }
  98.     return *this;
  99. }
  100. //--------------------------------------------------------------------------
  101. mstring & mstring::toright(unsigned newlen, char fill, bool cut)
  102. {
  103.     unsigned lstr = length();
  104.     if (lstr < newlen)
  105.     {
  106.         insert(size_type(0), newlen - lstr, fill);
  107.     }
  108.     if (cut && newlen < lstr)
  109.     {
  110.         erase(size_type(0), lstr - newlen);
  111.     }
  112.     return *this;
  113. }
  114. //--------------------------------------------------------------------------
  115. unsigned mstring::replace_all(const string &find_str, const string &repl_str)
  116. {
  117.     size_type pos = 0;
  118.     size_type find_len = find_str.length();
  119.     size_type repl_len = repl_str.length();
  120.     unsigned nrepl = 0;
  121.     while ((pos = find(find_str, pos)) != string::npos)
  122.     {
  123.         replace(pos, find_len, repl_str);
  124.         pos += repl_len;
  125.         nrepl++;
  126.     }
  127.     return nrepl;
  128. }
  129. //--------------------------------------------------------------------------
  130. int mstring::compare(const string &str, size_type len) const
  131. {
  132.     if (len == string::npos)
  133.     {
  134.         return strcmp(c_str(), str.c_str());
  135.     }
  136.     return strncmp(c_str(), str.c_str(), len);
  137. }
  138. //--------------------------------------------------------------------------
  139. int mstring::comparei(const string &str, size_type len) const
  140. {
  141.     if (len == string::npos)
  142.     {
  143.         return strcasecmp(c_str(), str.c_str());
  144.     }
  145.     return strncasecmp(c_str(), str.c_str(), len);
  146. }
  147. //--------------------------------------------------------------------------
  148. mstring & mstring::tab2sp(unsigned tab_size)
  149. {
  150.     size_type pos = 0;
  151.     while ((pos = find('t')) != string::npos)
  152.     {
  153.         size_type n_sp = tab_size - pos % tab_size;
  154.         replace(pos, 1, n_sp, ' ');
  155.         pos += n_sp;
  156.     }
  157.     return *this;
  158. }
  159. //---------------------------------------------------------------------------------
  160. mstring & mstring::ins_pair(const string &chrset, char pair_symb)
  161. {
  162.     string::size_type i;
  163.     char prev = 0;
  164.     for (i = 0; i < length(); ++i)
  165.     {
  166.         if ((chrset.find((*this)[i]) != string::npos) == (prev != pair_symb))
  167.         {
  168.             insert(i++, 1, pair_symb);
  169.         }
  170.         prev = (*this)[i];
  171.     }
  172.     if (i > 0 && (*this)[i - 1] == pair_symb) append(1, pair_symb);
  173.     return *this;
  174. }
  175. //---------------------------------------------------------------------------------
  176. mstring & mstring::del_pair(char pair_symb)
  177. {
  178.     string::size_type i;
  179.     for (i = 0; i < length(); i++)
  180.     {
  181.         if ((*this)[i] == pair_symb)
  182.         {
  183.             erase(i, 1);
  184.             if ((*this)[i] == 0) break;
  185.         }
  186.     }
  187.     return *this;
  188. }
  189. //---------------------------------------------------------------------------------
  190. mstring & mstring::ins_escaped(const string &chrset, char escaped_symb)
  191. {
  192.     ///!!! for further implementation
  193.     return *this;
  194. }
  195. //---------------------------------------------------------------------------------
  196. mstring & mstring::del_escaped(char escaped_symb)
  197. {
  198.     ///!!! for further implementation
  199.     return *this;
  200. }
  201. //---------------------------------------------------------------------------------
  202. mstring & mstring::quote(const string &q_start, const string &q_end)
  203. {
  204.     insert(0, q_start);
  205.     append(q_end);
  206.     return *this;
  207. }
  208. //---------------------------------------------------------------------------------
  209. /**
  210. Get the next token from string
  211. @return:  the next position in string to be continue or 
  212.           string::npos if no more tokens
  213. @param start              Start position of the string - 0 or 
  214.                           the previous returned value
  215. @param sep                String with possible separators. Every symbol
  216.                           of this string is separator
  217. @param quote              String with quotation symbols, for example, "'"
  218.                           Inside quote string is not divided. Quotation can
  219.                           start with any of these symbols, but finish with
  220.                           the same symbol only.
  221. @param pair_chr           Usually '' symbol to include quotation symbols
  222.                           inside the quote parts
  223. @param sep_flag           Flag sep_single or sep_multiple to determine, 
  224.                           whether the separators, going successively are 
  225.                           nerpreted as detached empty tokens (sep_single) 
  226.                           or one token (sep_multiple), as strtok does.
  227.                           sep_single:   string "123,,456" will be "123", "", "456"
  228.                           sep_multiple: string "123,,456" will be "123", "456"
  229. \================================================================================*/
  230. string::size_type mstring::next_token(size_type start, const string &sep,
  231.                                       const string &quote, char pair_chr,
  232.                                       sep_flag flag) const
  233. {
  234.     size_type count = 0;
  235.     char quote_chr = 0;
  236.     if (start == string::npos) return string::npos;
  237.     const char *pstr = c_str() + start;
  238.     if (*pstr == 0) return string::npos;
  239.     if (flag == sep_multiple)
  240.     {
  241.         //Pass all the separators symbols at the begin of the string
  242.         while (*pstr && sep.find(*pstr) != string::npos)
  243.         {
  244.             ++pstr;
  245.             ++start;
  246.         }
  247.     }
  248.     for (count = 0; ; count++)
  249.     {
  250.         char c = *pstr++;
  251.         if (c == 0)
  252.         {
  253.             start = string::npos;
  254.             break;
  255.         }
  256.         //Outside quote find one of separator symbols
  257.         if (quote_chr == 0 && sep.find(c) != string::npos)
  258.         {
  259.             start += count;
  260.             break;
  261.         }
  262.         //Switch quote. If it is not a quote yet, try to check any of
  263.         //quote symbols. Otherwise quote must be finished with quote_symb
  264.         if (quote_chr == 0)
  265.         {
  266.             if (quote.find(c) != string::npos)
  267.             {
  268.                 quote_chr = c;
  269.                 continue;
  270.             }
  271.         }
  272.         else
  273.         {
  274.             //Inside quote pass all the pair symbols
  275.             if (pair_chr && c == pair_chr)
  276.             {
  277.                 if (*pstr)
  278.                 {
  279.                     ++count;
  280.                     ++pstr;
  281.                 }
  282.                 continue;
  283.             }
  284.             if (c == quote_chr)
  285.             {
  286.                 quote_chr = 0;
  287.                 continue;
  288.             }
  289.         }
  290.     }
  291.     return start;
  292. }
  293. //---------------------------------------------------------------------------------
  294. /**
  295. Get the next token from string
  296. @return:  the next position in string to be continue or 
  297.           string::npos if no more tokens
  298. @param dst                Pointer to the destination string. 
  299.                           If this parameter is null
  300.                           the function may be used to counting 
  301.                           tokens
  302. @param start              Start position of the string - 0 or 
  303.                           the previous returned value
  304. @param sep                String with possible separators. Every symbol
  305.                           of this string is separator
  306. @param quote              String with quotation symbols, for example, "'"
  307.                           Inside quote string is not divided. Quotation can
  308.                           start with any of these symbols, but finish with
  309.                           the same symbol only.
  310. @param pair_chr           Usually '' symbol to include quotation symbols
  311.                           inside the quote parts
  312. @param sep_flag           Flag sep_single or sep_multiple to determine, 
  313.                           whether the separators, going successively are 
  314.                           nerpreted as detached empty tokens (sep_single) 
  315.                           or one token (sep_multiple), as strtok does.
  316.                           sep_single:   string "123,,456" will be "123", "", "456"
  317.                           sep_multiple: string "123,,456" will be "123", "456"
  318. \================================================================================*/
  319. string::size_type mstring::token(string *dst, size_type start, const string &sep,
  320.                                  const string &quote, char pair_chr,
  321.                                  sep_flag flag) const
  322. {
  323.     size_type count = 0;
  324.     char quote_chr = 0;
  325.     if (dst) dst->erase();
  326.     if (start == string::npos) return string::npos;
  327.     const char *pstr = c_str() + start;
  328.     if (*pstr == 0) return string::npos;
  329.     size_type sep_len = 1;
  330.     if (flag == sep_whole_str) sep_len = sep.length();
  331.     const char *psep = sep.c_str();
  332.     if (flag == sep_multiple)
  333.     {
  334.         //Pass all the separators symbols at the begin of the string
  335.         while (*pstr && sep.find(*pstr) != string::npos)
  336.         {
  337.             ++pstr;
  338.             ++start;
  339.         }
  340.     }
  341.     for (count = 0; ; count++)
  342.     {
  343.         char c = *pstr;
  344.         bool found = false;
  345.         //Outside quote find one of separator symbols
  346.         if (quote_chr == 0)
  347.         {
  348.             if (sep_len == 1)
  349.             {
  350.                 found = sep.find(c) != string::npos;
  351.             }
  352.             else
  353.             {
  354.                 found = strncmp(psep, pstr, sep_len) == 0;  //sep.compare(0, sep_len, pstr, sep_len) == 0;
  355.             }
  356.         }
  357.         ++pstr;
  358.         if (c == 0 || found)
  359.         {
  360.             if (dst) dst->assign(*this, start, count);
  361.             //The next time it will be the next separator character
  362.             //But we must check, whether it is the end of the string.
  363.             start += count;
  364.             if (c) start += sep_len;
  365.             break;
  366.         }
  367.         //Switch quote. If it is not a quote yet, try to check any of
  368.         //quote symbols. Otherwise quote must be finished with quote_symb
  369.         if (quote_chr == 0)
  370.         {
  371.             if (quote.find(c) != string::npos)
  372.             {
  373.                 quote_chr = c;
  374.                 continue;
  375.             }
  376.         }
  377.         else
  378.         {
  379.             //Inside quote pass all the pair symbols
  380.             if (pair_chr && c == pair_chr)
  381.             {
  382.                 if (*pstr)
  383.                 {
  384.                     ++count;
  385.                     ++pstr;
  386.                 }
  387.                 continue;
  388.             }
  389.             if (c == quote_chr)
  390.             {
  391.                 quote_chr = 0;
  392.                 continue;
  393.             }
  394.         }
  395.     }
  396.     return start;
  397. }
  398. //-------------------------------------------------------------------------------------
  399. /**
  400. Split up the string into the many pieces. This function uses token function.
  401. @return  Number of found tokens
  402. @param str_vec             Pointer to the destination vector of strings. 
  403.                            If this parameter is null
  404.                            the function may be used to counting 
  405.                            tokens
  406. @param sep                 String with possible separators. Every symbol
  407.                            of this string is separator
  408. @param quote               String with quotation symbols, for example, "'"
  409.                            Inside quote string is not divided. Quotation can
  410.                            start with any of this symbol, but finish with
  411.                            the same symbol only.
  412. @param pair_chr            Usually '' symbol to include quotation symbols
  413.                            inside the quote parts
  414. @param flag                Flag sep_single or sep_multiple to determine, 
  415.                            whether the separators, going successively are 
  416.                            nerpreted as detached empty tokens (sep_single) 
  417.                            or one token (sep_multiple), as strtok does.
  418.                            sep_single:   string "123,,456" will be "123", "", "456"
  419.                            sep_multiple: string "123,,456" will be "123", "456"
  420.                            
  421. \================================================================================*/
  422. unsigned mstring::split(mstr_vector *str_vec, const string &sep,
  423.                         const string &quote, char pair_chr, sep_flag flag) const
  424. {
  425.     if (str_vec) str_vec->clear();
  426.     unsigned count = 0;
  427.     size_type start = 0;
  428.     mstring tmp;
  429.     while ((start = token(&tmp, start, sep, quote, pair_chr, flag)) != string::npos)
  430.     {
  431.         if (str_vec) str_vec->push_back(tmp);
  432.         count++;
  433.     }
  434.     return count;
  435. }
  436. //-------------------------------------------------------------------------------------
  437. /**
  438. Check quote parts balance.
  439. @return true = balance OK, false - no balance
  440.    
  441. @param quote               String with quotation symbols, for example, "'"
  442.                            Quotation can start with any of this symbol, 
  443.                            but finish with
  444.                            the same symbol only.
  445. @param pair_chr            Usually '' symbol to include quotation symbols
  446.                            inside the quote parts
  447. \================================================================================*/
  448. bool mstring::chkquote(const string &quote, char pair_chr) const
  449. {
  450.     char quote_chr = 0;
  451.     const char *pstr = c_str();
  452.     char c;
  453.     while ((c = *pstr++) != 0)
  454.     {
  455.         //Switch quote. If it is not a quote yet, try to check any of
  456.         //quote symbols. Otherwise quote must be finished with quote_symb
  457.         if (quote_chr == 0)
  458.         {
  459.             if (quote.find(c) != string::npos)
  460.             {
  461.                 quote_chr = c;
  462.                 continue;
  463.             }
  464.         }
  465.         else
  466.         {
  467.             //Inside quote pass all the pair symbols
  468.             if (pair_chr && c == pair_chr)
  469.             {
  470.                 if (*pstr)
  471.                 {
  472.                     ++pstr;
  473.                 }
  474.                 continue;
  475.             }
  476.             if (c == quote_chr)
  477.             {
  478.                 quote_chr = 0;
  479.                 continue;
  480.             }
  481.         }
  482.     }
  483.     return quote_chr == 0;
  484. }
  485. //-------------------------------------------------------------------------------------
  486. /**
  487.     Get the next BRACKET token from string. 
  488.     Parsing nested brackets can be done recursively. For example:
  489.     begin{verbatim}
  490.     void print_brackets(int ident, std::mstring str, std::string &quote, char pair)
  491.     {
  492.         std::mstring tmp;
  493.         std::string::size_type start = 0;
  494.         int bal;
  495.   
  496.        while((start = str.brtok(&tmp, start, &bal, 
  497.                       '+', '-', quote, pair)) != 
  498.               std::string::npos)
  499.        {
  500.            for(unsigned i = 0; i < ident; i++) cout << '*';
  501.            cout << tmp.c_str() << " = " << bal << "n";
  502.            print_brackets(ident+1, tmp, quote, pair);
  503.        }
  504.     }
  505.     end{verbatim}
  506.   @return  the next position in string to be continue or 
  507.            string::npos if no more tokens
  508.  
  509.  
  510.   @param dst                 Pointer to the destination string. 
  511.                              If this parameter is null
  512.                              the function may be used to counting 
  513.                              tokens
  514.  
  515.   @param start               Start position in the string - 0 or 
  516.                              the previous returned value
  517.  
  518.   @param balance             Returns bracket balance
  519.                              positive - a lake of closing brackets
  520.                              negatine - an overage of closing brackets
  521.  
  522.   @param br_open             Open bracket character
  523.  
  524.   @param br_close            Close bracket character
  525.  
  526.   @param quote               String with quotation symbols, for example, "'"
  527.                              Inside quote string is not divided. Quotation can
  528.                              start with any of this symbol, but finish with
  529.                              the same symbol only.
  530.  
  531.   @param pair_chr            Usually '' symbol to include quotation symbols
  532.                              inside the quote parts
  533. \================================================================================*/
  534. string::size_type mstring::brtok(string *dst, size_type *start, int *balance,
  535.                                  char br_open, char br_close,
  536.                                  const string &quote, char pair_chr) const
  537. {
  538.     int brbal = 0;
  539.     char quote_chr = 0;
  540.     size_type count = 0;
  541.     size_type start_pos = string::npos;
  542.     size_type end_pos = string::npos;
  543.     if (dst) dst->erase();
  544.     if (*start == string::npos) return string::npos;
  545.     const char *pstr = c_str() + *start;
  546.     if (*pstr == 0) return string::npos;
  547.     char c;
  548.     for (count = 0; (c = *pstr++) != 0; count++)
  549.     {
  550.         //Outside quote find a bracket
  551.         if (quote_chr == 0)
  552.         {
  553.             if (c == br_open)
  554.             {
  555.                 if (start_pos == string::npos && brbal == 0) start_pos = count;
  556.                 brbal++;
  557.             }
  558.             if (c == br_close)
  559.             {
  560.                 brbal--;
  561.                 if (end_pos == string::npos && brbal == 0) end_pos = count;
  562.             }
  563.         }
  564.         //Switch quote. If it is not a quote yet, try to check any of
  565.         //quote symbols. Otherwise quote must be finished with quote_symb
  566.         if (quote_chr == 0)
  567.         {
  568.             if (quote.find(c) != string::npos)
  569.             {
  570.                 quote_chr = c;
  571.                 continue;
  572.             }
  573.         }
  574.         else
  575.         {
  576.             //Inside quote pass all the pair symbols
  577.             if (pair_chr && c == pair_chr)
  578.             {
  579.                 if (*pstr)
  580.                 {
  581.                     ++count;
  582.                     ++pstr;
  583.                 }
  584.                 continue;
  585.             }
  586.             if (c == quote_chr)
  587.             {
  588.                 quote_chr = 0;
  589.                 continue;
  590.             }
  591.         }
  592.     }
  593.     if (start_pos != string::npos && end_pos != string::npos)
  594.     {
  595.         if (dst) dst->assign(*this, *start + start_pos + 1,
  596.                                  end_pos - start_pos - 1);
  597.         ++end_pos;
  598.     }
  599.     if (balance) *balance = brbal;
  600.     if (end_pos == string::npos) return npos;
  601.     end_pos += *start;
  602.     *start += start_pos;
  603.     return end_pos;
  604. }
  605. }