1 : #ifndef TAGCOLL_TEXTFORMAT_H
2 : #define TAGCOLL_TEXTFORMAT_H
3 :
4 : /** \file
5 : * Serialize and deserialize a tagged collection to a text file
6 : */
7 :
8 : /*
9 : * Copyright (C) 2003--2006 Enrico Zini <enrico@debian.org>
10 : *
11 : * This library is free software; you can redistribute it and/or
12 : * modify it under the terms of the GNU Lesser General Public
13 : * License as published by the Free Software Foundation; either
14 : * version 2.1 of the License, or (at your option) any later version.
15 : *
16 : * This library is distributed in the hope that it will be useful,
17 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 : * Lesser General Public License for more details.
20 : *
21 : * You should have received a copy of the GNU Lesser General Public
22 : * License along with this library; if not, write to the Free Software
23 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 : */
25 :
26 : #include <wibble/mixin.h>
27 : #include <wibble/empty.h>
28 : #include <wibble/singleton.h>
29 : #include <tagcoll/input/base.h>
30 :
31 : #include <stdio.h>
32 :
33 : //#define TRACE_PARSE
34 :
35 : namespace tagcoll
36 : {
37 : template<class ITEM, class TAG>
38 : class PatchList;
39 : template<class ITEM, class TAG>
40 : class Patch;
41 :
42 : namespace textformat
43 : {
44 :
45 : /**
46 : * TagcollConsumer that serializes its input to an output stream
47 : *
48 : * The format of the output is:
49 : * lines of "comma+space"-separated items, followed by "colon+space",
50 : * followed by the corresponding "comma+space"-separated tags.
51 : * Examples:
52 : * ITEM:
53 : * ITEM: TAG
54 : * ITEM: TAG1, TAG2, TAG3
55 : * ITEM1, ITEM2, ITEM3:
56 : * ITEM1, ITEM2, ITEM3: TAG1, TAG2, TAG3
57 : */
58 : class StdioWriter : public wibble::mixin::OutputIterator<StdioWriter>
59 : {
60 : protected:
61 : FILE* out;
62 :
63 : public:
64 1 : StdioWriter(FILE* out) : out(out) {}
65 :
66 : template<typename Items, typename Tags>
67 : StdioWriter& operator=(const std::pair<Items, Tags>& data);
68 : };
69 :
70 : class OstreamWriter : public wibble::mixin::OutputIterator<OstreamWriter>
71 : {
72 : protected:
73 : std::ostream& out;
74 :
75 : public:
76 : OstreamWriter(std::ostream& out) : out(out) {}
77 :
78 : template<typename Items, typename Tags>
79 : OstreamWriter& operator=(const std::pair<Items, Tags>& data);
80 : };
81 :
82 : /**
83 : * Parse an element from input
84 : *
85 : * @retval item
86 : * The item found on input
87 : * @return
88 : * the trailing separating char, that can be:
89 : * \li input::Input::Eof
90 : * \li '\n'
91 : * \li ':'
92 : * \li ','
93 : */
94 : int parseElement(input::Input& in, std::string& item);
95 :
96 :
97 : /**
98 : * Serialize a patch
99 : */
100 : template<typename ITEM, typename TAG, typename ITEMSER, typename TAGSER>
101 : void outputPatch(
102 : ITEMSER& itemconv,
103 : TAGSER& tagconv,
104 : const PatchList<ITEM, TAG>& patch,
105 : FILE* out);
106 :
107 : void outputPatch(
108 : const PatchList<std::string, std::string>& patch,
109 : FILE* out);
110 :
111 :
112 : /*
113 : * Parse a tagged collection, sending the results to out.
114 : *
115 : * @param out
116 : * An output iterator accepting a std::pair<string, string>
117 : */
118 : template<typename OUT>
119 : void parse(input::Input& in, OUT out);
120 :
121 : /**
122 : * Assemble a patch from a stream of "item: +added, -removed" items and tags
123 : */
124 : template<typename OUT>
125 : class PatchAssembler : public wibble::mixin::OutputIterator< PatchAssembler<OUT> >
126 : {
127 : OUT out;
128 : public:
129 0 : PatchAssembler(const OUT& out) : out(out) {}
130 :
131 : template<typename ITEMS, typename TAGS>
132 : PatchAssembler& operator=(const std::pair<ITEMS, TAGS>& data);
133 : };
134 :
135 : template<typename OUT>
136 0 : PatchAssembler<OUT> patchAssembler(const OUT& out)
137 : {
138 0 : return PatchAssembler<OUT>(out);
139 : }
140 :
141 : template<typename OUT>
142 0 : void parsePatch(input::Input& in, OUT out)
143 : {
144 0 : parse(in, patchAssembler(out));
145 0 : }
146 :
147 : /**
148 : * Parse a tagcoll patch
149 : */
150 : template<typename ITEM, typename TAG, typename ITEMSER, typename TAGSER>
151 : PatchList<ITEM, TAG> parsePatch(
152 : ITEMSER& itemconv,
153 : TAGSER& tagconv,
154 : input::Input& in);
155 :
156 : PatchList<std::string, std::string> parsePatch(input::Input& in);
157 :
158 :
159 :
160 : template<typename ITEM, typename TAG, typename ITEMSER, typename TAGSER>
161 : class PatchBuilder : public wibble::mixin::OutputIterator< PatchBuilder<ITEM, TAG, ITEMSER, TAGSER> >
162 : {
163 : protected:
164 : PatchList<ITEM, TAG>& patch;
165 : const ITEMSER& itemconv;
166 : const TAGSER& tagconv;
167 :
168 : public:
169 : PatchBuilder(
170 : PatchList<ITEM, TAG>& patch,
171 : const ITEMSER& itemconv,
172 : const TAGSER& tagconv)
173 : : patch(patch), itemconv(itemconv), tagconv(tagconv) {}
174 :
175 : template<typename ITEMS, typename TAGS>
176 : PatchBuilder<ITEM, TAG, ITEMSER, TAGSER>& operator=(const std::pair<ITEMS, TAGS>& data);
177 :
178 : const PatchList<ITEM, TAG>& getPatch() const throw () { return patch; }
179 : };
180 :
181 : template<typename ITEM, typename TAG, typename ITEMSER, typename TAGSER>
182 : PatchBuilder<ITEM, TAG, ITEMSER, TAGSER> patchBuilder(
183 : PatchList<ITEM, TAG>& patch,
184 : const ITEMSER& itemconv,
185 : const TAGSER& tagconv)
186 : {
187 : return PatchBuilder<ITEM, TAG, ITEMSER, TAGSER>(patch, itemconv, tagconv);
188 : }
189 :
190 : }
191 : }
192 :
193 : // vim:set ts=4 sw=4:
194 : #endif
|