blob: 9f3d781d884c11ccf74ea21621d8c52b5e7200ad [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39#include <ucommon-config.h>
40#include <commoncpp/config.h>
41#include <commoncpp/export.h>
42#include <commoncpp/string.h>
43#include <commoncpp/exception.h>
44#include <commoncpp/thread.h>
45#include <commoncpp/tokenizer.h>
46#include <cstdlib>
47#include <cstdio>
48
49NAMESPACE_COMMONCPP
50using namespace std;
51
52// sorted by the usual probability of occurence
53// see also: manpage of isspace()
54const char * const StringTokenizer::SPACE=" \t\n\r\f\v";
55
56StringTokenizer::StringTokenizer (const char *_str, const char *_delim, bool _skipAll, bool _trim) :
57str(_str),delim(_delim),skipAll(_skipAll),trim(_trim)
58{
59 if (str == 0)
60 itEnd = iterator(*this, 0);
61 else
62 itEnd = iterator(*this,strchr(str, '\0')+1);
63}
64
65StringTokenizer::StringTokenizer (const char *s) :
66str(s), delim(SPACE), skipAll(false),trim(true)
67{
68 if (str == 0)
69 itEnd = iterator(*this, 0);
70 else
71 itEnd = iterator(*this,strchr(str, '\0')+1);
72}
73
74
75StringTokenizer::iterator& StringTokenizer::iterator::operator ++ () THROWS (StringTokenizer::NoSuchElementException)
76{
77
78 // someone requested to read beyond the end .. tsts
79 if (endp == myTok->itEnd.endp)
80 THROW (NoSuchElementException());
81
82 if (token) {
83 // this is to help people find their bugs, if they
84 // still maintain a pointer to this invalidated
85 // area :-)
86 *token = '\0';
87 delete[] token;
88 token = 0;
89 }
90
91 start = ++endp;
92 if (endp == myTok->itEnd.endp) return *this; // done
93
94 // search for next delimiter
95 while (*endp && strchr(myTok->delim, *endp)==NULL)
96 ++endp;
97
98 tokEnd = endp;
99
100 if (*endp && myTok->skipAll) { // skip all delimiters
101 while (*(endp+1) && strchr(myTok->delim, *(endp+1)))
102 ++endp;
103 }
104 return *this;
105}
106
107/*
108 * if no one requests the token, no time is spent skipping the whitespaces
109 * or allocating memory.
110 */
111const char * StringTokenizer::iterator::operator * () THROWS (StringTokenizer::NoSuchElementException)
112{
113 // someone requested to read beyond the end .. tsts
114 if (endp == myTok->itEnd.endp)
115 THROW (NoSuchElementException());
116
117 if (!token) {
118 /*
119 * someone requests this token; return a copy to provide
120 * a NULL terminated string.
121 */
122
123 /* don't clobber tokEnd, it is used in nextDelimiter() */
124 const char *wsTokEnd = tokEnd;
125 if (myTok->trim) {
126 while (wsTokEnd > start && strchr(SPACE, *start))
127 ++start;
128 while (wsTokEnd > start && strchr(SPACE,*(wsTokEnd-1)))
129 --wsTokEnd;
130 }
131 size_t tokLen = wsTokEnd - start;
132 if (start > wsTokEnd) {
133 tokLen = 0;
134 }
135 token = newString(start, tokLen + 1);
136 }
137 return token;
138}
139
140END_NAMESPACE
141
142/** EMACS **
143 * Local variables:
144 * mode: c++
145 * c-basic-offset: 4
146 * End:
147 */