1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/tokenzr.cpp
3 // Purpose: String tokenizer
4 // Author: Guilhem Lavaux
5 // Modified by: Vadim Zeitlin (almost full rewrite)
8 // Copyright: (c) Guilhem Lavaux
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #include "wx/tokenzr.h"
30 #include "wx/arrstr.h"
34 // Required for wxIs... functions
37 // ============================================================================
39 // ============================================================================
41 // ----------------------------------------------------------------------------
42 // wxStringTokenizer construction
43 // ----------------------------------------------------------------------------
45 wxStringTokenizer::wxStringTokenizer(const wxString
& str
,
46 const wxString
& delims
,
47 wxStringTokenizerMode mode
)
49 SetString(str
, delims
, mode
);
52 void wxStringTokenizer::SetString(const wxString
& str
,
53 const wxString
& delims
,
54 wxStringTokenizerMode mode
)
56 if ( mode
== wxTOKEN_DEFAULT
)
58 // by default, we behave like strtok() if the delimiters are only
59 // whitespace characters and as wxTOKEN_RET_EMPTY otherwise (for
60 // whitespace delimiters, strtok() behaviour is better because we want
61 // to count consecutive spaces as one delimiter)
62 wxString::const_iterator p
;
63 for ( p
= delims
.begin(); p
!= delims
.end(); ++p
)
69 if ( p
!= delims
.end() )
71 // not whitespace char in delims
72 mode
= wxTOKEN_RET_EMPTY
;
77 mode
= wxTOKEN_STRTOK
;
87 void wxStringTokenizer::Reinit(const wxString
& str
)
89 wxASSERT_MSG( IsOk(), _T("you should call SetString() first") );
93 m_lastDelim
= _T('\0');
96 // ----------------------------------------------------------------------------
97 // access to the tokens
98 // ----------------------------------------------------------------------------
100 // do we have more of them?
101 bool wxStringTokenizer::HasMoreTokens() const
103 wxCHECK_MSG( IsOk(), false, _T("you should call SetString() first") );
105 if ( m_string
.find_first_not_of(m_delims
, m_pos
) != wxString::npos
)
107 // there are non delimiter characters left, so we do have more tokens
113 case wxTOKEN_RET_EMPTY
:
114 case wxTOKEN_RET_DELIMS
:
115 // special hack for wxTOKEN_RET_EMPTY: we should return the initial
116 // empty token even if there are only delimiters after it
117 return m_pos
== 0 && !m_string
.empty();
119 case wxTOKEN_RET_EMPTY_ALL
:
120 // special hack for wxTOKEN_RET_EMPTY_ALL: we can know if we had
121 // already returned the trailing empty token after the last
122 // delimiter by examining m_lastDelim: it is set to NUL if we run
123 // up to the end of the string in GetNextToken(), but if it is not
124 // NUL yet we still have this last token to return even if m_pos is
125 // already at m_string.length()
126 return m_pos
< m_string
.length() || m_lastDelim
!= _T('\0');
128 case wxTOKEN_INVALID
:
129 case wxTOKEN_DEFAULT
:
130 wxFAIL_MSG( _T("unexpected tokenizer mode") );
134 // never return empty delimiters
141 // count the number of (remaining) tokens in the string
142 size_t wxStringTokenizer::CountTokens() const
144 wxCHECK_MSG( IsOk(), 0, _T("you should call SetString() first") );
146 // VZ: this function is IMHO not very useful, so it's probably not very
147 // important if its implementation here is not as efficient as it
148 // could be -- but OTOH like this we're sure to get the correct answer
150 wxStringTokenizer
tkz(m_string
.c_str() + m_pos
, m_delims
, m_mode
);
153 while ( tkz
.HasMoreTokens() )
157 (void)tkz
.GetNextToken();
163 // ----------------------------------------------------------------------------
165 // ----------------------------------------------------------------------------
167 wxString
wxStringTokenizer::GetNextToken()
172 if ( !HasMoreTokens() )
177 // find the end of this token
178 size_t pos
= m_string
.find_first_of(m_delims
, m_pos
);
180 // and the start of the next one
181 if ( pos
== wxString::npos
)
183 // no more delimiters, the token is everything till the end of
185 token
.assign(m_string
, m_pos
, wxString::npos
);
188 m_pos
= m_string
.length();
190 // it wasn't terminated
191 m_lastDelim
= _T('\0');
193 else // we found a delimiter at pos
195 // in wxTOKEN_RET_DELIMS mode we return the delimiter character
196 // with token, otherwise leave it out
197 size_t len
= pos
- m_pos
;
198 if ( m_mode
== wxTOKEN_RET_DELIMS
)
201 token
.assign(m_string
, m_pos
, len
);
203 // skip the token and the trailing delimiter
206 m_lastDelim
= m_string
[pos
];
209 while ( !AllowEmpty() && token
.empty() );
214 // ----------------------------------------------------------------------------
216 // ----------------------------------------------------------------------------
218 wxArrayString
wxStringTokenize(const wxString
& str
,
219 const wxString
& delims
,
220 wxStringTokenizerMode mode
)
222 wxArrayString tokens
;
223 wxStringTokenizer
tk(str
, delims
, mode
);
224 while ( tk
.HasMoreTokens() )
226 tokens
.Add(tk
.GetNextToken());