home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lyx-0.13.2.tar.gz / lyx-0.13.2.tar / lyx-0.13.2 / src / LString.h < prev    next >
C/C++ Source or Header  |  1998-04-23  |  9KB  |  415 lines

  1. // -*- C++ -*-
  2. /* This file is part of
  3.  * ======================================================
  4.  * 
  5.  *           LyX, The Document Processor
  6.  *      
  7.  *        Copyright (C) 1995 1996 Matthias Ettrich
  8.  *           and the LyX Team.
  9.  *
  10.  *======================================================*/
  11.  
  12. // This one is heavily based on the string class in The C++
  13. // Programming Language by Bjarne Stroustrup
  14.  
  15. #ifndef _LSTRING_H_
  16. #define _LSTRING_H_ 
  17.  
  18. #ifdef __GNUG__
  19. #pragma interface
  20. #endif
  21.  
  22. #include <config.h> // needed at least for compilers that do not
  23.             // understand `explicit' (JMarc)
  24. #include <string.h>
  25.  
  26. /** A string class for LyX
  27.   
  28.   This is a permanent String class. It was supposed to be superseeded
  29.   with QString when we switch to the Qt library, but now it's so developed
  30.   that it is as good as theirs (or maybe even better :-)
  31.  
  32.   Notes for usage:
  33.  
  34.   When you declare an LString, it is initially empty. There is no need to
  35.   do things like #LString a= "";#, especially not in constructors.
  36.  
  37.   If you want to use a default empty LString as a parameter, use
  38.   
  39.       #void foo(LString par = LString());    // Correct#
  40.   
  41.   rather than
  42.  
  43.       #void foo(LString par = "");    // WRONG!#
  44.       #void foo(LString par = 0);    // WRONG!#
  45.  
  46.   (The last one is only wrong because some compilers can't handle it.)
  47.  
  48.   Methods that take an index as parameter all follow this rule: Valid indexes
  49.   go from 0 to length()-1.
  50.   \begin{tabular}{rl}
  51.   Correct: & #foo.substring(0, length()-1);# \\
  52.   Wrong:   & #bar.substring(0, length());#
  53.   \end{tabular}
  54.   
  55.   It is important that you declare LStrings as const if possible, because
  56.   some methods are much more efficient in const versions.
  57.   
  58.   If you want to check whether a string is empty, do
  59.  
  60.       #if (foo.empty()) something right#
  61.  
  62.   rather than something along the lines of
  63.  
  64.       #if (!foo) completely wrong#
  65.  
  66.   When you use the #.copy()# method, LString calls "#new []#", so you have to
  67.   release the memory with #delete[]#. Don't preallocate memory.
  68.  
  69.   When you want to copy an LString, just do
  70.   
  71.     #LString a, b = "String";#
  72.     #a = b;    // That's it!#
  73.  
  74.   not something like
  75.   
  76.       #LString a, b = "String";#
  77.       #a = b.copy(); // This leaks.#
  78.   
  79.   The class automatically handles deep copying when required.
  80. */
  81. class LString {
  82. public:
  83.     /**@name Constructors and Deconstructors */
  84.     //@{
  85.     /// #LString x;# in STL
  86.     LString();
  87.     /// #LString x(LString ...)# in STL
  88.     LString(LString const &);
  89.     /// #LString x("abc")#  in STL
  90.     LString(char const*);
  91.     /// #LString x('a')# STL don't have this
  92.     //explicit LString(char const);
  93.     // not all C++ compilers understands explicit as of now
  94.  
  95.     /// in STL
  96.     ~LString();
  97.     //@}
  98.  
  99.     /**@name Operators */
  100.     //@{
  101.     // Assignment
  102.     /// in STL
  103.     LString& operator=(LString const &);
  104.     /// in STL
  105.     LString& operator=(char const *);
  106.     /// in STL
  107.     LString& operator=(char);
  108.  
  109.     /// in STL
  110.     char& operator[](int);
  111. #ifndef const
  112.     /// in STL
  113.     char const& operator[](int) const;
  114. #endif
  115.     /// in STL
  116.     LString& operator+=(LString const &);
  117.     /// in STL
  118.     LString& operator+=(char const*);
  119.     /// in STL
  120.     LString& operator+=(char);
  121.     /// NOT in STL
  122.     inline LString& operator+=(int);
  123.     /// NOT in STL
  124.     LString& operator+=(long);
  125.     //@}
  126.  
  127.     /**@name Methods */
  128.     //@{
  129.     ///  in STL
  130.     bool empty() const;
  131.     ///
  132.     int length() const;
  133.  
  134.         /** equivalent to  *this = empty. But usable outside LString
  135.             implementation. in STL*/
  136.     LString &erase();
  137.  
  138.     /// in STL
  139.     char const* c_str() const;
  140.  
  141.     /** in STL. This one returns a verbatim copy. Not the trailing '\0'
  142.       The caller must provide a buffer with engough room.
  143.       */
  144.     char * copy(char *buf, int len) const;
  145.  
  146.     ///
  147.     bool contains(char const *) const;
  148.     ///
  149.     bool contains(LString const &) const;
  150.     
  151.     // Remove and replace (STL)
  152.     /// Truncate to substring. I.e. #"abcdef".substring(2,4)="cde"#
  153.     LString& substring(int i1, int i2);
  154.         
  155.     /** Splits the string by the first delim.
  156.       Splits the string by the first appearance of delim.
  157.         The leading string up to delim is returned in piece (not including
  158.         delim), while the original string is cut from after the delimiter.
  159.         Example:
  160.         #s1=""; s2="a;bc".split(s1, ';') -> s1=="a"; s2 == "bc";#
  161.     */
  162.     LString& split(LString& piece, char delim);
  163.     /// Same as split but does not return a piece
  164.     LString& split(char delim);
  165.         /// Same as split but uses the last delim.
  166.     LString& rsplit(LString& piece, char delim);
  167.     
  168.     /** Extracts a token from this string at the nth delim.
  169.         Doesn't modify the original string. Similar to strtok.
  170.         Example:
  171.         #"a;bc;d".token(';', 1) == "bc";#
  172.         #"a;bc;d".token(';', 2) == "d";#
  173.     */
  174.     LString token(char delim, int n=0) const;
  175.  
  176.     /** Search a token in this string using the delim.
  177.         Doesn't modify the original string. Returns -1 in case of
  178.         failure. 
  179.         Example:
  180.         #"a;bc;d".tokenPos(';', "bc") == 1;#
  181.         #"a;bc;d".token(';', "d") == 2;#
  182.     */
  183.     int tokenPos(char delim, LString const &tok);
  184.  
  185.     /** Strips characters off the end of a string.
  186.         #"abccc".strip('c') = "ab".#
  187.     */
  188.     LString& strip(char const c = ' ');
  189.  
  190.     /** Strips characters of the beginning of a string.
  191.       #"cccba".frontstrip('c') = "ba"#. */
  192.     LString& frontStrip(char const c = ' ');
  193.     
  194.     /// Does the string start with this prefix?
  195.     bool prefixIs(char const *) const;
  196.  
  197.     /// Does the string end with this char?
  198.     bool suffixIs(char) const;
  199.  
  200.     /// Does the string end with this suffix?
  201.     bool suffixIs(char const *) const;
  202.     
  203.     /// Substitute all "oldchar"s with "newchar"
  204.     LString& subst(char oldchar, char newchar);
  205.  
  206.     /// Substitutes all instances of oldstr with newstr
  207.     LString& subst(char const * oldstr, LString const & newstr);
  208.  
  209.     /** Compares a string and a (simple) regular expression
  210.       The only element allowed is "*" for any string of characters
  211.       */
  212.     bool regexMatch(LString const & pattern) const;
  213.  
  214.     /// Lowercases a string
  215.     LString& lowercase();
  216.  
  217.     /// Counts how many of character c there is in string
  218.     int countChar(const char c) const;
  219.  
  220.     /// Position of the character c from the beggining
  221.     int charPos(const char c) const;
  222.         
  223.     //@}
  224.  
  225.     /**@name Friends */
  226.     //@{
  227.     
  228.     ///
  229.     friend bool operator==(LString const &x, char const *s)
  230.     {
  231.         if (s == 0 || !(*s)) 
  232.             return x.p->s[0] == '\0';
  233.         else
  234.             return strcmp(x.p->s, s) == 0;
  235.     }
  236.     
  237.     ///
  238.     friend bool operator==(LString const &x, LString const &y)
  239.     {
  240.         return strcmp(x.p->s, y.p->s) == 0;
  241.     }
  242.     
  243.     ///
  244.     friend bool operator!=(LString const &x, char const *s)
  245.     {
  246.         if (s == 0 || !(*s)) 
  247.             return x.p->s[0] != '\0';
  248.         else
  249.             return strcmp(x.p->s, s) != 0;
  250.     }
  251.     
  252.     ///
  253.     friend bool operator!=(LString const &x, LString const &y)
  254.     {
  255.         return strcmp(x.p->s, y.p->s) != 0;
  256.     }
  257.     //@}
  258.  
  259.     // in STL
  260.     static int const npos;
  261. protected:
  262. private:
  263.     /// A string representation
  264.     struct srep {
  265.         /// Length
  266.         unsigned int l;
  267.         /// Reference count (number of references - 1)
  268.         unsigned short n;
  269.         /// Extra space at end of allocated string
  270.         unsigned short e;
  271.         /// Data. At least 1 char for trailing null.
  272.         char s[1];
  273.         ///
  274.         srep() { n = 0; l = 0; e = 0; s[0] = '\0'; }
  275.         /// Dummy constructor used for the static empty char
  276.         srep(int) { };
  277.     };
  278.  
  279.     /// The empty string is static
  280.     static srep empty_rep;
  281.  
  282.     /// A string is a pointer to it's representation
  283.     srep *p;
  284.     ///
  285.         inline void lose();
  286. };
  287.  
  288.  
  289. inline LString &LString::operator+=(int i)
  290. {
  291.     return this->operator+=(long(i));
  292. }
  293.  
  294.  
  295. inline LString::LString()
  296. {
  297.     p = &empty_rep;
  298.     empty_rep.n++;
  299. }
  300.  
  301.  
  302. inline LString::LString(LString const &x)
  303. {
  304.     x.p->n++;
  305.     p = x.p;
  306. }
  307.  
  308.  
  309. inline void LString::lose()
  310. {
  311.     if (p->n-- == 0) {
  312.         delete[] p;
  313.     }
  314. }
  315.  
  316.  
  317. inline LString::~LString()
  318. {
  319.    lose();
  320. }
  321.  
  322.  
  323. inline int LString::length() const
  324. {
  325.     return p->l;
  326. }
  327.  
  328.  
  329. inline bool LString::empty() const
  330. {
  331.     return p->l == 0;
  332. }
  333.  
  334.  
  335. inline int LString::countChar(const char c) const
  336. {
  337.     int n = 0;
  338.     for (int i=0; i < length(); i++)
  339.         if (operator[](i) == c) n++;
  340.     return n;
  341. }
  342.  
  343.  
  344. inline LString operator+(LString const &x, LString const &y)
  345. {
  346.     LString str(x);
  347.     str += y;
  348.     return str;
  349. }
  350.  
  351.  
  352. inline LString operator+(LString const &x, char const &y)
  353. {
  354.     LString str(x);
  355.     str += y;
  356.     return str;
  357. }
  358.  
  359.  
  360. inline LString operator+(LString const &x, int const &y)
  361. {
  362.     LString str(x);
  363.     str += y;
  364.     return str;
  365. }
  366.  
  367.  
  368. inline LString operator+(LString const &x, long const &y)
  369. {
  370.     LString str(x);
  371.     str += y;
  372.     return str;
  373. }
  374.  
  375. inline char const* LString::c_str() const
  376. {
  377.     return (char const*)p->s;
  378. }
  379.  
  380.  
  381. inline char * LString::copy(char *buf, int len) const
  382. {
  383.     memcpy(buf, p->s, len == npos ? length() : len);
  384.     return buf;
  385. }
  386.  
  387.  
  388. inline int LString::charPos(const char c) const
  389. {
  390.         for (int i=0; i < length(); i++) {
  391.             if (operator[](i) == c) return i;
  392.     }
  393.         return -1;
  394. }
  395.      
  396. inline LString &LString::erase()
  397. {
  398.   lose();
  399.   p = &empty_rep;
  400.   empty_rep.n++;
  401.   return *this;
  402. }
  403.  
  404. inline bool LString::contains(char const *a) const
  405. {
  406.     return strstr(p->s, a) != NULL;
  407. }
  408.  
  409. inline bool LString::contains(LString const &a) const
  410. {
  411.     return strstr(p->s, a.c_str()) != NULL;
  412. }
  413.  
  414. #endif
  415.