]> www.fi.muni.cz Git - evince.git/blob - backend/ps/gsio.c
Include config.h. Bug #504721.
[evince.git] / backend / ps / gsio.c
1 /*
2  * gsio.c: an IO abstraction
3  *
4  * Copyright 2002 - 2005 the Free Software Foundation
5  *
6  * Author: Jaka Mocnik  <jaka@gnu.org>
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 2 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, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include <config.h>
24 #include <string.h>
25
26 #include <gsio.h>
27
28 #define CHUNK_SIZE 32768
29
30 typedef struct _GtkGSDocChunk GtkGSDocChunk;
31 struct _GtkGSDocChunk {
32   gchar *buf, *ptr;
33   guint len, max_len;
34 };
35
36 struct _GtkGSDocSink {
37   GSList *chunks;
38   GtkGSDocChunk *tail;
39 };
40
41 static GtkGSDocChunk *
42 gtk_gs_doc_chunk_new(guint size)
43 {
44   GtkGSDocChunk *c;
45
46   c = g_new0(GtkGSDocChunk, 1);
47   if((c->buf = g_malloc(sizeof(gchar) * size)) == NULL) {
48     g_free(c);
49     return NULL;
50   }
51   c->ptr = c->buf;
52   *c->ptr = '\0';
53   c->max_len = size;
54   c->len = 0;
55   return c;
56 }
57
58 static void
59 gtk_gs_doc_chunk_free(GtkGSDocChunk * c)
60 {
61   if(c->buf)
62     g_free(c->buf);
63   g_free(c);
64 }
65
66 GtkGSDocSink *
67 gtk_gs_doc_sink_new()
68 {
69   GtkGSDocSink *sink;
70
71   sink = g_new0(GtkGSDocSink, 1);
72   return sink;
73 }
74
75 void
76 gtk_gs_doc_sink_free(GtkGSDocSink * sink)
77 {
78   GSList *node;
79
80   node = sink->chunks;
81   while(node) {
82     gtk_gs_doc_chunk_free((GtkGSDocChunk *) node->data);
83     node = node->next;
84   }
85   g_slist_free(sink->chunks);
86 }
87
88 void
89 gtk_gs_doc_sink_write(GtkGSDocSink * sink, const gchar * buf, int len)
90 {
91   gint real_len;
92
93   if(sink->tail == NULL) {
94     sink->tail = gtk_gs_doc_chunk_new(CHUNK_SIZE);
95     sink->chunks = g_slist_append(sink->chunks, sink->tail);
96   }
97
98   real_len = MIN(sink->tail->max_len - sink->tail->len, len);
99   if(real_len > 0) {
100     strncpy(sink->tail->ptr, buf, real_len);
101     sink->tail->ptr += real_len;
102     sink->tail->len += real_len;
103   }
104   len -= real_len;
105   if(len > 0) {
106     sink->tail = NULL;
107     gtk_gs_doc_sink_write(sink, buf + real_len, len);
108   }
109 }
110
111 void
112 gtk_gs_doc_sink_printf_v(GtkGSDocSink * sink, const gchar * fmt, va_list ap)
113 {
114   gint max_len, len;
115
116   if(sink->tail == NULL) {
117     sink->tail = gtk_gs_doc_chunk_new(CHUNK_SIZE);
118     sink->chunks = g_slist_append(sink->chunks, sink->tail);
119   }
120
121   max_len = sink->tail->max_len - sink->tail->len;
122   if(max_len > 0) {
123     len = g_vsnprintf(sink->tail->ptr, max_len, fmt, ap);
124     if(len >= max_len - 1) {
125       /* force printf in the next chunk later on */
126       max_len = 0;
127       sink->tail = NULL;
128     }
129     else {
130       sink->tail->ptr += len;
131       sink->tail->len += len;
132     }
133   }
134   if(max_len <= 0) {
135     gtk_gs_doc_sink_printf(sink, fmt, ap);
136   }
137 }
138
139 void
140 gtk_gs_doc_sink_printf(GtkGSDocSink * sink, const gchar * fmt, ...)
141 {
142   va_list ap;
143
144   va_start(ap, fmt);
145   gtk_gs_doc_sink_printf_v(sink, fmt, ap);
146   va_end(ap);
147 }
148
149 gchar *
150 gtk_gs_doc_sink_get_buffer(GtkGSDocSink * sink)
151 {
152   guint total;
153   GSList *node;
154
155   for(total = 0, node = sink->chunks; node; node = node->next) {
156     total += ((GtkGSDocChunk *) node->data)->len;
157   }
158   if(total) {
159     gchar *buf = g_malloc(sizeof(gchar) * (total + 1)), *ptr;
160     if(!buf)
161       return NULL;
162     for(ptr = buf, node = sink->chunks; node; node = node->next) {
163       memcpy(ptr,
164              ((GtkGSDocChunk *) node->data)->buf,
165              ((GtkGSDocChunk *) node->data)->len);
166       ptr += ((GtkGSDocChunk *) node->data)->len;
167     }
168     buf[total] = '\0';
169     return buf;
170   }
171   else
172     return NULL;
173 }