string.h

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C头文件 代码 · 共 1,531 行 · 第 1/4 页

H
1,531
字号
///////////////////////////////////////////////////////////////////////////////
// Name:        wx/string.h
// Purpose:     wxString and wxArrayString classes
// Author:      Vadim Zeitlin
// Modified by:
// Created:     29/01/98
// RCS-ID:      $Id: string.h,v 1.206.2.3 2005/12/15 19:26:27 VZ Exp $
// Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence:     wxWindows licence
///////////////////////////////////////////////////////////////////////////////

/*
    Efficient string class [more or less] compatible with MFC CString,
    wxWidgets version 1 wxString and std::string and some handy functions
    missing from string.h.
*/

#ifndef _WX_WXSTRINGH__
#define _WX_WXSTRINGH__

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

#include "wx/defs.h"        // everybody should include this

#if defined(__WXMAC__) || defined(__VISAGECPP__)
    #include <ctype.h>
#endif

#if defined(__VISAGECPP__) && __IBMCPP__ >= 400
   // problem in VACPP V4 with including stdlib.h multiple times
   // strconv includes it anyway
#  include <stdio.h>
#  include <string.h>
#  include <stdarg.h>
#  include <limits.h>
#else
#  include <string.h>
#  include <stdio.h>
#  include <stdarg.h>
#  include <limits.h>
#  include <stdlib.h>
#endif

#ifdef HAVE_STRCASECMP_IN_STRINGS_H
    #include <strings.h>    // for strcasecmp()
#endif // HAVE_STRCASECMP_IN_STRINGS_H

#ifdef __WXPALMOS__
    #include <StringMgr.h>
#endif

#include "wx/wxchar.h"      // for wxChar
#include "wx/buffer.h"      // for wxCharBuffer
#include "wx/strconv.h"     // for wxConvertXXX() macros and wxMBConv classes

class WXDLLIMPEXP_BASE wxString;

// ---------------------------------------------------------------------------
// macros
// ---------------------------------------------------------------------------

// casts [unfortunately!] needed to call some broken functions which require
// "char *" instead of "const char *"
#define   WXSTRINGCAST (wxChar *)(const wxChar *)
#define   wxCSTRINGCAST (wxChar *)(const wxChar *)
#define   wxMBSTRINGCAST (char *)(const char *)
#define   wxWCSTRINGCAST (wchar_t *)(const wchar_t *)

// implementation only
#define   wxASSERT_VALID_INDEX(i) \
    wxASSERT_MSG( (size_t)(i) <= length(), _T("invalid index in wxString") )

// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------

// maximum possible length for a string means "take all string" everywhere
#define wxSTRING_MAXLEN wxStringBase::npos

// ----------------------------------------------------------------------------
// global data
// ----------------------------------------------------------------------------

// global pointer to empty string
extern WXDLLIMPEXP_DATA_BASE(const wxChar*) wxEmptyString;

// ---------------------------------------------------------------------------
// global functions complementing standard C string library replacements for
// strlen() and portable strcasecmp()
//---------------------------------------------------------------------------

// Use wxXXX() functions from wxchar.h instead! These functions are for
// backwards compatibility only.

// checks whether the passed in pointer is NULL and if the string is empty
inline bool IsEmpty(const char *p) { return (!p || !*p); }

// safe version of strlen() (returns 0 if passed NULL pointer)
inline size_t Strlen(const char *psz)
  { return psz ? strlen(psz) : 0; }

// portable strcasecmp/_stricmp
inline int Stricmp(const char *psz1, const char *psz2)
{
#if defined(__VISUALC__) && defined(__WXWINCE__)
  register char c1, c2;
  do {
    c1 = tolower(*psz1++);
    c2 = tolower(*psz2++);
  } while ( c1 && (c1 == c2) );

  return c1 - c2;
#elif defined(__VISUALC__) || ( defined(__MWERKS__) && defined(__INTEL__) )
  return _stricmp(psz1, psz2);
#elif defined(__SC__)
  return _stricmp(psz1, psz2);
#elif defined(__SALFORDC__)
  return stricmp(psz1, psz2);
#elif defined(__BORLANDC__)
  return stricmp(psz1, psz2);
#elif defined(__WATCOMC__)
  return stricmp(psz1, psz2);
#elif defined(__DJGPP__)
  return stricmp(psz1, psz2);
#elif defined(__EMX__)
  return stricmp(psz1, psz2);
#elif defined(__WXPM__)
  return stricmp(psz1, psz2);
#elif defined(__WXPALMOS__) || \
      defined(HAVE_STRCASECMP_IN_STRING_H) || \
      defined(HAVE_STRCASECMP_IN_STRINGS_H) || \
      defined(__GNUWIN32__)
  return strcasecmp(psz1, psz2);
#elif defined(__MWERKS__) && !defined(__INTEL__)
  register char c1, c2;
  do {
    c1 = tolower(*psz1++);
    c2 = tolower(*psz2++);
  } while ( c1 && (c1 == c2) );

  return c1 - c2;
#else
  // almost all compilers/libraries provide this function (unfortunately under
  // different names), that's why we don't implement our own which will surely
  // be more efficient than this code (uncomment to use):
  /*
    register char c1, c2;
    do {
      c1 = tolower(*psz1++);
      c2 = tolower(*psz2++);
    } while ( c1 && (c1 == c2) );

    return c1 - c2;
  */

  #error  "Please define string case-insensitive compare for your OS/compiler"
#endif  // OS/compiler
}

// ----------------------------------------------------------------------------
// deal with STL/non-STL/non-STL-but-wxUSE_STD_STRING
// ----------------------------------------------------------------------------

// in both cases we need to define wxStdString
#if wxUSE_STL || wxUSE_STD_STRING

#include "wx/beforestd.h"
#include <string>
#include "wx/afterstd.h"

#if wxUSE_UNICODE
    #ifdef HAVE_STD_WSTRING
        typedef std::wstring wxStdString;
    #else
        typedef std::basic_string<wxChar> wxStdString;
    #endif
#else
    typedef std::string wxStdString;
#endif

#endif // need <string>

#if wxUSE_STL

    // we don't need an extra ctor from std::string when copy ctor already does
    // the work
    #undef wxUSE_STD_STRING
    #define wxUSE_STD_STRING 0

    #if (defined(__GNUG__) && (__GNUG__ < 3)) || \
        (defined(_MSC_VER) && (_MSC_VER <= 1200))
        #define wxSTRING_BASE_HASNT_CLEAR
    #endif

    typedef wxStdString wxStringBase;
#else // if !wxUSE_STL

#if !defined(HAVE_STD_STRING_COMPARE) && \
    (!defined(__WX_SETUP_H__) || wxUSE_STL == 0)
    #define HAVE_STD_STRING_COMPARE
#endif

// ---------------------------------------------------------------------------
// string data prepended with some housekeeping info (used by wxString class),
// is never used directly (but had to be put here to allow inlining)
// ---------------------------------------------------------------------------

struct WXDLLIMPEXP_BASE wxStringData
{
  int     nRefs;        // reference count
  size_t  nDataLength,  // actual string length
          nAllocLength; // allocated memory size

  // mimics declaration 'wxChar data[nAllocLength]'
  wxChar* data() const { return (wxChar*)(this + 1); }

  // empty string has a special ref count so it's never deleted
  bool  IsEmpty()   const { return (nRefs == -1); }
  bool  IsShared()  const { return (nRefs > 1);   }

  // lock/unlock
  void  Lock()   { if ( !IsEmpty() ) nRefs++;                    }

  // VC++ will refuse to inline Unlock but profiling shows that it is wrong
#if defined(__VISUALC__) && (__VISUALC__ >= 1200)
  __forceinline
#endif
  // VC++ free must take place in same DLL as allocation when using non dll
  // run-time library (e.g. Multithreaded instead of Multithreaded DLL)
#if defined(__VISUALC__) && defined(_MT) && !defined(_DLL)
  void  Unlock() { if ( !IsEmpty() && --nRefs == 0) Free();  }
  // we must not inline deallocation since allocation is not inlined
  void  Free();
#else
  void  Unlock() { if ( !IsEmpty() && --nRefs == 0) free(this);  }
#endif

  // if we had taken control over string memory (GetWriteBuf), it's
  // intentionally put in invalid state
  void  Validate(bool b)  { nRefs = (b ? 1 : 0); }
  bool  IsValid() const   { return (nRefs != 0); }
};

class WXDLLIMPEXP_BASE wxStringBase
{
#if !wxUSE_STL
friend class WXDLLIMPEXP_BASE wxArrayString;
#endif
public :
  // an 'invalid' value for string index, moved to this place due to a CW bug
  static const size_t npos;
protected:
  // points to data preceded by wxStringData structure with ref count info
  wxChar *m_pchData;

  // accessor to string data
  wxStringData* GetStringData() const { return (wxStringData*)m_pchData - 1; }

  // string (re)initialization functions
    // initializes the string to the empty value (must be called only from
    // ctors, use Reinit() otherwise)
  void Init() { m_pchData = (wxChar *)wxEmptyString; }
    // initializaes the string with (a part of) C-string
  void InitWith(const wxChar *psz, size_t nPos = 0, size_t nLen = npos);
    // as Init, but also frees old data
  void Reinit() { GetStringData()->Unlock(); Init(); }

  // memory allocation
    // allocates memory for string of length nLen
  bool AllocBuffer(size_t nLen);
    // copies data to another string
  bool AllocCopy(wxString&, int, int) const;
    // effectively copies data to string
  bool AssignCopy(size_t, const wxChar *);

  // append a (sub)string
  bool ConcatSelf(size_t nLen, const wxChar *src, size_t nMaxLen);
  bool ConcatSelf(size_t nLen, const wxChar *src)
    { return ConcatSelf(nLen, src, nLen); }

  // functions called before writing to the string: they copy it if there
  // are other references to our data (should be the only owner when writing)
  bool CopyBeforeWrite();
  bool AllocBeforeWrite(size_t);

    // compatibility with wxString
  bool Alloc(size_t nLen);
public:
  // standard types
  typedef wxChar value_type;
  typedef wxChar char_type;
  typedef size_t size_type;
  typedef value_type& reference;
  typedef const value_type& const_reference;
  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type *iterator;
  typedef const value_type *const_iterator;

  // constructors and destructor
    // ctor for an empty string
  wxStringBase() { Init(); }
    // copy ctor
  wxStringBase(const wxStringBase& stringSrc)
  {
    wxASSERT_MSG( stringSrc.GetStringData()->IsValid(),
                  _T("did you forget to call UngetWriteBuf()?") );

    if ( stringSrc.empty() ) {
      // nothing to do for an empty string
      Init();
    }
    else {
      m_pchData = stringSrc.m_pchData;            // share same data
      GetStringData()->Lock();                    // => one more copy
    }
  }
    // string containing nRepeat copies of ch
  wxStringBase(size_type nRepeat, wxChar ch);
    // ctor takes first nLength characters from C string
    // (default value of npos means take all the string)
  wxStringBase(const wxChar *psz)
      { InitWith(psz, 0, npos); }
  wxStringBase(const wxChar *psz, size_t nLength)
      { InitWith(psz, 0, nLength); }
  wxStringBase(const wxChar *psz, wxMBConv& WXUNUSED(conv), size_t nLength = npos)
      { InitWith(psz, 0, nLength); }
    // take nLen chars starting at nPos
  wxStringBase(const wxStringBase& str, size_t nPos, size_t nLen)
  {
    wxASSERT_MSG( str.GetStringData()->IsValid(),
                  _T("did you forget to call UngetWriteBuf()?") );
    Init();
    size_t strLen = str.length() - nPos; nLen = strLen < nLen ? strLen : nLen;
    InitWith(str.c_str(), nPos, nLen);
  }
    // take all characters from pStart to pEnd
  wxStringBase(const void *pStart, const void *pEnd);

    // dtor is not virtual, this class must not be inherited from!
  ~wxStringBase()
  {
#if defined(__VISUALC__) && (__VISUALC__ >= 1200)
      //RN - according to the above VC++ does indeed inline this,
      //even though it spits out two warnings
      #pragma warning (disable:4714)
#endif

      GetStringData()->Unlock();
  }

#if defined(__VISUALC__) && (__VISUALC__ >= 1200)
    //re-enable inlining warning
    #pragma warning (default:4714)
#endif
  // overloaded assignment
    // from another wxString
  wxStringBase& operator=(const wxStringBase& stringSrc);
    // from a character
  wxStringBase& operator=(wxChar ch);
    // from a C string
  wxStringBase& operator=(const wxChar *psz);

    // return the length of the string
  size_type size() const { return GetStringData()->nDataLength; }
    // return the length of the string
  size_type length() const { return size(); }
    // return the maximum size of the string
  size_type max_size() const { return wxSTRING_MAXLEN; }
    // resize the string, filling the space with c if c != 0
  void resize(size_t nSize, wxChar ch = wxT('\0'));
    // delete the contents of the string
  void clear() { erase(0, npos); }
    // returns true if the string is empty
  bool empty() const { return size() == 0; }
    // inform string about planned change in size
  void reserve(size_t sz) { Alloc(sz); }
  size_type capacity() const { return GetStringData()->nAllocLength; }

  // lib.string.access
    // return the character at position n

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?