Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / gettext-tools / gnulib-lib / html-ostream.c
1 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
2
3 #line 1 "html-ostream.oo.c"
4 /* Output stream that produces HTML output.
5    Copyright (C) 2006-2009, 2015 Free Software Foundation, Inc.
6    Written by Bruno Haible <bruno@clisp.org>, 2006.
7
8    This program is free software: you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include <config.h>
22
23 /* Specification.  */
24 #include "html-ostream.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "gl_xlist.h"
31 #include "gl_array_list.h"
32 #include "unistr.h"
33 #include "xalloc.h"
34
35 #line 36 "html-ostream.c"
36 #if !IS_CPLUSPLUS
37 #define html_ostream_representation any_ostream_representation
38 #endif
39 #include "html_ostream.priv.h"
40
41 const typeinfo_t html_ostream_typeinfo = { "html_ostream" };
42
43 static const typeinfo_t * const html_ostream_superclasses[] =
44   { html_ostream_SUPERCLASSES };
45
46 #define super ostream_vtable
47
48 #line 48 "html-ostream.oo.c"
49
50 /* Implementation of ostream_t methods.  */
51
52 static void
53 emit_pending_spans (html_ostream_t stream, bool shrink_stack)
54 {
55   if (stream->curr_class_stack_size > stream->last_class_stack_size)
56     {
57       size_t i;
58
59       for (i = stream->last_class_stack_size; i < stream->curr_class_stack_size; i++)
60         {
61           char *classname = (char *) gl_list_get_at (stream->class_stack, i);
62
63           ostream_write_str (stream->destination, "<span class=\"");
64           ostream_write_str (stream->destination, classname);
65           ostream_write_str (stream->destination, "\">");
66         }
67       stream->last_class_stack_size = stream->curr_class_stack_size;
68     }
69   else if (stream->curr_class_stack_size < stream->last_class_stack_size)
70     {
71       size_t i = stream->last_class_stack_size;
72
73       while (i > stream->curr_class_stack_size)
74         {
75           char *classname;
76
77           --i;
78           classname = (char *) gl_list_get_at (stream->class_stack, i);
79           ostream_write_str (stream->destination, "</span>");
80           if (shrink_stack)
81             {
82               gl_list_remove_at (stream->class_stack, i);
83               free (classname);
84             }
85         }
86       stream->last_class_stack_size = stream->curr_class_stack_size;
87     }
88 }
89
90 static void
91 html_ostream__write_mem (html_ostream_t stream, const void *data, size_t len)
92 {
93   if (len > 0)
94     {
95       #define BUFFERSIZE 2048
96       char inbuffer[BUFFERSIZE];
97       size_t inbufcount;
98
99       inbufcount = stream->buflen;
100       if (inbufcount > 0)
101         memcpy (inbuffer, stream->buf, inbufcount);
102       for (;;)
103         {
104           /* At this point, inbuffer[0..inbufcount-1] is filled.  */
105           {
106             /* Combine the previous rest with a chunk of new input.  */
107             size_t n =
108               (len <= BUFFERSIZE - inbufcount ? len : BUFFERSIZE - inbufcount);
109
110             if (n > 0)
111               {
112                 memcpy (inbuffer + inbufcount, data, n);
113                 data = (char *) data + n;
114                 inbufcount += n;
115                 len -= n;
116               }
117           }
118           {
119             /* Handle complete UTF-8 characters.  */
120             const char *inptr = inbuffer;
121             size_t insize = inbufcount;
122
123             while (insize > 0)
124               {
125                 unsigned char c0;
126                 ucs4_t uc;
127                 int nbytes;
128
129                 c0 = ((const unsigned char *) inptr)[0];
130                 if (insize < (c0 < 0xc0 ? 1 : c0 < 0xe0 ? 2 : c0 < 0xf0 ? 3 :
131                               c0 < 0xf8 ? 4 : c0 < 0xfc ? 5 : 6))
132                   break;
133
134                 nbytes = u8_mbtouc (&uc, (const unsigned char *) inptr, insize);
135
136                 if (uc == '\n')
137                   {
138                     size_t prev_class_stack_size = stream->curr_class_stack_size;
139                     stream->curr_class_stack_size = 0;
140                     emit_pending_spans (stream, false);
141                     ostream_write_str (stream->destination, "<br/>");
142                     stream->curr_class_stack_size = prev_class_stack_size;
143                   }
144                 else
145                   {
146                     emit_pending_spans (stream, true);
147
148                     switch (uc)
149                       {
150                       case '"':
151                         ostream_write_str (stream->destination, "&quot;");
152                         break;
153                       case '&':
154                         ostream_write_str (stream->destination, "&amp;");
155                         break;
156                       case '<':
157                         ostream_write_str (stream->destination, "&lt;");
158                         break;
159                       case '>':
160                         /* Needed to avoid "]]>" in the output.  */
161                         ostream_write_str (stream->destination, "&gt;");
162                         break;
163                       case ' ':
164                         /* Needed because HTML viewers merge adjacent spaces
165                            and drop spaces adjacent to <br> and similar.  */
166                         ostream_write_str (stream->destination, "&nbsp;");
167                         break;
168                       default:
169                         if (uc >= 0x20 && uc < 0x7F)
170                           {
171                             /* Output ASCII characters as such.  */
172                             char bytes[1];
173                             bytes[0] = uc;
174                             ostream_write_mem (stream->destination, bytes, 1);
175                           }
176                         else
177                           {
178                             /* Output non-ASCII characters in #&nnn;
179                                notation.  */
180                             char bytes[32];
181                             sprintf (bytes, "&#%d;", (int) uc);
182                             ostream_write_str (stream->destination, bytes);
183                           }
184                         break;
185                       }
186                   }
187
188                 inptr += nbytes;
189                 insize -= nbytes;
190               }
191             /* Put back the unconverted part.  */
192             if (insize > BUFSIZE)
193               abort ();
194             if (len == 0)
195               {
196                 if (insize > 0)
197                   memcpy (stream->buf, inptr, insize);
198                 stream->buflen = insize;
199                 break;
200               }
201             if (insize > 0)
202               memmove (inbuffer, inptr, insize);
203             inbufcount = insize;
204           }
205         }
206       #undef BUFFERSIZE
207     }
208 }
209
210 static void
211 html_ostream__flush (html_ostream_t stream)
212 {
213   /* There's nothing to do here, since stream->buf[] contains only a few
214      bytes that don't correspond to a character, and it's not worth closing
215      the open spans.  */
216 }
217
218 static void
219 html_ostream__free (html_ostream_t stream)
220 {
221   stream->curr_class_stack_size = 0;
222   emit_pending_spans (stream, true);
223   gl_list_free (stream->class_stack);
224   free (stream);
225 }
226
227 /* Implementation of html_ostream_t methods.  */
228
229 static void
230 html_ostream__begin_span (html_ostream_t stream, const char *classname)
231 {
232   if (stream->last_class_stack_size > stream->curr_class_stack_size
233       && strcmp ((char *) gl_list_get_at (stream->class_stack,
234                                           stream->curr_class_stack_size),
235                  classname) != 0)
236     emit_pending_spans (stream, true);
237   /* Now either
238        last_class_stack_size <= curr_class_stack_size
239        - in this case we have to append the given CLASSNAME -
240      or
241        last_class_stack_size > curr_class_stack_size
242        && class_stack[curr_class_stack_size] == CLASSNAME
243        - in this case we only need to increment curr_class_stack_size.  */
244   if (stream->last_class_stack_size <= stream->curr_class_stack_size)
245     gl_list_add_at (stream->class_stack, stream->curr_class_stack_size,
246                     xstrdup (classname));
247   stream->curr_class_stack_size++;
248 }
249
250 static void
251 html_ostream__end_span (html_ostream_t stream, const char *classname)
252 {
253   if (!(stream->curr_class_stack_size > 0
254         && strcmp ((char *) gl_list_get_at (stream->class_stack,
255                                             stream->curr_class_stack_size - 1),
256                    classname) == 0))
257     /* Improperly nested begin_span/end_span calls.  */
258     abort ();
259   stream->curr_class_stack_size--;
260 }
261
262 /* Constructor.  */
263
264 html_ostream_t
265 html_ostream_create (ostream_t destination)
266 {
267   html_ostream_t stream = XMALLOC (struct html_ostream_representation);
268
269   stream->base.vtable = &html_ostream_vtable;
270   stream->destination = destination;
271   stream->class_stack =
272     gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, NULL, true);
273   stream->curr_class_stack_size = 0;
274   stream->last_class_stack_size = 0;
275   stream->buflen = 0;
276
277   return stream;
278 }
279
280 #line 281 "html-ostream.c"
281
282 const struct html_ostream_implementation html_ostream_vtable =
283 {
284   html_ostream_superclasses,
285   sizeof (html_ostream_superclasses) / sizeof (html_ostream_superclasses[0]),
286   sizeof (struct html_ostream_representation),
287   html_ostream__write_mem,
288   html_ostream__flush,
289   html_ostream__free,
290   html_ostream__begin_span,
291   html_ostream__end_span,
292 };
293
294 #if !HAVE_INLINE
295
296 /* Define the functions that invoke the methods.  */
297
298 void
299 html_ostream_write_mem (html_ostream_t first_arg, const void *data, size_t len)
300 {
301   const struct html_ostream_implementation *vtable =
302     ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable;
303   vtable->write_mem (first_arg,data,len);
304 }
305
306 void
307 html_ostream_flush (html_ostream_t first_arg)
308 {
309   const struct html_ostream_implementation *vtable =
310     ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable;
311   vtable->flush (first_arg);
312 }
313
314 void
315 html_ostream_free (html_ostream_t first_arg)
316 {
317   const struct html_ostream_implementation *vtable =
318     ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable;
319   vtable->free (first_arg);
320 }
321
322 void
323 html_ostream_begin_span (html_ostream_t first_arg, const char *classname)
324 {
325   const struct html_ostream_implementation *vtable =
326     ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable;
327   vtable->begin_span (first_arg,classname);
328 }
329
330 void
331 html_ostream_end_span (html_ostream_t first_arg, const char *classname)
332 {
333   const struct html_ostream_implementation *vtable =
334     ((struct html_ostream_representation_header *) (struct html_ostream_representation *) first_arg)->vtable;
335   vtable->end_span (first_arg,classname);
336 }
337
338 #endif