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-2007 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_list.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 41const typeinfo_t html_ostream_typeinfo = { "html_ostream" }; 42 43static 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 52static void 53emit_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 90static void 91html_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 unsigned int 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, """); 152 break; 153 case '&': 154 ostream_write_str (stream->destination, "&"); 155 break; 156 case '<': 157 ostream_write_str (stream->destination, "<"); 158 break; 159 case '>': 160 /* Needed to avoid "]]>" in the output. */ 161 ostream_write_str (stream->destination, ">"); 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, " "); 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;", 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 210static void 211html_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 218static void 219html_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 229void 230html_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 250void 251html_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 264html_ostream_t 265html_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 282const 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 298void 299html_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 306void 307html_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 314void 315html_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 322void 323html_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 330void 331html_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 339