summaryrefslogtreecommitdiff
path: root/cpp/include/IceXML/Output.h
blob: a0d37e4ce12b8c07040d4a6a9d8af2763ff6c666 (plain)
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
// **********************************************************************
//
// Copyright (c) 2001
// MutableRealms, Inc.
// Huntsville, AL, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef ICE_XML_OUTPUT_H
#define ICE_XML_OUTPUT_H

#include <IceUtil/Config.h>
#include <fstream>
#include <stack>

#ifdef WIN32
#   ifdef ICE_XML_API_EXPORTS
#       define ICE_XML_API __declspec(dllexport)
#   else
#       define ICE_XML_API __declspec(dllimport)
#   endif
#else
#   define ICE_XML_API /**/
#endif

namespace IceXML
{

class ICE_XML_API StartElement
{
public:

    StartElement(const std::string& name)
	: _name(name)
    {
    }
    
    ~StartElement()
    {
    }

    const std::string& getName() const { return _name; }

private:

    const std::string _name;
};

class ICE_XML_API NextLine { };
class ICE_XML_API EndElement { };
class ICE_XML_API Separator { };

extern ICE_XML_API NextLine nl;
typedef StartElement se;
extern ICE_XML_API EndElement ee;
extern ICE_XML_API Separator sp;

// ----------------------------------------------------------------------
// Indent
// ----------------------------------------------------------------------

class ICE_XML_API Output : public ::IceUtil::noncopyable
{
public:

    Output();
    Output(std::ostream&);
    Output(const char*);

    void setIndent(int);              // what is the indent level?
    void setUseTab(bool);             // should we output tabs?

    void open(const char*); // Open output stream

    void print(const char*); // Print a string

    void inc(); // Increment indentation level
    void dec(); // Decrement indentation level

    void useCurrentPosAsIndent(); // Save the current position as indentation
    void zeroIndent(); // Use zero identation
    void restoreIndent(); // Restore indentation

    void nl(); // Print newline
    void se(const std::string&); // Start an element
    void ee(); // End an element
    void sp(); // Print separator

    bool operator!() const; // Check whether the output state is ok

private:

    std::ofstream _fout;
    std::ostream& _out;
    int _pos;
    int _indent;
    std::stack<int> _indentSave;
    std::stack<std::string> _elementStack;
    bool _separator;
    bool _printed;

    bool _useTab;
    int  _indentSize;
};

template<typename T>
Output&
operator<<(Output& out, const T& val)
{
    std::ostringstream s;
    s << val;
    out.print(s.str().c_str());
    return out;
}

template<>
inline Output&
operator<<(Output& o, const NextLine&)
{
    o.nl();
    return o;
}

template<>
inline Output&
operator<<(Output& o, const StartElement& e)
{
    o.se(e.getName());
    return o;
}

template<>
inline Output&
operator<<(Output& o, const EndElement&)
{
    o.ee();
    return o;
}

template<>
inline Output&
operator<<(Output& o, const Separator&)
{
    o.sp();
    return o;
}

ICE_XML_API Output& operator<<(Output&, std::ios_base& (*)(std::ios_base&));

}

#endif