X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3e473156c6dbfb55dfc33e36746a957da53f5040..55021f25ff19ab334c4b8bf8a90836856471cf99:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index 85560f9d65..da831ccafa 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -256,15 +256,14 @@ wxString::wxString(const void *pStart, const void *pEnd) wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) { // first get necessary size - - size_t nLen = conv.MB2WC((wchar_t *) NULL, psz, 0); + size_t nLen = psz ? conv.MB2WC((wchar_t *) NULL, psz, 0) : 0; // nLength is number of *Unicode* characters here! - if (nLen > nLength) + if ((nLen != (size_t)-1) && (nLen > nLength)) nLen = nLength; // empty? - if ( nLen != 0 ) { + if ( (nLen != 0) && (nLen != (size_t)-1) ) { AllocBuffer(nLen); conv.MB2WC(m_pchData, psz, nLen); } @@ -275,15 +274,15 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) #else +#if wxUSE_WCHAR_T // from wide string wxString::wxString(const wchar_t *pwz) { // first get necessary size - - size_t nLen = wxWC2MB((char *) NULL, pwz, 0); + size_t nLen = pwz ? wxWC2MB((char *) NULL, pwz, 0) : 0; // empty? - if ( nLen != 0 ) { + if ( (nLen != 0) && (nLen != (size_t)-1) ) { AllocBuffer(nLen); wxWC2MB(m_pchData, pwz, nLen); } @@ -291,6 +290,7 @@ wxString::wxString(const wchar_t *pwz) Init(); } } +#endif #endif @@ -497,12 +497,14 @@ wxString& wxString::operator=(const unsigned char* psz) return *this; } +#if wxUSE_WCHAR_T wxString& wxString::operator=(const wchar_t *pwz) { wxString str(pwz); *this = str; return *this; } +#endif #endif @@ -983,14 +985,17 @@ int wxString::Printf(const wxChar *pszFormat, ...) int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) { // static buffer to avoid dynamic memory allocation each time - static char s_szScratch[1024]; + char s_szScratch[1024]; // using static buffer causes internal compiler err +#if 0 #if wxUSE_THREADS // protect the static buffer static wxCriticalSection critsect; wxCriticalSectionLocker lock(critsect); #endif +#endif -#if 1 // the new implementation +#if wxUSE_EXPERIMENTAL_PRINTF +// the new implementation Reinit(); for (size_t n = 0; pszFormat[n]; n++) @@ -1166,7 +1171,7 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) char *val = va_arg(argptr, char *); #if wxUSE_UNICODE // ASCII->Unicode constructor handles max_width right - wxString s(val, wxConv_libc, max_width); + wxString s(val, wxConvLibc, max_width); #else size_t len = wxSTRING_MAXLEN; if (val) { @@ -1187,8 +1192,8 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) if (s.Len() < min_width) s.Pad(min_width - s.Len(), _T(' '), adj_left); *this += s; - done = TRUE; } + done = TRUE; break; case _T('n'): if (ilen == 0) { @@ -1408,7 +1413,7 @@ size_t wxString::rfind(const wxString& str, size_t nStart) const wxASSERT( str.GetStringData()->IsValid() ); wxASSERT( nStart <= Len() ); - // # could be quicker than that + // TODO could be made much quicker than that const wxChar *p = c_str() + (nStart == npos ? Len() : nStart); while ( p >= c_str() + str.Len() ) { if ( wxStrncmp(p - str.Len(), str, str.Len()) == 0 ) @@ -1423,19 +1428,131 @@ size_t wxString::rfind(const wxString& str, size_t nStart) const #if !defined(__VISUALC__) || defined(__WIN32__) size_t wxString::rfind(const wxChar* sz, size_t nStart, size_t n) const { - return rfind(wxString(sz, n == npos ? 0 : n), nStart); + return rfind(wxString(sz, n == npos ? 0 : n), nStart); } size_t wxString::rfind(wxChar ch, size_t nStart) const { - wxASSERT( nStart <= Len() ); + if ( nStart == npos ) + { + nStart = Len(); + } + else + { + wxASSERT( nStart <= Len() ); + } - const wxChar *p = wxStrrchr(c_str() + nStart, ch); + const wxChar *p = wxStrrchr(c_str(), ch); - return p == NULL ? npos : p - c_str(); + if ( p == NULL ) + return npos; + + size_t result = p - c_str(); + return ( result > nStart ) ? npos : result; } #endif // VC++ 1.5 +size_t wxString::find_first_of(const wxChar* sz, size_t nStart) const +{ + const wxChar *start = c_str() + nStart; + const wxChar *firstOf = wxStrpbrk(start, sz); + if ( firstOf ) + return firstOf - start; + else + return npos; +} + +size_t wxString::find_last_of(const wxChar* sz, size_t nStart) const +{ + if ( nStart == npos ) + { + nStart = Len(); + } + else + { + wxASSERT( nStart <= Len() ); + } + + for ( const wxChar *p = c_str() + length() - 1; p >= c_str(); p-- ) + { + if ( wxStrchr(sz, *p) ) + return p - c_str(); + } + + return npos; +} + +size_t wxString::find_first_not_of(const wxChar* sz, size_t nStart) const +{ + if ( nStart == npos ) + { + nStart = Len(); + } + else + { + wxASSERT( nStart <= Len() ); + } + + size_t nAccept = wxStrspn(c_str() + nStart, sz); + if ( nAccept >= length() - nStart ) + return npos; + else + return nAccept; +} + +size_t wxString::find_first_not_of(wxChar ch, size_t nStart) const +{ + wxASSERT( nStart <= Len() ); + + for ( const wxChar *p = c_str() + nStart; *p; p++ ) + { + if ( *p != ch ) + return p - c_str(); + } + + return npos; +} + +size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart) const +{ + if ( nStart == npos ) + { + nStart = Len(); + } + else + { + wxASSERT( nStart <= Len() ); + } + + for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- ) + { + if ( !wxStrchr(sz, *p) ) + return p - c_str(); + } + + return npos; +} + +size_t wxString::find_last_not_of(wxChar ch, size_t nStart) const +{ + if ( nStart == npos ) + { + nStart = Len(); + } + else + { + wxASSERT( nStart <= Len() ); + } + + for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- ) + { + if ( *p != ch ) + return p - c_str(); + } + + return npos; +} + wxString wxString::substr(size_t nStart, size_t nLen) const { // npos means 'take all' @@ -1627,6 +1744,21 @@ void wxArrayString::Alloc(size_t nSize) m_nCount = 0; } +// minimizes the memory usage by freeing unused memory +void wxArrayString::Shrink() +{ + // only do it if we have some memory to free + if( m_nCount < m_nSize ) { + // allocates exactly as much memory as we need + wxChar **pNew = new wxChar *[m_nCount]; + + // copy data to new location + memcpy(pNew, m_pItems, m_nCount*sizeof(wxChar *)); + delete [] m_pItems; + m_pItems = pNew; + } +} + // searches the array for an item (forward or backwards) int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const { @@ -1788,13 +1920,18 @@ void wxArrayString::DoSort() // MBConv // ============================================================================ -WXDLLEXPORT_DATA(wxMBConv *) wxConv_current = &wxConv_libc; +WXDLLEXPORT_DATA(wxMBConv *) wxConvCurrent = &wxConvLibc; +#if !wxUSE_WCHAR_T +WXDLLEXPORT_DATA(wxMBConv) wxConvLibc, wxConvFile; +#endif + +#if wxUSE_WCHAR_T // ---------------------------------------------------------------------------- // standard libc conversion // ---------------------------------------------------------------------------- -WXDLLEXPORT_DATA(wxMBConv) wxConv_libc; +WXDLLEXPORT_DATA(wxMBConv) wxConvLibc; size_t wxMBConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const { @@ -1810,15 +1947,15 @@ size_t wxMBConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const // standard file conversion // ---------------------------------------------------------------------------- -WXDLLEXPORT_DATA(wxMBConv_file) wxConv_file; +WXDLLEXPORT_DATA(wxMBConvFile) wxConvFile; // just use the libc conversion for now -size_t wxMBConv_file::MB2WC(wchar_t *buf, const char *psz, size_t n) const +size_t wxMBConvFile::MB2WC(wchar_t *buf, const char *psz, size_t n) const { return wxMB2WC(buf, psz, n); } -size_t wxMBConv_file::WC2MB(char *buf, const wchar_t *psz, size_t n) const +size_t wxMBConvFile::WC2MB(char *buf, const wchar_t *psz, size_t n) const { return wxWC2MB(buf, psz, n); } @@ -1827,12 +1964,12 @@ size_t wxMBConv_file::WC2MB(char *buf, const wchar_t *psz, size_t n) const // standard gdk conversion // ---------------------------------------------------------------------------- -#ifdef __WXGTK__ -WXDLLEXPORT_DATA(wxMBConv_gdk) wxConv_gdk; +#ifdef __WXGTK12__ +WXDLLEXPORT_DATA(wxMBConvGdk) wxConvGdk; #include -size_t wxMBConv_gdk::MB2WC(wchar_t *buf, const char *psz, size_t n) const +size_t wxMBConvGdk::MB2WC(wchar_t *buf, const char *psz, size_t n) const { if (buf) { return gdk_mbstowcs((GdkWChar *)buf, psz, n); @@ -1844,7 +1981,7 @@ size_t wxMBConv_gdk::MB2WC(wchar_t *buf, const char *psz, size_t n) const } } -size_t wxMBConv_gdk::WC2MB(char *buf, const wchar_t *psz, size_t n) const +size_t wxMBConvGdk::WC2MB(char *buf, const wchar_t *psz, size_t n) const { char *mbstr = gdk_wcstombs((GdkWChar *)psz); size_t len = mbstr ? strlen(mbstr) : 0; @@ -1855,21 +1992,35 @@ size_t wxMBConv_gdk::WC2MB(char *buf, const wchar_t *psz, size_t n) const } return len; } -#endif +#endif // GTK > 1.0 // ---------------------------------------------------------------------------- // UTF-7 // ---------------------------------------------------------------------------- -WXDLLEXPORT_DATA(wxMBConv_UTF7) wxConv_UTF7; +WXDLLEXPORT_DATA(wxMBConvUTF7) wxConvUTF7; + +#if 0 +static char utf7_setD[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789'(),-./:?"; +static char utf7_setO[]="!\"#$%&*;<=>@[]^_`{|}"; +static char utf7_setB[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; +#endif // TODO: write actual implementations of UTF-7 here -size_t wxMBConv_UTF7::MB2WC(wchar_t *buf, const char *psz, size_t n) const +size_t wxMBConvUTF7::MB2WC(wchar_t * WXUNUSED(buf), + const char * WXUNUSED(psz), + size_t WXUNUSED(n)) const { return 0; } -size_t wxMBConv_UTF7::WC2MB(char *buf, const wchar_t *psz, size_t n) const +size_t wxMBConvUTF7::WC2MB(char * WXUNUSED(buf), + const wchar_t * WXUNUSED(psz), + size_t WXUNUSED(n)) const { return 0; } @@ -1878,17 +2029,74 @@ size_t wxMBConv_UTF7::WC2MB(char *buf, const wchar_t *psz, size_t n) const // UTF-8 // ---------------------------------------------------------------------------- -WXDLLEXPORT_DATA(wxMBConv_UTF8) wxConv_UTF8; +WXDLLEXPORT_DATA(wxMBConvUTF8) wxConvUTF8; + +static unsigned long utf8_max[]={0x7f,0x7ff,0xffff,0x1fffff,0x3ffffff,0x7fffffff,0xffffffff}; -// TODO: write actual implementations of UTF-8 here -size_t wxMBConv_UTF8::MB2WC(wchar_t *buf, const char *psz, size_t n) const +size_t wxMBConvUTF8::MB2WC(wchar_t *buf, const char *psz, size_t n) const { - return wxMB2WC(buf, psz, n); + size_t len = 0; + + while (*psz && ((!buf) || (len>cnt); + while (cnt--) { + cc = *psz++; + if ((cc&0xC0)!=0x80) { + // invalid UTF-8 sequence + return (size_t)-1; + } + res=(res<<6)|(cc&0x3f); + } + if (res<=utf8_max[ocnt]) { + // illegal UTF-8 encoding + return (size_t)-1; + } + if (buf) *buf++=res; + len++; + } + } + } + if (buf && (lenutf8_max[cnt]; cnt++); + if (!cnt) { + // plain ASCII char + if (buf) *buf++=cc; + len++; + } else { + len+=cnt+1; + if (buf) { + *buf++=(-128>>cnt)|((cc>>(cnt*6))&(0x3f>>cnt)); + while (cnt--) + *buf++=0x80|((cc>>(cnt*6))&0x3f); + } + } + } + if (buf && (lennames.Add(name); - } + if (token.GetNextToken() == _T("alias")) + cset->names.Add(token.GetNextToken()); } else if (cmd == _T("")) cset->names.Add(token.GetNextToken()); @@ -1953,12 +2162,13 @@ static void wxLoadCharacterSets(void) comchar = token.GetNextToken(); else if (cmd == _T("")) escchar = token.GetNextToken(); - else if (cmd == _T("")) { delete cset; - goto forget_it; // we don't support multibyte charsets ourselves (yet) + cset = (wxCharacterSet *) NULL; + break; // we don't support multibyte charsets ourselves (yet) } else if (cmd == _T("CHARMAP")) { - cset->data = (wchar_t *)calloc(256, sizeof(wxChar)); + cset->data = (wchar_t *)calloc(256, sizeof(wchar_t)); in_charset = TRUE; } else if (cmd == _T("END")) { @@ -1967,103 +2177,163 @@ static void wxLoadCharacterSets(void) } else if (in_charset) { // format: /x00 NULL (NUL) + // /x41 LATIN CAPITAL LETTER A wxString hex = token.GetNextToken(); + // skip whitespace (why doesn't wxStringTokenizer do this?) + while (wxIsEmpty(hex) && token.HasMoreTokens()) hex = token.GetNextToken(); wxString uni = token.GetNextToken(); - // just assume that we've got the right format - int pos = ::wxHexToDec(hex.Mid(2,2)); - unsigned long uni1 = ::wxHexToDec(uni.Mid(2,2)); - unsigned long uni2 = ::wxHexToDec(uni.Mid(4,2)); - cset->data[pos] = (uni1 << 16) | uni2; + // skip whitespace again + while (wxIsEmpty(uni) && token.HasMoreTokens()) uni = token.GetNextToken(); + + if ((hex.Len() > 2) && (hex.GetChar(0) == escchar) && (hex.GetChar(1) == _T('x')) && + (uni.Left(2) == _T("=0) { + unsigned long uni1 = ::wxHexToDec(uni.Mid(2,2)); + unsigned long uni2 = ::wxHexToDec(uni.Mid(4,2)); + cset->data[pos] = (uni1 << 16) | uni2; + // wxFprintf(stderr,_T("char %02x mapped to %04x (%c)\n"),pos,cset->data[pos],cset->data[pos]); + } + } } } - cset->names.Shrink(); - wxCharsets.Add(cset); - forget_it: - continue; + if (cset) { + cset->names.Shrink(); + wxCharsets.Add(cset); + } } } #endif wxCharsets.Shrink(); - already_loaded = TRUE; } -static wxCharacterSet *wxFindCharacterSet(const wxString& charset) +static wxCharacterSet *wxFindCharacterSet(const wxChar *charset) { + if (!charset) return (wxCharacterSet *)NULL; + wxLoadCharacterSets(); for (size_t n=0; n4) { - if (wxString(charset,4) == _T("8859")) { - codeset << _T("8859-"); - if (*charset == _T('-')) charset++; + // first, convert the character set name to standard form + wxString codeset; + if (wxString(charset,3).CmpNoCase(_T("ISO")) == 0) { + // make sure it's represented in the standard form: ISO_8859-1 + codeset = _T("ISO_"); + charset += 3; + if ((*charset == _T('-')) || (*charset == _T('_'))) charset++; + if (wxStrlen(charset)>4) { + if (wxString(charset,4) == _T("8859")) { + codeset << _T("8859-"); + if (*charset == _T('-')) charset++; + } } } - } - codeset << charset; - codeset.MakeUpper(); - cset = wxFindCharacterSet(codeset); + codeset << charset; + codeset.MakeUpper(); + m_name = wxStrdup(codeset.c_str()); + m_deferred = TRUE; #endif + } } -wxCSConv::~wxCSConv(void) +void wxCSConv::LoadNow() { +// wxPrintf(_T("Conversion request\n")); + if (m_deferred) { + if (!m_name) { +#ifdef __UNIX__ + wxChar *lang = wxGetenv(_T("LANG")); + wxChar *dot = lang ? wxStrchr(lang, _T('.')) : (wxChar *)NULL; + if (dot) SetName(dot+1); +#endif + } + m_cset = wxFindCharacterSet(m_name); + m_deferred = FALSE; + } } size_t wxCSConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const { + ((wxCSConv *)this)->LoadNow(); // discard constness if (buf) { - if (cset) { - for (size_t c=0; c<=n; c++) - buf[c] = cset->data[psz[c]]; + if (m_cset) { + for (size_t c=0; cdata[(unsigned char)(psz[c])]; } else { // latin-1 (direct) - for (size_t c=0; c<=n; c++) - buf[c] = psz[c]; + for (size_t c=0; cLoadNow(); // discard constness if (buf) { - if (cset) { - for (size_t c=0; c<=n; c++) { + if (m_cset) { + for (size_t c=0; cdata[n] != psz[c]); n++); + for (n=0; (n<256) && (m_cset->data[n] != psz[c]); n++); buf[c] = (n>0xff) ? '?' : n; } } else { // latin-1 (direct) - for (size_t c=0; c<=n; c++) + for (size_t c=0; c0xff) ? '?' : psz[c]; } + return n; } - return n; + return wcslen(psz); } +#endif//wxUSE_WCHAR_T + +#if wxUSE_WCHAR_T +const wxWCharBuffer wxMBConv::cMB2WC(const char *psz) const + { + if (psz) { + size_t nLen = MB2WC((wchar_t *) NULL, psz, 0); + wxWCharBuffer buf(nLen); + MB2WC(WCSTRINGCAST buf, psz, nLen); + return buf; + } else return wxWCharBuffer((wchar_t *) NULL); + } + +const wxCharBuffer wxMBConv::cWC2MB(const wchar_t *psz) const + { + if (psz) { + size_t nLen = WC2MB((char *) NULL, psz, 0); + wxCharBuffer buf(nLen); + WC2MB(MBSTRINGCAST buf, psz, nLen); + return buf; + } else return wxCharBuffer((char *) NULL); + } + +#endif//wxUSE_WCHAR_T +