1/*********************************************************************** 2 * * 3 * $Id: hpgsistream.c 343 2006-08-18 16:48:09Z softadm $ 4 * * 5 * hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript * 6 * API for rendering a scene and thus renders to a variety of * 7 * devices and fileformats. * 8 * * 9 * (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at * 10 * * 11 * Author: Wolfgang Glas * 12 * * 13 * hpgs is free software; you can redistribute it and/or * 14 * modify it under the terms of the GNU Lesser General Public * 15 * License as published by the Free Software Foundation; either * 16 * version 2.1 of the License, or (at your option) any later version. * 17 * * 18 * hpgs is distributed in the hope that it will be useful, * 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 21 * Lesser General Public License for more details. * 22 * * 23 * You should have received a copy of the GNU Lesser General Public * 24 * License along with this library; if not, write to the * 25 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * 26 * Boston, MA 02111-1307 USA * 27 * * 28 *********************************************************************** 29 * * 30 * The implementations of input streams. * 31 * * 32 ***********************************************************************/ 33 34#include <hpgs.h> 35#include <math.h> 36#include <string.h> 37#include <errno.h> 38 39static int file_seek (FILE *file, size_t pos) 40{ 41 return fseek(file,pos,SEEK_SET); 42} 43 44static int file_seekend (FILE *file, size_t pos) 45{ 46 return fseek(file,-(long)pos,SEEK_END); 47} 48 49static int file_tell (FILE *file, size_t *pos) 50{ 51 long pp=ftell(file); 52 53 if (pp<0) return -1; 54 55 *pos = pp; 56 return 0; 57} 58 59/*! \defgroup base Basic facilities. 60 61 This module contains structures for operating on abstract input streams 62 as well as color structures and a 2D point. 63*/ 64 65static hpgs_istream_vtable file_vtable = 66 { 67 (hpgs_istream_getc_func_t) getc, 68 (hpgs_istream_ungetc_func_t) ungetc, 69 (hpgs_istream_close_func_t) fclose, 70 (hpgs_istream_iseof_func_t) feof, 71 (hpgs_istream_iserror_func_t) ferror, 72 (hpgs_istream_seek_func_t) file_seek, 73 (hpgs_istream_tell_func_t) file_tell, 74 (hpgs_istream_read_func_t) fread, 75 (hpgs_istream_seekend_func_t) file_seekend 76 }; 77 78/*! Returns a new \c hpgs_istream created on the heap, 79 which operates on a file, which is opened by this call 80 in read-only mode. 81 82 Returns a null pointer, when an I/O error occurrs. 83 In this case, details about the the error can be retrieved 84 using \c errno. 85 */ 86hpgs_istream *hpgs_new_file_istream(const char *fn) 87{ 88 FILE *in = fopen (fn,"rb"); 89 hpgs_istream *ret = 0; 90 91 if (!in) return 0; 92 93 ret = (hpgs_istream *)malloc(sizeof(hpgs_istream)); 94 95 if (!ret) 96 { 97 fclose(in); 98 return 0; 99 } 100 101 ret->stream = in; 102 ret->vtable = &file_vtable; 103 104 return ret; 105} 106 107/* memory stream implementation functions. */ 108typedef struct hpgs_mem_istream_stream_st hpgs_mem_istream_stream; 109 110struct hpgs_mem_istream_stream_st 111{ 112 const unsigned char *data; 113 const unsigned char *gptr; 114 const unsigned char *eptr; 115 int errflg; 116}; 117 118static int mem_getc (hpgs_mem_istream_stream *stream) 119{ 120 int ret; 121 122 if (stream->errflg) 123 ret=EOF; 124 else 125 { 126 if (stream->gptr >= stream->eptr) 127 ret = EOF; 128 else 129 { 130 ret = *stream->gptr; 131 ++stream->gptr; 132 } 133 } 134 135 return ret; 136} 137 138static int mem_ungetc (int c, hpgs_mem_istream_stream *stream) 139{ 140 if (stream->errflg) return -1; 141 if (stream->gptr <= stream->data) { stream->errflg = 1; return -1; } 142 --stream->gptr; 143 return 0; 144} 145 146static int mem_close (hpgs_mem_istream_stream *stream) 147{ 148 return 0; 149} 150 151static int mem_iseof (hpgs_mem_istream_stream *stream) 152{ 153 return stream->gptr >= stream->eptr; 154} 155 156static int mem_iserror (hpgs_mem_istream_stream *stream) 157{ 158 return stream->errflg; 159} 160 161static int mem_tell (hpgs_mem_istream_stream *stream, size_t *pos) 162{ 163 if (stream->errflg) return -1; 164 *pos = stream->gptr - stream->data; 165 return 0; 166} 167 168static int mem_seek (hpgs_mem_istream_stream *stream, size_t pos) 169{ 170 if (stream->data + pos > stream->eptr) 171 { 172 stream->errflg = 1; 173 return -1; 174 } 175 176 stream->gptr = stream->data+pos; 177 stream->errflg = 0; 178 return 0; 179} 180 181static int mem_seekend (hpgs_mem_istream_stream *stream, size_t pos) 182{ 183 if (stream->data + pos > stream->eptr) 184 { 185 stream->errflg = 1; 186 return -1; 187 } 188 189 stream->gptr = stream->eptr-pos; 190 stream->errflg = 0; 191 return 0; 192} 193 194static size_t mem_read (void *ptr, size_t size, size_t nmemb, hpgs_mem_istream_stream *stream) 195{ 196 size_t ret = 0; 197 198 if (!stream->errflg) 199 { 200 if (stream->gptr < stream->eptr) 201 { 202 ret = (stream->eptr - stream->gptr)/size; 203 if (ret > nmemb) ret = nmemb; 204 205 memcpy(ptr,stream->gptr,size * ret); 206 stream->gptr += size * ret; 207 } 208 } 209 210 return ret; 211} 212 213static hpgs_istream_vtable mem_vtable = 214 { 215 (hpgs_istream_getc_func_t) mem_getc, 216 (hpgs_istream_ungetc_func_t) mem_ungetc, 217 (hpgs_istream_close_func_t) mem_close, 218 (hpgs_istream_iseof_func_t) mem_iseof, 219 (hpgs_istream_iserror_func_t) mem_iserror, 220 (hpgs_istream_seek_func_t) mem_seek, 221 (hpgs_istream_tell_func_t) mem_tell, 222 (hpgs_istream_read_func_t) mem_read, 223 (hpgs_istream_seekend_func_t) mem_seekend 224 }; 225 226/*! Returns a new \c hpgs_istream created on the heap, 227 which operates on a chunk of memory in the given 228 location with the given size. 229 230 Returns a null pointer, when the system is out of memory. 231 */ 232hpgs_istream *hpgs_new_mem_istream(const unsigned char *data, 233 size_t data_size, 234 hpgs_bool dup) 235{ 236#define HPGS_ISTREAM_PAD_SZ (8*((sizeof(hpgs_istream)+7)/8)) 237#define HPGS_ISTREAM_STREAM_PAD_SZ (8*((sizeof(hpgs_mem_istream_stream)+7)/8)) 238 239 hpgs_mem_istream_stream *stream; 240 hpgs_istream *ret; 241 size_t sz = HPGS_ISTREAM_PAD_SZ + HPGS_ISTREAM_STREAM_PAD_SZ; 242 void *ptr; 243 244 if (dup) sz += data_size; 245 246 ptr = malloc(sz); 247 ret = (hpgs_istream *)ptr; 248 249 if (!ret) 250 return 0; 251 252 stream = (hpgs_mem_istream_stream *)(ptr+HPGS_ISTREAM_PAD_SZ); 253 254 if (dup) 255 { 256 unsigned char *ddata = 257 (unsigned char *)ptr + HPGS_ISTREAM_PAD_SZ + HPGS_ISTREAM_STREAM_PAD_SZ; 258 259 stream->data = ddata; 260 stream->gptr = ddata; 261 stream->eptr = ddata+data_size; 262 263 memcpy(ddata,data,data_size); 264 } 265 else 266 { 267 stream->data = data; 268 stream->gptr = data; 269 stream->eptr = data+data_size; 270 } 271 272 stream->errflg = 0; 273 274 ret->stream = stream; 275 ret->vtable = &mem_vtable; 276 277 return ret; 278} 279