wsstream_file.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:4k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  *
  3.  * wsstream_file.c
  4.  *
  5.  * Author: Markku Rossi <mtr@iki.fi>
  6.  *
  7.  * Copyright (c) 1999-2000 WAPIT OY LTD.
  8.  *  All rights reserved.
  9.  *
  10.  * Implementation of the file stream.
  11.  *
  12.  */
  13. #include "wsint.h"
  14. /********************* Types and definitions ****************************/
  15. struct WsStreamFileCtxRec
  16. {
  17.     FILE *fp;
  18.     /* Should the `fp' be closed when the stream is closed. */
  19.     WsBool close_fp;
  20.     /* A temporary buffer for the raw file data. */
  21.     unsigned char buf[WS_STREAM_BUFFER_SIZE];
  22.     /* For file output streams, this variable holds the number of data
  23.        in `buf'. */
  24.     size_t data_in_buf;
  25.     /* Other fields (like character set conversion information) might be
  26.        defined later. */
  27. };
  28. typedef struct WsStreamFileCtxRec WsStreamFileCtx;
  29. /********************* Static method functions **************************/
  30. static size_t file_input(void *context, WsUInt32 *buf, size_t buflen)
  31. {
  32.     WsStreamFileCtx *ctx = (WsStreamFileCtx *) context;
  33.     size_t read = 0;
  34.     while (buflen > 0) {
  35.         size_t toread = buflen < sizeof(ctx->buf) ? buflen : sizeof(ctx->buf);
  36.         size_t got, i;
  37.         got = fread(ctx->buf, 1, toread, ctx->fp);
  38.         /* Convert the data to the stream's IO buffer. */
  39.         for (i = 0; i < got; i++)
  40.             buf[i] = ctx->buf[i];
  41.         buflen -= got;
  42.         buf += got;
  43.         read += got;
  44.         if (got < toread)
  45.             /* EOF seen. */
  46.             break;
  47.     }
  48.     return read;
  49. }
  50. static size_t file_output(void *context, WsUInt32 *buf, size_t buflen)
  51. {
  52.     WsStreamFileCtx *ctx = (WsStreamFileCtx *) context;
  53.     size_t wrote = 0;
  54.     unsigned char ch;
  55.     while (buflen) {
  56.         /* Do we have any space in the stream's internal IO buffer? */
  57.         if (ctx->data_in_buf >= WS_STREAM_BUFFER_SIZE) {
  58.             size_t w;
  59.             /* No, flush something to our file stream. */
  60.             w = fwrite(ctx->buf, 1, ctx->data_in_buf, ctx->fp);
  61.             if (w < ctx->data_in_buf) {
  62.                 /* Write failed.  As a result code we return the number
  63.                           of characters written from our current write
  64.                           request. */
  65.                 ctx->data_in_buf = 0;
  66.                 return wrote;
  67.             }
  68.             ctx->data_in_buf = 0;
  69.         }
  70.         /* Now we have space in the internal buffer. */
  71.         /* Here we could perform some sort of conversions from ISO 10646
  72.            to the output character set.  Currently we just support
  73.            ISO-8859/1 and all unknown characters are replaced with
  74.            '?'. */
  75.         if (*buf > 0xff)
  76.             ch = '?';
  77.         else
  78.             ch = (unsigned char) * buf;
  79.         ctx->buf[ctx->data_in_buf++] = ch;
  80.         /* Move forward. */
  81.         buf++;
  82.         buflen--;
  83.         wrote++;
  84.     }
  85.     return wrote;
  86. }
  87. static WsBool file_flush(void *context)
  88. {
  89.     WsStreamFileCtx *ctx = (WsStreamFileCtx *) context;
  90.     /* If the internal buffer has any data, then this stream must be an
  91.        output stream.  The variable `data_in_buf' is not updated on
  92.        input streams. */
  93.     if (ctx->data_in_buf) {
  94.         if (fwrite(ctx->buf, 1, ctx->data_in_buf, ctx->fp) != ctx->data_in_buf) {
  95.             /* The write failed. */
  96.             ctx->data_in_buf = 0;
  97.             return WS_FALSE;
  98.         }
  99.         /* The temporary buffer is not empty. */
  100.         ctx->data_in_buf = 0;
  101.     }
  102.     /* Flush the underlying file stream. */
  103.     return fflush(ctx->fp) == 0;
  104. }
  105. static void file_close(void *context)
  106. {
  107.     WsStreamFileCtx *ctx = (WsStreamFileCtx *) context;
  108.     if (ctx->close_fp)
  109.         fclose(ctx->fp);
  110.     ws_free(ctx);
  111. }
  112. /********************* Global functions *********************************/
  113. WsStream *ws_stream_new_file(FILE *fp, WsBool output, WsBool close)
  114. {
  115.     WsStreamFileCtx *ctx = ws_calloc(1, sizeof(*ctx));
  116.     WsStream *stream;
  117.     if (ctx == NULL)
  118.         return NULL;
  119.     ctx->fp = fp;
  120.     ctx->close_fp = close;
  121.     if (output)
  122.         stream = ws_stream_new(ctx, file_output, file_flush, file_close);
  123.     else
  124.         stream = ws_stream_new(ctx, file_input, file_flush, file_close);
  125.     if (stream == NULL)
  126.         /* The stream creation failed.  Close the stream context. */
  127.         file_close(ctx);
  128.     return stream;
  129. }