X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3f8e5072f7391db2158f44c6b9209bbb3db6eb06..38a5c64e29ab1d081af309a73c7af94069cf799f:/src/common/tokenzr.cpp diff --git a/src/common/tokenzr.cpp b/src/common/tokenzr.cpp index b6272da149..f69e8e6a73 100644 --- a/src/common/tokenzr.cpp +++ b/src/common/tokenzr.cpp @@ -2,7 +2,7 @@ // Name: tokenzr.cpp // Purpose: String tokenizer // Author: Guilhem Lavaux -// Modified by: Vadim Zeitlin +// Modified by: Vadim Zeitlin (almost full rewrite) // Created: 04/22/98 // RCS-ID: $Id$ // Copyright: (c) Guilhem Lavaux @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "tokenzr.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -29,6 +25,7 @@ #endif #include "wx/tokenzr.h" +#include "wx/arrstr.h" // Required for wxIs... functions #include @@ -89,9 +86,7 @@ void wxStringTokenizer::Reinit(const wxString& str) m_string = str; m_pos = 0; - - // empty string doesn't have any tokens - m_hasMore = !m_string.empty(); + m_lastDelim = _T('\0'); } // ---------------------------------------------------------------------------- @@ -101,45 +96,63 @@ void wxStringTokenizer::Reinit(const wxString& str) // do we have more of them? bool wxStringTokenizer::HasMoreTokens() const { - wxCHECK_MSG( IsOk(), FALSE, _T("you should call SetString() first") ); + wxCHECK_MSG( IsOk(), false, _T("you should call SetString() first") ); - if ( m_string.find_first_not_of(m_delims) == wxString::npos ) + if ( m_string.find_first_not_of(m_delims, m_pos) != wxString::npos ) { - // no non empty tokens left, but in wxTOKEN_RET_EMPTY_ALL mode we - // still may return TRUE if GetNextToken() wasn't called yet for the - // last trailing empty token - return m_mode == wxTOKEN_RET_EMPTY_ALL ? m_hasMore : FALSE; + // there are non delimiter characters left, so we do have more tokens + return true; } - else + + switch ( m_mode ) { - // there are non delimiter characters left, hence we do have more - // tokens - return TRUE; + case wxTOKEN_RET_EMPTY: + case wxTOKEN_RET_DELIMS: + // special hack for wxTOKEN_RET_EMPTY: we should return the initial + // empty token even if there are only delimiters after it + return m_pos == 0 && !m_string.empty(); + + case wxTOKEN_RET_EMPTY_ALL: + // special hack for wxTOKEN_RET_EMPTY_ALL: we can know if we had + // already returned the trailing empty token after the last + // delimiter by examining m_lastDelim: it is set to NUL if we run + // up to the end of the string in GetNextToken(), but if it is not + // NUL yet we still have this last token to return even if m_pos is + // already at m_string.length() + return m_pos < m_string.length() || m_lastDelim != _T('\0'); + + case wxTOKEN_INVALID: + case wxTOKEN_DEFAULT: + wxFAIL_MSG( _T("unexpected tokenizer mode") ); + // fall through + + case wxTOKEN_STRTOK: + // never return empty delimiters + break; } + + return false; } -// count the number of tokens in the string +// count the number of (remaining) tokens in the string size_t wxStringTokenizer::CountTokens() const { wxCHECK_MSG( IsOk(), 0, _T("you should call SetString() first") ); // VZ: this function is IMHO not very useful, so it's probably not very - // important if it's implementation here is not as efficient as it - // could be - but OTOH like this we're sure to get the correct answer + // important if its implementation here is not as efficient as it + // could be -- but OTOH like this we're sure to get the correct answer // in all modes - wxStringTokenizer *self = (wxStringTokenizer *)this; // const_cast - wxString stringInitial = m_string; + wxStringTokenizer tkz(m_string.c_str() + m_pos, m_delims, m_mode); size_t count = 0; - while ( self->HasMoreTokens() ) + while ( tkz.HasMoreTokens() ) { count++; - (void)self->GetNextToken(); + (void)tkz.GetNextToken(); } - self->Reinit(stringInitial); - return count; } @@ -149,9 +162,6 @@ size_t wxStringTokenizer::CountTokens() const wxString wxStringTokenizer::GetNextToken() { - // strtok() doesn't return empty tokens, all other modes do - bool allowEmpty = m_mode != wxTOKEN_STRTOK; - wxString token; do { @@ -159,40 +169,58 @@ wxString wxStringTokenizer::GetNextToken() { break; } + // find the end of this token - size_t pos = m_string.find_first_of(m_delims); + size_t pos = m_string.find_first_of(m_delims, m_pos); // and the start of the next one if ( pos == wxString::npos ) { // no more delimiters, the token is everything till the end of // string - token = m_string; + token.assign(m_string, m_pos, wxString::npos); - m_pos += m_string.length(); - m_string.clear(); + // skip the token + m_pos = m_string.length(); - // no more tokens in this string, even in wxTOKEN_RET_EMPTY_ALL - // mode (we will return the trailing one right now in this case) - m_hasMore = FALSE; + // it wasn't terminated + m_lastDelim = _T('\0'); } - else + else // we found a delimiter at pos { - size_t pos2 = pos + 1; - // in wxTOKEN_RET_DELIMS mode we return the delimiter character - // with token - token = wxString(m_string, m_mode == wxTOKEN_RET_DELIMS ? pos2 - : pos); + // with token, otherwise leave it out + size_t len = pos - m_pos; + if ( m_mode == wxTOKEN_RET_DELIMS ) + len++; - // remove token with the following it delimiter from string - m_string.erase(0, pos2); + token.assign(m_string, m_pos, len); - // keep track of the position in the original string too - m_pos += pos2; + // skip the token and the trailing delimiter + m_pos = pos + 1; + + m_lastDelim = m_string[pos]; } } - while ( !allowEmpty && token.empty() ); + while ( !AllowEmpty() && token.empty() ); return token; } + +// ---------------------------------------------------------------------------- +// public functions +// ---------------------------------------------------------------------------- + +wxArrayString wxStringTokenize(const wxString& str, + const wxString& delims, + wxStringTokenizerMode mode) +{ + wxArrayString tokens; + wxStringTokenizer tk(str, delims, mode); + while ( tk.HasMoreTokens() ) + { + tokens.Add(tk.GetNextToken()); + } + + return tokens; +}