1/*=============================================================================
2    Copyright (c) 2001-2003 Joel de Guzman
3    Copyright (c) 2001-2003 Daniel Nuffer
4    http://spirit.sourceforge.net/
5
6    Use, modification and distribution is subject to the Boost Software
7    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8    http://www.boost.org/LICENSE_1_0.txt)
9=============================================================================*/
10#ifndef BOOST_XPRESSIVE_SPIRIT_BASIC_CHSET_IPP
11#define BOOST_XPRESSIVE_SPIRIT_BASIC_CHSET_IPP
12
13///////////////////////////////////////////////////////////////////////////////
14#include <bitset>
15#include <boost/xpressive/detail/utility/chset/basic_chset.hpp>
16
17///////////////////////////////////////////////////////////////////////////////
18namespace boost { namespace xpressive { namespace detail
19{
20
21///////////////////////////////////////////////////////////////////////////////
22//
23//  basic_chset: character set implementation
24//
25///////////////////////////////////////////////////////////////////////////////
26template<typename Char>
27inline basic_chset<Char>::basic_chset()
28{
29}
30
31//////////////////////////////////
32template<typename Char>
33inline basic_chset<Char>::basic_chset(basic_chset const &arg)
34  : rr_(arg.rr_)
35{
36}
37
38//////////////////////////////////
39template<typename Char>
40inline bool basic_chset<Char>::empty() const
41{
42    return this->rr_.empty();
43}
44
45//////////////////////////////////
46template<typename Char>
47template<typename Traits>
48inline bool basic_chset<Char>::test(Char v, Traits const &, mpl::false_) const // case-sensitive
49{
50    return this->rr_.test(v);
51}
52
53//////////////////////////////////
54template<typename Char>
55template<typename Traits>
56inline bool basic_chset<Char>::test(Char v, Traits const &tr, mpl::true_) const // case-insensitive
57{
58    return this->rr_.test(v, tr);
59}
60
61//////////////////////////////////
62template<typename Char>
63inline void basic_chset<Char>::set(Char from, Char to)
64{
65    this->rr_.set(range<Char>(from, to));
66}
67
68//////////////////////////////////
69template<typename Char>
70template<typename Traits>
71inline void basic_chset<Char>::set(Char from, Char to, Traits const &)
72{
73    this->rr_.set(range<Char>(from, to));
74}
75
76//////////////////////////////////
77template<typename Char>
78inline void basic_chset<Char>::set(Char c)
79{
80    this->rr_.set(range<Char>(c, c));
81}
82
83//////////////////////////////////
84template<typename Char>
85template<typename Traits>
86inline void basic_chset<Char>::set(Char c, Traits const &)
87{
88    this->rr_.set(range<Char>(c, c));
89}
90
91//////////////////////////////////
92template<typename Char>
93inline void basic_chset<Char>::clear(Char c)
94{
95    this->rr_.clear(range<Char>(c, c));
96}
97
98//////////////////////////////////
99template<typename Char>
100template<typename Traits>
101inline void basic_chset<Char>::clear(Char c, Traits const &)
102{
103    this->rr_.clear(range<Char>(c, c));
104}
105
106//////////////////////////////////
107template<typename Char>
108inline void basic_chset<Char>::clear(Char from, Char to)
109{
110    this->rr_.clear(range<Char>(from, to));
111}
112
113//////////////////////////////////
114template<typename Char>
115template<typename Traits>
116inline void basic_chset<Char>::clear(Char from, Char to, Traits const &)
117{
118    this->rr_.clear(range<Char>(from, to));
119}
120
121//////////////////////////////////
122template<typename Char>
123inline void basic_chset<Char>::clear()
124{
125    this->rr_.clear();
126}
127
128/////////////////////////////////
129template<typename Char>
130inline void basic_chset<Char>::inverse()
131{
132    // BUGBUG is this right? Does this handle icase correctly?
133    basic_chset<Char> inv;
134    inv.set((std::numeric_limits<Char>::min)(), (std::numeric_limits<Char>::max)());
135    inv -= *this;
136    this->swap(inv);
137}
138
139/////////////////////////////////
140template<typename Char>
141inline void basic_chset<Char>::swap(basic_chset<Char> &that)
142{
143    this->rr_.swap(that.rr_);
144}
145
146/////////////////////////////////
147template<typename Char>
148inline basic_chset<Char> &
149basic_chset<Char>::operator |=(basic_chset<Char> const &that)
150{
151    typedef typename range_run<Char>::const_iterator const_iterator;
152    for(const_iterator iter = that.rr_.begin(); iter != that.rr_.end(); ++iter)
153    {
154        this->rr_.set(*iter);
155    }
156    return *this;
157}
158
159/////////////////////////////////
160template<typename Char>
161inline basic_chset<Char> &
162basic_chset<Char>::operator &=(basic_chset<Char> const &that)
163{
164    basic_chset<Char> inv;
165    inv.set((std::numeric_limits<Char>::min)(), (std::numeric_limits<Char>::max)());
166    inv -= that;
167    *this -= inv;
168    return *this;
169}
170
171/////////////////////////////////
172template<typename Char>
173inline basic_chset<Char> &
174basic_chset<Char>::operator -=(basic_chset<Char> const &that)
175{
176    typedef typename range_run<Char>::const_iterator const_iterator;
177    for(const_iterator iter = that.rr_.begin(); iter != that.rr_.end(); ++iter)
178    {
179        this->rr_.clear(*iter);
180    }
181    return *this;
182}
183
184/////////////////////////////////
185template<typename Char>
186inline basic_chset<Char> &
187basic_chset<Char>::operator ^=(basic_chset<Char> const &that)
188{
189    basic_chset bma = that;
190    bma -= *this;
191    *this -= that;
192    *this |= bma;
193    return *this;
194}
195
196#if(CHAR_BIT == 8)
197
198///////////////////////////////////////////////////////////////////////////////
199//
200//  basic_chset: specializations for 8 bit chars using std::bitset
201//
202///////////////////////////////////////////////////////////////////////////////
203template<typename Char>
204inline basic_chset_8bit<Char>::basic_chset_8bit()
205{
206}
207
208/////////////////////////////////
209template<typename Char>
210inline basic_chset_8bit<Char>::basic_chset_8bit(basic_chset_8bit<Char> const &arg)
211  : bset_(arg.bset_)
212{
213}
214
215/////////////////////////////////
216template<typename Char>
217inline bool basic_chset_8bit<Char>::empty() const
218{
219    return !this->bset_.any();
220}
221
222/////////////////////////////////
223template<typename Char>
224template<typename Traits>
225inline bool basic_chset_8bit<Char>::test(Char v, Traits const &, mpl::false_) const // case-sensitive
226{
227    return this->bset_.test((unsigned char)v);
228}
229
230/////////////////////////////////
231template<typename Char>
232template<typename Traits>
233inline bool basic_chset_8bit<Char>::test(Char v, Traits const &tr, mpl::true_) const // case-insensitive
234{
235    return this->bset_.test((unsigned char)tr.translate_nocase(v));
236}
237
238/////////////////////////////////
239template<typename Char>
240inline void basic_chset_8bit<Char>::set(Char from, Char to)
241{
242    for(int i = from; i <= to; ++i)
243    {
244        this->bset_.set((unsigned char)i);
245    }
246}
247
248/////////////////////////////////
249template<typename Char>
250template<typename Traits>
251inline void basic_chset_8bit<Char>::set(Char from, Char to, Traits const &tr)
252{
253    for(int i = from; i <= to; ++i)
254    {
255        this->bset_.set((unsigned char)tr.translate_nocase((Char)i));
256    }
257}
258
259/////////////////////////////////
260template<typename Char>
261inline void basic_chset_8bit<Char>::set(Char c)
262{
263    this->bset_.set((unsigned char)c);
264}
265
266/////////////////////////////////
267template<typename Char>
268template<typename Traits>
269inline void basic_chset_8bit<Char>::set(Char c, Traits const &tr)
270{
271    this->bset_.set((unsigned char)tr.translate_nocase(c));
272}
273
274/////////////////////////////////
275template<typename Char>
276inline void basic_chset_8bit<Char>::clear(Char from, Char to)
277{
278    for(int i = from; i <= to; ++i)
279    {
280        this->bset_.reset((unsigned char)i);
281    }
282}
283
284/////////////////////////////////
285template<typename Char>
286template<typename Traits>
287inline void basic_chset_8bit<Char>::clear(Char from, Char to, Traits const &tr)
288{
289    for(int i = from; i <= to; ++i)
290    {
291        this->bset_.reset((unsigned char)tr.translate_nocase((Char)i));
292    }
293}
294
295/////////////////////////////////
296template<typename Char>
297inline void basic_chset_8bit<Char>::clear(Char c)
298{
299    this->bset_.reset((unsigned char)c);
300}
301
302/////////////////////////////////
303template<typename Char>
304template<typename Traits>
305inline void basic_chset_8bit<Char>::clear(Char c, Traits const &tr)
306{
307    this->bset_.reset((unsigned char)tr.tranlsate_nocase(c));
308}
309
310/////////////////////////////////
311template<typename Char>
312inline void basic_chset_8bit<Char>::clear()
313{
314    this->bset_.reset();
315}
316
317/////////////////////////////////
318template<typename Char>
319inline void basic_chset_8bit<Char>::inverse()
320{
321    this->bset_.flip();
322}
323
324/////////////////////////////////
325template<typename Char>
326inline void basic_chset_8bit<Char>::swap(basic_chset_8bit<Char> &that)
327{
328    std::swap(this->bset_, that.bset_);
329}
330
331/////////////////////////////////
332template<typename Char>
333inline basic_chset_8bit<Char> &
334basic_chset_8bit<Char>::operator |=(basic_chset_8bit<Char> const &that)
335{
336    this->bset_ |= that.bset_;
337    return *this;
338}
339
340/////////////////////////////////
341template<typename Char>
342inline basic_chset_8bit<Char> &
343basic_chset_8bit<Char>::operator &=(basic_chset_8bit<Char> const &that)
344{
345    this->bset_ &= that.bset_;
346    return *this;
347}
348
349/////////////////////////////////
350template<typename Char>
351inline basic_chset_8bit<Char> &
352basic_chset_8bit<Char>::operator -=(basic_chset_8bit<Char> const &that)
353{
354    this->bset_ &= ~that.bset_;
355    return *this;
356}
357
358/////////////////////////////////
359template<typename Char>
360inline basic_chset_8bit<Char> &
361basic_chset_8bit<Char>::operator ^=(basic_chset_8bit<Char> const &that)
362{
363    this->bset_ ^= that.bset_;
364    return *this;
365}
366
367template<typename Char>
368inline std::bitset<256> const &
369basic_chset_8bit<Char>::base() const
370{
371    return this->bset_;
372}
373
374#endif // if(CHAR_BIT == 8)
375
376
377///////////////////////////////////////////////////////////////////////////////
378// helpers
379template<typename Char, typename Traits>
380inline void set_char(basic_chset<Char> &chset, Char ch, Traits const &tr, bool icase)
381{
382    icase ? chset.set(ch, tr) : chset.set(ch);
383}
384
385template<typename Char, typename Traits>
386inline void set_range(basic_chset<Char> &chset, Char from, Char to, Traits const &tr, bool icase)
387{
388    icase ? chset.set(from, to, tr) : chset.set(from, to);
389}
390
391template<typename Char, typename Traits>
392inline void set_class(basic_chset<Char> &chset, typename Traits::char_class_type char_class, bool no, Traits const &tr)
393{
394    BOOST_MPL_ASSERT_RELATION(1, ==, sizeof(Char));
395    for(std::size_t i = 0; i <= UCHAR_MAX; ++i)
396    {
397        typedef typename std::char_traits<Char>::int_type int_type;
398        Char ch = std::char_traits<Char>::to_char_type(static_cast<int_type>(i));
399        if(no != tr.isctype(ch, char_class))
400        {
401            chset.set(ch);
402        }
403    }
404}
405
406}}} // namespace boost::xpressive::detail
407
408#endif
409
410