]> git.donarmstrong.com Git - lilypond.git/blobdiff - flower/string.cc
(Module):
[lilypond.git] / flower / string.cc
index 1e532a2fadd2930a5b9ae7330891b643411780a7..e210ea21730cfe42e814b2b167fd0eac97b0448a 100644 (file)
 /*
-  PROJECT: FlowerSoft C++ library
-  FILE   : string.cc
+  string.cc - implement String
 
-  Rehacked by HWN 3/nov/95
-  removed String &
-  introduced class String_handle
-  */
+  (c) 1997--2006 Han-Wen Nienhuys & Jan Nieuwenhuizen
+*/
+#if !STD_STRING
 
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <assert.h>
+#ifndef _GNU_SOURCE // we want memmem
+#define _GNU_SOURCE
+#endif
 
-#include "string.hh"
+#include "std-string.hh"
 
-#ifdef STRING_DEBUG
-void* mymemmove( void* dest, void* src, size_t n );
-#define memmove mymemmove
-#endif
+#include <cstdlib>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
 
-static char* 
-strlwr( char* s )
-{
-    char* p = s;
+using namespace std;
+
+#include "libc-extension.hh"
+#include "string-convert.hh"
 
-    while( *p )
-        {
-        *p = tolower( *p );    /* a macro on some compilers */
-        p++;
-        }
-    return s;
+/* std::string interface */
+
+namespace std {
+
+String::String (char const *s, int n)
+{
+  strh_.set ((Byte const *)s, n);
 }
 
-static char* 
-strupr( char* s )
+String::String (String const &s, int pos, ssize n)
 {
-    char* p = s;
+  *this = s.substr (pos, n);
+}
 
-    while( *p )
-        {
-        *p = toupper( *p );    /* a macro on some compilers */
-        p++;
-        }
-    return s;
+String::String (int n, char c)
+{
+  *this = String_convert::char_string (c, n);
 }
 
-String::String(Rational r)
+String &
+String::operator = (String const &source)
 {
-    char * n = Itoa(r.numerator()); // LEAK????
-    
-    *this = n;
-    if (r.denominator() != 1) {
-       char * d = Itoa(r.denominator());
-       *this +=  String( '/' ) + String(d);
-       //delete d;
-    }
-/*    delete n;
-    */
+  strh_ = source.strh_;
+  return *this;
 }
 
-// return array, alloced with new.
-Byte*
-String::copy_byte_p() const
+String
+String::substr (int pos, ssize n) const
+{
+#if 1
+  if (n == (ssize)-1 || n == (ssize)INT_MAX || n == NPOS)
+    n = length () - pos;
+  return cut_string (pos, n);
+#else
+  if (n == (ssize)-1 || n == (ssize)INT_MAX || n == NPOS)
+    n = length () - pos;
+  if (pos == 0)
+    return left_string (n);
+  else
+    return right_string (length () - pos).left_string (n);
+#endif
+}
+
+String
+String::insert (ssize pos, String s)
 {
-    Byte const* src = strh_.byte_c_l();
-    Byte* dest = new Byte[strh_.length_i() + 1];
-    memmove( dest, src, strh_.length_i() + 1 );
-    return dest;    
+  *this = substr (0, pos) + s + substr (pos + 1);
+  return *this;
 }
 
-void
-String::printOn(ostream& os) const
+ssize
+String::copy (char *buf, ssize n, ssize pos) const
 {
-    if ( length_i() == strlen( ch_c_l() ) )
-        os << ch_c_l();
-    else
-       for ( int i = 0; i < length_i(); i++ )
-           os << (Byte)(*this)[ i ];
+  assert (pos == 0);
+  memcpy (buf, strh_.to_bytes (), strh_.length () + 1);
+  return n; // ?
 }
 
-String::String (bool b)
+int
+String::compare (String const &s) const
 {
-    *this = (char const* ) (b ? "true" : "false");
+  char const *p1 = c_str ();
+  char const *p2 = s.c_str ();
+  if (p1 == p2)
+    return 0;
+
+  /*
+    don't forget the terminating '\0'
+  */
+  int f = min (length (), s.length ());
+  int cmp_length = 1+ f;
+  int i = memcmp (p1, p2, cmp_length);
+  return i;
 }
-String::String( char const* source )
-{   
-    assert(source);    
-    strh_ = source;    
+
+char const *
+String::data () const
+{
+  return (char const*) to_bytes ();
 }
 
-String::String( Byte const* byte_l, int length_i )
-{   
-    assert( !length_i || byte_l );
-    strh_.set( byte_l, length_i );    
+bool
+String::empty () const
+{
+  return !length ();
 }
 
-void
-String::operator +=(String s)
+int
+String::find (char c, int pos) const
 {
-    strh_.append( s.byte_c_l(), s.length_i() );
+  String f = right_string (length () - pos);
+  ssize n = f.index (c);
+  if (n != NPOS)
+    return pos + n;
+  return NPOS;
 }
 
 int
-String::length_i() const
+String::find (char const *c, int pos) const
 {
-    return strh_.length_i();
+  return find (String (c), pos);
 }
 
-// will go away, fixed anyway
-String::String( char c,  int n )
+int
+String::find (String s, int pos) const
 {
-    n = n >= 0 ? n : 0;
-    char* ch_p = new char[ n ];
-    memset( ch_p, c, n );
-    strh_.set( (Byte*)ch_p, n );
-    delete ch_p;
+  if (!pos)
+    return index (s);
+  String f = right_string (length () - pos);
+  ssize n = f.index (s);
+  if (n != NPOS)
+    return pos + n;
+  return NPOS;
 }
 
-String::String(int i)
+int
+String::rfind (char c) const
 {
-    char digits[ 81 ];             // who the fuck is 80???
-    digits[ 0 ] = '\0';
-    sprintf(digits, "%d", i );     // assume radix 10
-    strh_ = digits;
+  return index_last (c);
 }
 
-String::String( const int i, const int n, char const c )
+String
+String::replace (int pos, int n, String str)
 {
-    char fillChar = c;
-    if ( fillChar)
-        fillChar = '0';
+  return this->substr (0, pos) + str + this->substr (pos + n);
+}
 
-    String v( i );
-    
-    String str = String( fillChar, n - v.length_i() ) + String( v );
-    strh_.set( str.byte_c_l(), str.length_i() );
+void
+String::append (String s)
+{
+  strh_.append (s.to_bytes (), s.length ());
 }
 
-Byte const*
-String::byte_c_l() const
+void
+String::operator += (String s)
 {
-    return strh_.byte_c_l();
+  append (s);
 }
 
-char const*
-String::ch_c_l() const
+int
+String::length () const
 {
-    return strh_.ch_c_l();
+  return strh_.length ();
 }
 
-Byte*
-String::byte_l()
+
+
+
+/* String */
+
+int
+String::compare (String const &s1, String const &s2)
 {
-    return strh_.byte_l();
+  return s1.compare (s2);
 }
 
-char*
-String::ch_l()
+#ifdef STRING_DEBUG
+void *mymemmove (void *dest, void const *src, size_t n);
+#define memmove mymemmove
+#endif
+
+// return array, alloced with new.
+Byte *
+String::get_copy_byte () const
 {
-    return strh_.ch_l();
+  Byte const *src = strh_.to_bytes ();
+  Byte *dest = new Byte[strh_.length () + 1];
+  memcpy (dest, src, strh_.length () + 1);
+  return dest;
 }
 
-// signed comparison,  analogous to memcmp;
-int
-String::compare(String const& s1, String const& s2 ) 
+char *
+String::get_copy_str0 () const
 {
-    Byte const* p1 = s1.byte_c_l();
-    Byte const* p2 = s2.byte_c_l();
-    if ( p1 == p2 )
-       return 0;
+  return (char *)get_copy_byte ();
+}
 
-    int i1 = s1.length_i();
-    int i2 = s2.length_i();
-    int i = i1 <? i2;
+\f
 
-    int result=  memcmp( p1, p2, i );
-    return result ? result : i1-i2;
+#if 0
+void
+String::prepend (String s)
+{
+  s += *this;
+  *this = s;
 }
 
+#endif
 
-int
-String::lastPos( char const c ) const
+
+Byte const *
+String::to_bytes () const
 {
-    // not binary safe
-    assert( length_i() == strlen( ch_c_l() ) );
-    char const* me = strh_.ch_c_l();
-    int pos = 0;
-    if ( length_i() )
-        {
-       char const* p = strrchr(me, c );
-        if ( p )
-            pos = p - me + 1;
-        }
-    return pos;
+  return strh_.to_bytes ();
 }
 
-int
-String::lastPos( char const* string ) const
-{
-    // not binary safe
-    assert( length_i() == strlen( ch_c_l() ) );
-    int pos = 0;
-    int length = strlen( string );
-    if ( length_i() && length )
-        {
-        int nextpos = this->pos( string );
-        while( nextpos )
-            {
-            pos += nextpos;
-            nextpos = right( length_i() - pos - length + 1 ).pos( string );
-            }
-        }
-    return pos;
-}
-
-// find c
-// return 0 if not found. 
-
-// ? should return length_i()?, as in string.left(pos(delimiter))
-int
-String::pos(char c ) const
-{
-    // not binary safe
-    assert( length_i() == strlen( ch_c_l() ) );
-    char const* me = strh_.ch_c_l();
-    int pos = 0;
-    if ( length_i() )
-        {
-       char const* p = strchr( me, c );
-        if ( p )
-            pos = p - me + 1;
-        }
-    return pos;
-}
-
-// find searchfor. (what if this == "" && searchfor == "") ???
-int
-String::pos( char const* searchfor ) const
-{
-    // not binary safe
-    assert( length_i() == strlen( ch_c_l() ) );
-    char const* me = strh_.ch_c_l();
-    int pos = 0;
-    if ( length_i() && searchfor)
-        {
-       char const* p = strstr(me, searchfor);
-        if ( p )
-           pos = p - me + 1;
-        }
-    return pos;
-}
-
-// find chars of a set.
-int
-String::posAny( char const* string ) const
+Byte *
+String::get_bytes ()
 {
-    // not binary safe
-    assert( length_i() == strlen( ch_c_l() ) );
-    int pos = 0;
-    char const* s = (char const* )strh_.ch_c_l();
-    if ( length_i() && string )
-        {
-       char const* p = strpbrk( s, string );
-        if ( p )
-           pos = p - s + 1;
-        }
-    return pos;
+  return strh_.get_bytes ();
 }
 
-String
-String::left( int n ) const
+\f
+int
+String::index_last (char const c) const
 {
-    if (n >= length_i())
-       return *this;
+  if (!length ())
+    return NPOS;
 
-    String retval;     
-    if (n < 1)
-        return retval;
-    
-    retval = *this;
-    retval.strh_.trunc(n);
-    return retval;
+  char const *me = strh_.c_str ();
+  char const *p = (char const *)memrchr ((Byte *)me, length (), c);
+  if (p)
+    return p - me;
+  return NPOS;
 }
 
+/** find  a character.
 
-// n rightmst chars
-String
-String::right( int n ) const
+@return
+the index of the leftmost character #c# (0 <= return < length ()),
+or   NPOS if not found.
+
+? should return length ()?, as in string.left_string (index (delimiter))
+*/
+int
+String::index (char c) const
 {
-    if (n > length_i())
-       return *this;
-    
-    if ( n < 1)
-        String(); 
-    
-    return String( strh_.byte_c_l() + length_i() - n, n ); 
+  char const *me = strh_.c_str ();
+  char const *p = (char const *) memchr (me, c, length ());
+  if (p)
+    return p - me;
+  return NPOS;
 }
 
+/**
+   find a substring.
 
-String
-String::nomid( const int pos, const int n ) const
+   @return
+   index of leftmost occurrence of #searchfor#
+*/
+int
+String::index (String searchfor) const
 {
-    String retval;
-        
-    if ( pos < 1 )
-        return String("");
-    if ( pos > length_i())
-       return *this;
-    
-    return String( String( left( pos - 1 ) ) + right( length_i() - pos - n + 1 ));
+  char const *me = strh_.c_str ();
+
+  char const *p
+    = (char const *) memmem (me, length (),
+                            searchfor.c_str (), searchfor.length ());
+
+  if (p)
+    return p - me;
+
+  return NPOS;
 }
 
+/** find chars of a set.
+
+@return
 
+the index of the leftmost occurance of an element of #set#.  NPOS if
+nothing is found.
+*/
+int
+String::index_any (String set) const
+{
+  int n = length ();
+  if (!n)
+    return NPOS;
+
+  void const *me = (void const *) strh_.c_str ();
+  for (int i = 0; i < set.length (); i++)
+    {
+      char *found = (char *) memchr (me, set[i], n);
+      if (found)
+       return found - (char const *)me;
+    }
+  return NPOS;
+}
+\f
 String
-String::mid( int pos, int n ) const
+String::left_string (int n) const
 {
-    // HWN. This SUX: JCN: yep, please change me + all my invocations
-    // pos 1 == strh_->string[ 0 ];
-    // pos 0 allowed for convenience
-    if ( !length_i() || ( pos < 0 ) || ( pos > length_i() ) && ( n < 1 ) )
-        return String();
+  if (n >= length ())
+    return *this;
 
-    // overflow...
-    if ( ( n > length_i() ) ||  ( pos + n - 1 > length_i() ) )
-       n = length_i() - pos + 1;
+  String retval;
+  if (n < 1)
+    return retval;
 
-    return String( byte_c_l() + pos -1, n );
+  retval = *this;
+  retval.strh_.trunc (n);
+  return retval;
 }
 
-
-// to  uppercase
 String
-String::upper()
+String::right_string (int n) const
 {
-    // not binary safe
-    assert( length_i() == strlen( ch_c_l() ) );
-    char *s = strh_.byte_l();
-    strupr( s );
+  if (n > length ())
     return *this;
-}
 
+  if (n < 1)
+    return "";
+
+  return String (strh_.c_str () + length () - n, n);
+}
 
-// to lowercase
-String 
-String::lower()
+String
+String::nomid_string (int index_i, int n) const
 {
-    // not binary safe
-    assert( length_i() == strlen( ch_c_l() ) );
-    char* s = strh_.byte_l();
-    strlwr(s);
+  if (index_i < 0)
+    {
+      n += index_i;
+      index_i = 0;
+    }
+  if (n <= 0)
     return *this;
+
+  return left_string (index_i) + right_string (length () - index_i - n);
 }
 
-String::String (double f, char const* fmt)
+String
+String::cut_string (int index_i, int n) const
 {
-    /* worst case would be printing HUGE (or 1/HUGE), which is approx
-       2e318, this number would have approx 318 zero's in its string.
+  if (index_i < 0)
+    {
+      n += index_i;
+      index_i = 0;
+    }
+
+  if (!length () || (index_i < 0) || (index_i >= length ()) || (n < 1))
+    return String ();
 
-      1024 is a safe length for the buffer
-      */
+  if ((n > length ()) || (index_i + n > length ()))
+    n = length () - index_i;
 
-    char buf[1024]; 
-    if (!fmt)
-       sprintf(buf, "%f", f);
-    else
-       sprintf(buf, fmt,f);
-    *this = buf;
+  return String (c_str () + index_i, n);
 }
+\f
 
-long
-String::value() const
+int
+String::to_int () const
 {
-    long l =0;
-    if (length_i()) {
-       int conv = sscanf(strh_.ch_c_l(), "%ld", &l);
-       assert(conv);
-    }
-    return l;
+  return String_convert::dec2int (*this);
 }
 
 double
-String::fvalue() const
+String::to_double () const
 {
-    double d =0;
-    if (length_i()) {
-       int conv = sscanf(strh_.ch_c_l(), "%lf", &d);
-       assert(conv);
-    }
-    return d;
+  return String_convert::dec2double (*this);
 }
 
+#ifdef STREAM_SUPPORT
+#include <iostream>
 
-String quoteString( String msg, String quote)
+ostream &
+operator << (ostream &os, String d)
 {
-    return msg + " `" + quote  + "' ";
+  d.print_on (os);
+  return os;
 }
 
-
-Byte*
-strrev( Byte* byte_l, int length_i )
+void
+String::print_on (ostream &os) const
 {
-  Byte by;
-  Byte* left_byte_l = byte_l;
-  Byte* right_byte_l = byte_l + length_i;
-
-  while ( right_byte_l > left_byte_l ) {
-    by = *left_byte_l;
-    *left_byte_l++ = *right_byte_l;
-    *right_byte_l-- = by;
-  }
-  return byte_l;
+  if (!strh_.is_binary_bo ())
+    os << c_str ();
+  else
+    for (int i = 0; i < length (); i++)
+      os << (Byte) (*this)[ i ];
 }
+#endif
 
+String
+String::substitute (String find, String replace)
+{
+  int n = find.length ();
+  int m = replace.length ();
+  for (ssize i = index (find), j = 0; i != NPOS;
+       i = right_string (length () - j).index (find))
+    {
+      *this = left_string (i + j)
+       + replace
+       + right_string (length () - j - i - n);
+      j += i + m;
+    }
+  return *this;
+}
 
-String 
-String::reversed() const
+String
+String::substitute (char find, char replace)
 {
-    String str = *this;
-    strrev( str.byte_l(), str.length_i() );
-    return str;    
+  for (ssize i = index (find); i != NPOS; i = index (find))
+    (*this)[i] = replace;
+  return *this;
+}
+
 }
+
+#endif /* !STD_STRING */
+