Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

wsstream_file.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  *
00059  * wsstream_file.c
00060  *
00061  * Author: Markku Rossi <mtr@iki.fi>
00062  *
00063  * Copyright (c) 1999-2000 WAPIT OY LTD.
00064  *       All rights reserved.
00065  *
00066  * Implementation of the file stream.
00067  *
00068  */
00069 
00070 #include "wsint.h"
00071 
00072 /********************* Types and definitions ****************************/
00073 
00074 struct WsStreamFileCtxRec
00075 {
00076     FILE *fp;
00077 
00078     /* Should the `fp' be closed when the stream is closed. */
00079     WsBool close_fp;
00080 
00081     /* A temporary buffer for the raw file data. */
00082     unsigned char buf[WS_STREAM_BUFFER_SIZE];
00083 
00084     /* For file output streams, this variable holds the number of data
00085        in `buf'. */
00086     size_t data_in_buf;
00087 
00088     /* Other fields (like character set conversion information) might be
00089        defined later. */
00090 };
00091 
00092 typedef struct WsStreamFileCtxRec WsStreamFileCtx;
00093 
00094 /********************* Static method functions **************************/
00095 
00096 static size_t file_input(void *context, WsUInt32 *buf, size_t buflen)
00097 {
00098     WsStreamFileCtx *ctx = (WsStreamFileCtx *) context;
00099     size_t read = 0;
00100 
00101     while (buflen > 0) {
00102         size_t toread = buflen < sizeof(ctx->buf) ? buflen : sizeof(ctx->buf);
00103         size_t got, i;
00104 
00105         got = fread(ctx->buf, 1, toread, ctx->fp);
00106 
00107         /* Convert the data to the stream's IO buffer. */
00108         for (i = 0; i < got; i++)
00109             buf[i] = ctx->buf[i];
00110 
00111         buflen -= got;
00112         buf += got;
00113         read += got;
00114 
00115         if (got < toread)
00116             /* EOF seen. */
00117             break;
00118     }
00119 
00120     return read;
00121 }
00122 
00123 
00124 static size_t file_output(void *context, WsUInt32 *buf, size_t buflen)
00125 {
00126     WsStreamFileCtx *ctx = (WsStreamFileCtx *) context;
00127     size_t wrote = 0;
00128     unsigned char ch;
00129 
00130     while (buflen) {
00131         /* Do we have any space in the stream's internal IO buffer? */
00132         if (ctx->data_in_buf >= WS_STREAM_BUFFER_SIZE) {
00133             size_t w;
00134 
00135             /* No, flush something to our file stream. */
00136             w = fwrite(ctx->buf, 1, ctx->data_in_buf, ctx->fp);
00137             if (w < ctx->data_in_buf) {
00138                 /* Write failed.  As a result code we return the number
00139                           of characters written from our current write
00140                           request. */
00141                 ctx->data_in_buf = 0;
00142                 return wrote;
00143             }
00144 
00145             ctx->data_in_buf = 0;
00146         }
00147         /* Now we have space in the internal buffer. */
00148 
00149         /* Here we could perform some sort of conversions from ISO 10646
00150            to the output character set.  Currently we just support
00151            ISO-8859/1 and all unknown characters are replaced with
00152            '?'. */
00153 
00154         if (*buf > 0xff)
00155             ch = '?';
00156         else
00157             ch = (unsigned char) * buf;
00158 
00159         ctx->buf[ctx->data_in_buf++] = ch;
00160 
00161         /* Move forward. */
00162         buf++;
00163         buflen--;
00164         wrote++;
00165     }
00166 
00167     return wrote;
00168 }
00169 
00170 
00171 static WsBool file_flush(void *context)
00172 {
00173     WsStreamFileCtx *ctx = (WsStreamFileCtx *) context;
00174 
00175     /* If the internal buffer has any data, then this stream must be an
00176        output stream.  The variable `data_in_buf' is not updated on
00177        input streams. */
00178     if (ctx->data_in_buf) {
00179         if (fwrite(ctx->buf, 1, ctx->data_in_buf, ctx->fp) != ctx->data_in_buf) {
00180             /* The write failed. */
00181             ctx->data_in_buf = 0;
00182             return WS_FALSE;
00183         }
00184 
00185         /* The temporary buffer is not empty. */
00186         ctx->data_in_buf = 0;
00187     }
00188 
00189     /* Flush the underlying file stream. */
00190     return fflush(ctx->fp) == 0;
00191 }
00192 
00193 
00194 static void file_close(void *context)
00195 {
00196     WsStreamFileCtx *ctx = (WsStreamFileCtx *) context;
00197 
00198     if (ctx->close_fp)
00199         fclose(ctx->fp);
00200 
00201     ws_free(ctx);
00202 }
00203 
00204 /********************* Global functions *********************************/
00205 
00206 WsStream *ws_stream_new_file(FILE *fp, WsBool output, WsBool close)
00207 {
00208     WsStreamFileCtx *ctx = ws_calloc(1, sizeof(*ctx));
00209     WsStream *stream;
00210 
00211     if (ctx == NULL)
00212         return NULL;
00213 
00214     ctx->fp = fp;
00215     ctx->close_fp = close;
00216 
00217     if (output)
00218         stream = ws_stream_new(ctx, file_output, file_flush, file_close);
00219     else
00220         stream = ws_stream_new(ctx, file_input, file_flush, file_close);
00221 
00222     if (stream == NULL)
00223         /* The stream creation failed.  Close the stream context. */
00224         file_close(ctx);
00225 
00226     return stream;
00227 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.