]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | #ifndef DATETIME_PERIOD_FORMATTER_HPP___ | |
3 | #define DATETIME_PERIOD_FORMATTER_HPP___ | |
4 | ||
5 | /* Copyright (c) 2002-2004 CrystalClear Software, Inc. | |
6 | * Use, modification and distribution is subject to the | |
7 | * Boost Software License, Version 1.0. (See accompanying | |
8 | * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) | |
9 | * Author: Jeff Garland, Bart Garst | |
10 | * $Date$ | |
11 | */ | |
12 | ||
13 | ||
14 | ||
15 | namespace boost { namespace date_time { | |
16 | ||
17 | ||
18 | //! Not a facet, but a class used to specify and control period formats | |
19 | /*! Provides settings for the following: | |
20 | * - period_separator -- default '/' | |
21 | * - period_open_start_delimeter -- default '[' | |
22 | * - period_open_range_end_delimeter -- default ')' | |
23 | * - period_closed_range_end_delimeter -- default ']' | |
24 | * - display_as_open_range, display_as_closed_range -- default closed_range | |
25 | * | |
26 | * Thus the default formatting for a period is as follows: | |
27 | *@code | |
28 | * [period.start()/period.last()] | |
29 | *@endcode | |
30 | * So for a typical date_period this would be | |
31 | *@code | |
32 | * [2004-Jan-04/2004-Feb-01] | |
33 | *@endcode | |
34 | * where the date formatting is controlled by the date facet | |
35 | */ | |
36 | template <class CharT, class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > > | |
37 | class period_formatter { | |
38 | public: | |
39 | typedef std::basic_string<CharT> string_type; | |
40 | typedef CharT char_type; | |
41 | typedef typename std::basic_string<char_type>::const_iterator const_itr_type; | |
42 | typedef std::vector<std::basic_string<CharT> > collection_type; | |
43 | ||
44 | static const char_type default_period_separator[2]; | |
45 | static const char_type default_period_start_delimeter[2]; | |
46 | static const char_type default_period_open_range_end_delimeter[2]; | |
47 | static const char_type default_period_closed_range_end_delimeter[2]; | |
48 | ||
49 | enum range_display_options { AS_OPEN_RANGE, AS_CLOSED_RANGE }; | |
50 | ||
51 | //! Constructor that sets up period formatter options -- default should suffice most cases. | |
52 | period_formatter(range_display_options range_option_in = AS_CLOSED_RANGE, | |
53 | const char_type* const period_separator = default_period_separator, | |
54 | const char_type* const period_start_delimeter = default_period_start_delimeter, | |
55 | const char_type* const period_open_range_end_delimeter = default_period_open_range_end_delimeter, | |
56 | const char_type* const period_closed_range_end_delimeter = default_period_closed_range_end_delimeter) : | |
57 | m_range_option(range_option_in), | |
58 | m_period_separator(period_separator), | |
59 | m_period_start_delimeter(period_start_delimeter), | |
60 | m_open_range_end_delimeter(period_open_range_end_delimeter), | |
61 | m_closed_range_end_delimeter(period_closed_range_end_delimeter) | |
62 | {} | |
63 | ||
64 | //! Puts the characters between period elements into stream -- default is / | |
65 | OutItrT put_period_separator(OutItrT& oitr) const | |
66 | { | |
67 | const_itr_type ci = m_period_separator.begin(); | |
68 | while (ci != m_period_separator.end()) { | |
69 | *oitr = *ci; | |
70 | ci++; | |
71 | } | |
72 | return oitr; | |
73 | } | |
74 | ||
75 | //! Puts the period start characters into stream -- default is [ | |
76 | OutItrT put_period_start_delimeter(OutItrT& oitr) const | |
77 | { | |
78 | const_itr_type ci = m_period_start_delimeter.begin(); | |
79 | while (ci != m_period_start_delimeter.end()) { | |
80 | *oitr = *ci; | |
81 | ci++; | |
82 | } | |
83 | return oitr; | |
84 | } | |
85 | ||
86 | //! Puts the period end characters into stream as controled by open/closed range setting. | |
87 | OutItrT put_period_end_delimeter(OutItrT& oitr) const | |
88 | { | |
89 | ||
90 | const_itr_type ci, end; | |
91 | if (m_range_option == AS_OPEN_RANGE) { | |
92 | ci = m_open_range_end_delimeter.begin(); | |
93 | end = m_open_range_end_delimeter.end(); | |
94 | } | |
95 | else { | |
96 | ci = m_closed_range_end_delimeter.begin(); | |
97 | end = m_closed_range_end_delimeter.end(); | |
98 | } | |
99 | while (ci != end) { | |
100 | *oitr = *ci; | |
101 | ci++; | |
102 | } | |
103 | return oitr; | |
104 | } | |
105 | ||
106 | range_display_options range_option() const | |
107 | { | |
108 | return m_range_option; | |
109 | } | |
110 | ||
111 | //! Reset the range_option control | |
112 | void | |
113 | range_option(range_display_options option) const | |
114 | { | |
115 | m_range_option = option; | |
116 | } | |
11fdf7f2 TL |
117 | |
118 | //! Change the delimiter strings | |
119 | void delimiter_strings(const string_type& separator, | |
120 | const string_type& start_delim, | |
121 | const string_type& open_end_delim, | |
122 | const string_type& closed_end_delim) | |
7c673cae | 123 | { |
11fdf7f2 TL |
124 | m_period_separator = separator; |
125 | m_period_start_delimeter = start_delim; | |
126 | m_open_range_end_delimeter = open_end_delim; | |
127 | m_closed_range_end_delimeter = closed_end_delim; | |
7c673cae FG |
128 | } |
129 | ||
7c673cae FG |
130 | //! Generic code to output a period -- no matter the period type. |
131 | /*! This generic code will output any period using a facet to | |
132 | * to output the 'elements'. For example, in the case of a date_period | |
133 | * the elements will be instances of a date which will be formatted | |
134 | * according the to setup in the passed facet parameter. | |
135 | * | |
136 | * The steps for formatting a period are always the same: | |
137 | * - put the start delimiter | |
138 | * - put start element | |
139 | * - put the separator | |
140 | * - put either last or end element depending on range settings | |
141 | * - put end delimeter depending on range settings | |
142 | * | |
143 | * Thus for a typical date period the result might look like this: | |
144 | *@code | |
145 | * | |
146 | * [March 01, 2004/June 07, 2004] <-- closed range | |
147 | * [March 01, 2004/June 08, 2004) <-- open range | |
148 | * | |
149 | *@endcode | |
150 | */ | |
151 | template<class period_type, class facet_type> | |
152 | OutItrT put_period(OutItrT next, | |
153 | std::ios_base& a_ios, | |
154 | char_type a_fill, | |
155 | const period_type& p, | |
156 | const facet_type& facet) const { | |
157 | put_period_start_delimeter(next); | |
158 | next = facet.put(next, a_ios, a_fill, p.begin()); | |
159 | put_period_separator(next); | |
160 | if (m_range_option == AS_CLOSED_RANGE) { | |
161 | facet.put(next, a_ios, a_fill, p.last()); | |
162 | } | |
163 | else { | |
164 | facet.put(next, a_ios, a_fill, p.end()); | |
165 | } | |
166 | put_period_end_delimeter(next); | |
167 | return next; | |
168 | } | |
169 | ||
170 | ||
171 | private: | |
172 | range_display_options m_range_option; | |
173 | string_type m_period_separator; | |
174 | string_type m_period_start_delimeter; | |
175 | string_type m_open_range_end_delimeter; | |
176 | string_type m_closed_range_end_delimeter; | |
177 | }; | |
178 | ||
179 | template <class CharT, class OutItrT> | |
180 | const typename period_formatter<CharT, OutItrT>::char_type | |
181 | period_formatter<CharT, OutItrT>::default_period_separator[2] = {'/'}; | |
182 | ||
183 | template <class CharT, class OutItrT> | |
184 | const typename period_formatter<CharT, OutItrT>::char_type | |
185 | period_formatter<CharT, OutItrT>::default_period_start_delimeter[2] = {'['}; | |
186 | ||
187 | template <class CharT, class OutItrT> | |
188 | const typename period_formatter<CharT, OutItrT>::char_type | |
189 | period_formatter<CharT, OutItrT>::default_period_open_range_end_delimeter[2] = {')'}; | |
190 | ||
191 | template <class CharT, class OutItrT> | |
192 | const typename period_formatter<CharT, OutItrT>::char_type | |
193 | period_formatter<CharT, OutItrT>::default_period_closed_range_end_delimeter[2] = {']'}; | |
194 | ||
195 | } } //namespace boost::date_time | |
196 | ||
197 | #endif |