]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/serialization/include/boost/archive/iterators/wchar_from_mb.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / serialization / include / boost / archive / iterators / wchar_from_mb.hpp
CommitLineData
7c673cae
FG
1#ifndef BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
2#define BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
3
4// MS compatible compilers support #pragma once
5#if defined(_MSC_VER)
6# pragma once
7#endif
8
9/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
10// wchar_from_mb.hpp
11
12// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
13// Use, modification and distribution is subject to the Boost Software
14// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
15// http://www.boost.org/LICENSE_1_0.txt)
16
17// See http://www.boost.org for updates, documentation, and revision history.
18
19#include <boost/assert.hpp>
20#include <cctype>
21#include <cstddef> // size_t
22#include <cwchar> // mbstate_t
23#include <algorithm> // copy
24
25#include <boost/config.hpp>
26#if defined(BOOST_NO_STDC_NAMESPACE)
27namespace std{
28 using ::mbstate_t;
29} // namespace std
30#endif
31#include <boost/array.hpp>
32#include <boost/iterator/iterator_adaptor.hpp>
33#include <boost/archive/detail/utf8_codecvt_facet.hpp>
34#include <boost/archive/iterators/dataflow_exception.hpp>
35#include <boost/serialization/throw_exception.hpp>
36
37#include <iostream>
38
39namespace boost {
40namespace archive {
41namespace iterators {
42
43/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
44// class used by text archives to translate char strings to wchar_t
45// strings of the currently selected locale
46template<class Base>
47class wchar_from_mb
48 : public boost::iterator_adaptor<
49 wchar_from_mb<Base>,
50 Base,
51 wchar_t,
52 single_pass_traversal_tag,
53 wchar_t
54 >
55{
56 friend class boost::iterator_core_access;
57 typedef typename boost::iterator_adaptor<
58 wchar_from_mb<Base>,
59 Base,
60 wchar_t,
61 single_pass_traversal_tag,
62 wchar_t
63 > super_t;
64
65 typedef wchar_from_mb<Base> this_t;
66
67 void drain();
68
69 wchar_t dereference() const {
70 if(m_output.m_next == m_output.m_next_available)
71 return static_cast<wchar_t>(0);
72 return * m_output.m_next;
73 }
74
75 void increment(){
76 if(m_output.m_next == m_output.m_next_available)
77 return;
78 if(++m_output.m_next == m_output.m_next_available){
79 if(m_input.m_done)
80 return;
81 drain();
82 }
83 }
84
85 bool equal(this_t const & rhs) const {
86 return dereference() == rhs.dereference();
87 }
88
89 boost::archive::detail::utf8_codecvt_facet m_codecvt_facet;
90 std::mbstate_t m_mbs;
91
92 template<typename T>
93 struct sliding_buffer {
94 boost::array<T, 32> m_buffer;
95 typename boost::array<T, 32>::const_iterator m_next_available;
96 typename boost::array<T, 32>::iterator m_next;
97 bool m_done;
98 // default ctor
99 sliding_buffer() :
100 m_next_available(m_buffer.begin()),
101 m_next(m_buffer.begin()),
102 m_done(false)
103 {}
104 // copy ctor
105 sliding_buffer(const sliding_buffer & rhs) :
106 m_next_available(
107 std::copy(
108 rhs.m_buffer.begin(),
109 rhs.m_next_available,
110 m_buffer.begin()
111 )
112 ),
113 m_next(
114 m_buffer.begin() + (rhs.m_next - rhs.m_buffer.begin())
115 ),
116 m_done(rhs.m_done)
117 {}
118 };
119
120 sliding_buffer<typename iterator_value<Base>::type> m_input;
121 sliding_buffer<typename iterator_value<this_t>::type> m_output;
122
123public:
124 // make composible buy using templated constructor
125 template<class T>
126 wchar_from_mb(T start) :
127 super_t(Base(static_cast< T >(start))),
128 m_mbs(std::mbstate_t())
129 {
130 BOOST_ASSERT(std::mbsinit(&m_mbs));
131 drain();
132 }
133 // default constructor used as an end iterator
134 wchar_from_mb(){}
135
136 // copy ctor
137 wchar_from_mb(const wchar_from_mb & rhs) :
138 super_t(rhs.base_reference()),
139 m_mbs(rhs.m_mbs),
140 m_input(rhs.m_input),
141 m_output(rhs.m_output)
142 {}
143};
144
145template<class Base>
146void wchar_from_mb<Base>::drain(){
147 BOOST_ASSERT(! m_input.m_done);
148 for(;;){
149 typename boost::iterators::iterator_reference<Base>::type c = *(this->base_reference());
150 // a null character in a multibyte stream is takes as end of string
151 if(0 == c){
152 m_input.m_done = true;
153 break;
154 }
155 ++(this->base_reference());
156 * const_cast<typename iterator_value<Base>::type *>(
157 (m_input.m_next_available++)
158 ) = c;
159 // if input buffer is full - we're done for now
160 if(m_input.m_buffer.end() == m_input.m_next_available)
161 break;
162 }
163 const typename boost::iterators::iterator_value<Base>::type * input_new_start;
164 typename iterator_value<this_t>::type * next_available;
165
166 std::codecvt_base::result r = m_codecvt_facet.in(
167 m_mbs,
168 m_input.m_buffer.begin(),
169 m_input.m_next_available,
170 input_new_start,
171 m_output.m_buffer.begin(),
172 m_output.m_buffer.end(),
173 next_available
174 );
175 BOOST_ASSERT(std::codecvt_base::ok == r);
176 m_output.m_next_available = next_available;
177 m_output.m_next = m_output.m_buffer.begin();
178
179 // we're done with some of the input so shift left.
180 m_input.m_next_available = std::copy(
181 input_new_start,
182 m_input.m_next_available,
183 m_input.m_buffer.begin()
184 );
185 m_input.m_next = m_input.m_buffer.begin();
186}
187
188} // namespace iterators
189} // namespace archive
190} // namespace boost
191
192#endif // BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP