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"
33 // Required for wxIs... functions
36 // ============================================================================
38 // ============================================================================
40 // ----------------------------------------------------------------------------
41 // wxStringTokenizer construction
42 // ----------------------------------------------------------------------------
44 wxStringTokenizer::wxStringTokenizer(const wxString
& str
,
45 const wxString
& delims
,
46 wxStringTokenizerMode mode
)
48 SetString(str
, delims
, mode
);
51 void wxStringTokenizer::SetString(const wxString
& str
,
52 const wxString
& delims
,
53 wxStringTokenizerMode mode
)
55 if ( mode
== wxTOKEN_DEFAULT
)
57 // by default, we behave like strtok() if the delimiters are only
58 // whitespace characters and as wxTOKEN_RET_EMPTY otherwise (for
59 // whitespace delimiters, strtok() behaviour is better because we want
60 // to count consecutive spaces as one delimiter)
62 for ( p
= delims
.c_str(); *p
; p
++ )
70 // not whitespace char in delims
71 mode
= wxTOKEN_RET_EMPTY
;
76 mode
= wxTOKEN_STRTOK
;
86 void wxStringTokenizer::Reinit(const wxString
& str
)
88 wxASSERT_MSG( IsOk(), _T("you should call SetString() first") );
92 m_lastDelim
= _T('\0');
95 // ----------------------------------------------------------------------------
96 // access to the tokens
97 // ----------------------------------------------------------------------------
99 // do we have more of them?
100 bool wxStringTokenizer::HasMoreTokens() const
102 wxCHECK_MSG( IsOk(), false, _T("you should call SetString() first") );
104 if ( m_string
.find_first_not_of(m_delims
, m_pos
) != wxString::npos
)
106 // there are non delimiter characters left, so we do have more tokens
112 case wxTOKEN_RET_EMPTY
:
113 case wxTOKEN_RET_DELIMS
:
114 // special hack for wxTOKEN_RET_EMPTY: we should return the initial
115 // empty token even if there are only delimiters after it
116 return m_pos
== 0 && !m_string
.empty();
118 case wxTOKEN_RET_EMPTY_ALL
:
119 // special hack for wxTOKEN_RET_EMPTY_ALL: we can know if we had
120 // already returned the trailing empty token after the last
121 // delimiter by examining m_lastDelim: it is set to NUL if we run
122 // up to the end of the string in GetNextToken(), but if it is not
123 // NUL yet we still have this last token to return even if m_pos is
124 // already at m_string.length()
125 return m_pos
< m_string
.length() || m_lastDelim
!= _T('\0');
127 case wxTOKEN_INVALID
:
128 case wxTOKEN_DEFAULT
:
129 wxFAIL_MSG( _T("unexpected tokenizer mode") );
133 // never return empty delimiters
140 // count the number of (remaining) tokens in the string
141 size_t wxStringTokenizer::CountTokens() const
143 wxCHECK_MSG( IsOk(), 0, _T("you should call SetString() first") );
145 // VZ: this function is IMHO not very useful, so it's probably not very
146 // important if its implementation here is not as efficient as it
147 // could be -- but OTOH like this we're sure to get the correct answer
149 wxStringTokenizer
tkz(m_string
.c_str() + m_pos
, m_delims
, m_mode
);
152 while ( tkz
.HasMoreTokens() )
156 (void)tkz
.GetNextToken();
162 // ----------------------------------------------------------------------------
164 // ----------------------------------------------------------------------------
166 wxString
wxStringTokenizer::GetNextToken()
171 if ( !HasMoreTokens() )
176 // find the end of this token
177 size_t pos
= m_string
.find_first_of(m_delims
, m_pos
);
179 // and the start of the next one
180 if ( pos
== wxString::npos
)
182 // no more delimiters, the token is everything till the end of
184 token
.assign(m_string
, m_pos
, wxString::npos
);
187 m_pos
= m_string
.length();
189 // it wasn't terminated
190 m_lastDelim
= _T('\0');
192 else // we found a delimiter at pos
194 // in wxTOKEN_RET_DELIMS mode we return the delimiter character
195 // with token, otherwise leave it out
196 size_t len
= pos
- m_pos
;
197 if ( m_mode
== wxTOKEN_RET_DELIMS
)
200 token
.assign(m_string
, m_pos
, len
);
202 // skip the token and the trailing delimiter
205 m_lastDelim
= m_string
[pos
];
208 while ( !AllowEmpty() && token
.empty() );
213 // ----------------------------------------------------------------------------
215 // ----------------------------------------------------------------------------
217 wxArrayString
wxStringTokenize(const wxString
& str
,
218 const wxString
& delims
,
219 wxStringTokenizerMode mode
)
221 wxArrayString tokens
;
222 wxStringTokenizer
tk(str
, delims
, mode
);
223 while ( tk
.HasMoreTokens() )
225 tokens
.Add(tk
.GetNextToken());