00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef IWAFIELD_H_INCLUDED
00011 #define IWAFIELD_H_INCLUDED
00012
00013 #include <deque>
00014 #include <stdexcept>
00015
00016 #include <boost/container/deque.hpp>
00017 #include <boost/optional.hpp>
00018 #include <boost/shared_ptr.hpp>
00019
00020 #include "IWAReader.h"
00021 #include "libetonyek_utils.h"
00022
00023 namespace libetonyek
00024 {
00025
00026 class IWAField
00027 {
00028 public:
00029 enum Tag
00030 {
00031 TAG_INT32,
00032 TAG_INT64,
00033 TAG_UINT32,
00034 TAG_UINT64,
00035 TAG_SINT32,
00036 TAG_SINT64,
00037 TAG_BOOL,
00038 TAG_ENUM,
00039 TAG_FIXED64,
00040 TAG_SFIXED64,
00041 TAG_DOUBLE,
00042 TAG_STRING,
00043 TAG_BYTES,
00044 TAG_MESSAGE,
00045 TAG_FIXED32,
00046 TAG_SFIXED32,
00047 TAG_FLOAT
00048 };
00049
00050 public:
00051 virtual ~IWAField() = 0;
00052
00053 virtual Tag tag() const = 0;
00054
00055
00056 virtual bool empty() const = 0;
00057 virtual std::size_t size() const = 0;
00058
00059
00060 virtual bool is() const = 0;
00061 operator bool() const;
00062 bool operator!() const;
00063
00064 virtual void parse(const RVNGInputStreamPtr_t &input, unsigned long length, bool allowEmpty) = 0;
00065 };
00066
00067 typedef boost::shared_ptr<IWAField> IWAFieldPtr_t;
00068
00069 namespace detail
00070 {
00071
00072 template<IWAField::Tag TagV, typename ValueT, typename Reader>
00073 class IWAFieldImpl : public IWAField
00074 {
00075 typedef boost::container::deque<ValueT> container_type;
00076
00077 public:
00078 typedef ValueT value_type;
00079 typedef ValueT &reference_type;
00080 typedef const ValueT &const_reference_type;
00081 typedef typename container_type::const_iterator const_iterator;
00082 typedef typename container_type::const_reverse_iterator const_reverse_iterator;
00083
00084 public:
00085
00086
00087 virtual IWAField::Tag tag() const
00088 {
00089 return TagV;
00090 }
00091
00092
00093
00094 virtual bool is() const
00095 {
00096 return !m_values.empty();
00097 }
00098
00099 const_reference_type get() const
00100 {
00101 if (m_values.empty())
00102 throw std::logic_error("the field is unset");
00103 return m_values[0];
00104 }
00105
00106
00107
00108 virtual bool empty() const
00109 {
00110 return m_values.empty();
00111 }
00112
00113 virtual std::size_t size() const
00114 {
00115 return m_values.size();
00116 }
00117
00118 const_reference_type operator[](const std::size_t index) const
00119 {
00120 if (index >= m_values.size())
00121 throw std::out_of_range("index is out of range");
00122 return m_values[index];
00123 }
00124
00125 const_iterator begin() const
00126 {
00127 return m_values.begin();
00128 }
00129
00130 const_iterator end() const
00131 {
00132 return m_values.end();
00133 }
00134
00135 const_reverse_iterator rbegin() const
00136 {
00137 return m_values.rbegin();
00138 }
00139
00140 const_reverse_iterator rend() const
00141 {
00142 return m_values.rend();
00143 }
00144
00145
00146
00147
00148 const std::deque<value_type> repeated() const
00149 {
00150 const std::deque<value_type> values(m_values.begin(), m_values.end());
00151 return values;
00152 }
00153
00154 const boost::optional<value_type> optional() const
00155 {
00156 return m_values.empty() ? boost::none : boost::make_optional(m_values.front());
00157 }
00158
00159
00160
00161 virtual void parse(const RVNGInputStreamPtr_t &input, const unsigned long length, const bool allowEmpty)
00162 {
00163 if (length != 0)
00164 {
00165 const long start = input->tell();
00166 while (!input->isEnd() && (length > static_cast<unsigned long>(input->tell() - start)))
00167 {
00168 const value_type value(Reader::read(input, length));
00169 m_values.push_back(value);
00170 }
00171 }
00172 else if (allowEmpty)
00173 {
00174 m_values.push_back(value_type());
00175 }
00176 }
00177
00178 private:
00179 container_type m_values;
00180 };
00181
00182 }
00183
00184 template<IWAField::Tag TagV, typename ValueT, typename Reader>
00185 const ValueT &get(const detail::IWAFieldImpl<TagV, ValueT, Reader> &field)
00186 {
00187 return field.get();
00188 }
00189
00190 template<IWAField::Tag TagV, typename ValueT, typename Reader>
00191 const ValueT &get_optional_value_or(const detail::IWAFieldImpl<TagV, ValueT, Reader> &field, const ValueT &value)
00192 {
00193 return bool(field) ? field.get() : value;
00194 }
00195
00196 template<IWAField::Tag TagV, typename ValueT, typename Reader, typename DefaultValueT>
00197 const ValueT get_optional_value_or(const detail::IWAFieldImpl<TagV, ValueT, Reader> &field, const DefaultValueT &value)
00198 {
00199 return bool(field) ? field.get() : ValueT(value);
00200 }
00201
00202 typedef detail::IWAFieldImpl<IWAField::TAG_UINT32, uint32_t, IWAReader::UInt32> IWAUInt32Field;
00203 typedef detail::IWAFieldImpl<IWAField::TAG_UINT64, uint64_t, IWAReader::UInt64> IWAUInt64Field;
00204 typedef detail::IWAFieldImpl<IWAField::TAG_SINT32, int32_t, IWAReader::SInt32> IWASInt32Field;
00205 typedef detail::IWAFieldImpl<IWAField::TAG_SINT64, int64_t, IWAReader::SInt64> IWASInt64Field;
00206 typedef detail::IWAFieldImpl<IWAField::TAG_BOOL, bool, IWAReader::Bool> IWABoolField;
00207
00208 typedef detail::IWAFieldImpl<IWAField::TAG_FIXED64, uint64_t, IWAReader::Fixed64> IWAFixed64Field;
00209 typedef detail::IWAFieldImpl<IWAField::TAG_DOUBLE, double, IWAReader::Double> IWADoubleField;
00210
00211 typedef detail::IWAFieldImpl<IWAField::TAG_STRING, std::string, IWAReader::String> IWAStringField;
00212 typedef detail::IWAFieldImpl<IWAField::TAG_BYTES, RVNGInputStreamPtr_t, IWAReader::Bytes> IWABytesField;
00213
00214 typedef detail::IWAFieldImpl<IWAField::TAG_FIXED32, uint32_t, IWAReader::Fixed32> IWAFixed32Field;
00215 typedef detail::IWAFieldImpl<IWAField::TAG_FLOAT, float, IWAReader::Float> IWAFloatField;
00216
00217 class IWAMessageField : public detail::IWAFieldImpl<IWAField::TAG_MESSAGE, IWAMessage, IWAReader::Message>
00218 {
00219 public:
00220 const IWAUInt32Field &uint32(std::size_t field) const;
00221 const IWAUInt64Field &uint64(std::size_t field) const;
00222 const IWASInt32Field &sint32(std::size_t field) const;
00223 const IWASInt64Field &sint64(std::size_t field) const;
00224 const IWABoolField &bool_(std::size_t field) const;
00225
00226 const IWAFixed64Field &fixed64(std::size_t field) const;
00227 const IWADoubleField &double_(std::size_t field) const;
00228
00229 const IWAStringField &string(std::size_t field) const;
00230 const IWABytesField &bytes(std::size_t field) const;
00231 const IWAMessageField &message(std::size_t field) const;
00232
00233 const IWAFixed32Field &fixed32(std::size_t field) const;
00234 const IWAFloatField &float_(std::size_t field) const;
00235 };
00236
00237 }
00238
00239 #endif
00240
00241