File: XMLWriter.hpp

package info (click to toggle)
libpwiz 3.0.18342-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 14,888 kB
  • sloc: cpp: 157,552; sh: 4,182; makefile: 317
file content (208 lines) | stat: -rw-r--r-- 6,559 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//
// $Id$
//
//
// Original author: Darren Kessner <darren@proteowizard.org>
//
// Copyright 2007 Spielberg Family Center for Applied Proteomics
//   Cedars-Sinai Medical Center, Los Angeles, California  90048
//
// Licensed under the Apache License, Version 2.0 (the "License"); 
// you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at 
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an "AS IS" BASIS, 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
// See the License for the specific language governing permissions and 
// limitations under the License.
//


#ifndef _XMLWRITER_HPP_
#define _XMLWRITER_HPP_


#include "pwiz/utility/misc/Export.hpp"
#include "pwiz/utility/misc/optimized_lexical_cast.hpp"
#include "boost/shared_ptr.hpp"
#include "boost/iostreams/positioning.hpp"
#include "boost/iostreams/filter/counter.hpp"
#include <iosfwd>
#include <string>
#include <vector>


namespace pwiz {
namespace minimxml {


///
/// The XMLWriter class provides simple, tag-level XML syntax writing.
/// Internally, XMLWriter keeps a style stack (for client customization
/// of the XML style) and an element stack (for element nesting/indentation). 
///
class PWIZ_API_DECL XMLWriter
{
    public:

    /// flags to control the XML writing style
    enum PWIZ_API_DECL StyleFlag
    {
        StyleFlag_InlineInner = 0x01, // no whitespace within an element 
        StyleFlag_InlineOuter = 0x02, // no whitespace around an element
        StyleFlag_Inline = StyleFlag_InlineInner | StyleFlag_InlineOuter,
        StyleFlag_AttributesOnMultipleLines = 0x04
    };

    /// interface to allow outside observation of data sent to output stream 
    class PWIZ_API_DECL OutputObserver
    {
        public:
        virtual void update(const std::string& output) = 0;
        virtual ~OutputObserver(){}
    };

    /// initial configuration of the XMLWriter
    struct PWIZ_API_DECL Config
    {
        unsigned int initialStyle;
        unsigned int indentationStep;
        OutputObserver* outputObserver;

        Config()
        :   initialStyle(0), indentationStep(2), outputObserver(0)
        {}
    };

    /// vector of name/value pairs to be written as XML attributes
    class PWIZ_API_DECL Attributes : public std::vector< std::pair<std::string,std::string> >
    {
        public:
        void add(const std::string& name, const double& value);
        void add(const std::string& name, const int& value);

        template <typename T>
        inline void add(const std::string& name, const T& value)
        {
            push_back(make_pair(name, boost::lexical_cast<std::string>(value)));
        }
    };

    /// constructor
    XMLWriter(std::ostream& os, const Config& config = Config());
    virtual ~XMLWriter() {}

    /// pushes style flags onto the internal style stack
    void pushStyle(unsigned int flags);

    /// pops the style stack
    void popStyle();

    /// writes a processing instruction
    void processingInstruction(const std::string& name, const std::string& data);

    /// tag for indicating an empty element
    enum EmptyElementTag {NotEmptyElement, EmptyElement};

    /// writes element start tag
    void startElement(const std::string& name, 
                      const Attributes& attributes = Attributes(),
                      EmptyElementTag emptyElementTag = NotEmptyElement);

    /// writes element end tag
    void endElement();

    /// writes character data;
    /// autoEscape writes reserved XML characters in the input text in their escaped form
    /// '&', '<', and '>' are '&amp;', '&lt;', '&gt;' respectively
    void characters(const std::string& text, bool autoEscape = true);

    typedef boost::iostreams::stream_offset stream_offset;

    /// returns current stream position
    stream_offset position() const;

    /// returns stream position of next element start tag 
    stream_offset positionNext() const;


    private:
    class Impl;
    boost::shared_ptr<Impl> impl_;
    XMLWriter(const XMLWriter&);
    XMLWriter& operator=(const XMLWriter&);
};


/// Encodes any characters not suitable in an xml:ID or xml:IDREF
/// with their hexadecimal value, e.g. " " encodes as "_x0020_"
/// This override modifies the input string in place and returns its reference.
PWIZ_API_DECL std::string& encode_xml_id(std::string& str);


/// Encodes any characters not suitable in an xml:ID or xml:IDREF
/// with their hexadecimal value, e.g. " " encodes as "_x0020_"
/// This override modifies and returns a copy of the input string.
PWIZ_API_DECL std::string encode_xml_id_copy(const std::string& str);


//
// Template name: basic_charcounter.
// Template paramters:
//      Ch - The character type.
// Description: Filter which counts characters.  
// Based on boost's basic_counter, but
// without the line counting, and couting using 
// stream_offset instead of int
//
template<typename Ch>
class basic_charcounter  {
public:
    typedef Ch char_type;
    struct category
		: boost::iostreams::dual_use,
          boost::iostreams::filter_tag,
          boost::iostreams::multichar_tag,
          boost::iostreams::optimally_buffered_tag
        { };
    explicit basic_charcounter(int first_char = 0)
        : chars_(first_char)
        { }
    boost::iostreams::stream_offset characters() const { return chars_; }
    std::streamsize optimal_buffer_size() const { return 0; }

    template<typename Source>
    std::streamsize read(Source& src, char_type* s, std::streamsize n)
    {
		std::streamsize result = boost::iostreams::read(src, s, n);
        if (result == -1)
            return -1;
        chars_ += result;
        return result;
    }

    template<typename Sink>
    std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
    {
		std::streamsize result = boost::iostreams::write(snk, s, n);
        chars_ += result;
        return result;
    }
private:
    boost::iostreams::stream_offset chars_;
};
BOOST_IOSTREAMS_PIPABLE(basic_charcounter, 1)


typedef basic_charcounter<char>     charcounter;
typedef basic_charcounter<wchar_t>  wcharcounter;

} // namespace minimxml
} // namespace pwiz


#endif // _XMLWRITER_HPP_