Rev 44870 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Language for Statistical Data Analysis* Copyright (C) 1995, 1996, 1997, Robert Gentleman and Ross Ihaka* 2007 R Development Core Team** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, a copy is available at* http://www.r-project.org/Licenses/*** I/O Support Code** This is a general IO support package to provide R with a uniform* interface to reading data from the console, files and internal* text strings.** This is probably overkill, but it works much better than the* previous anarchy.*//* <UTF8> byte-level access is ok */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "IOStuff.h"/* Move the iob->write_buf pointer to the next *//* BufferListItem in the chain. If there no next *//* buffer item, then one is added. */static int NextWriteBufferListItem(IoBuffer *iob){if (iob->write_buf->next) {iob->write_buf = iob->write_buf->next;}else {BufferListItem *_new;if (!(_new = (BufferListItem*)malloc(sizeof(BufferListItem))))return 0;_new->next = NULL;iob->write_buf->next = _new;iob->write_buf = iob->write_buf->next;}iob->write_ptr = iob->write_buf->buf;iob->write_offset = 0;return 1;}/* Move the iob->read_buf pointer to the next *//* BufferListItem in the chain. */static int NextReadBufferListItem(IoBuffer *iob){iob->read_buf = iob->read_buf->next;iob->read_ptr = iob->read_buf->buf;iob->read_offset = 0;return 1;}/* Reset the read/write pointers of an IoBuffer */int attribute_hidden R_IoBufferWriteReset(IoBuffer *iob){if (iob == NULL || iob->start_buf == NULL)return 0;iob->write_buf = iob->start_buf;iob->write_ptr = iob->write_buf->buf;iob->write_offset = 0;iob->read_buf = iob->start_buf;iob->read_ptr = iob->read_buf->buf;iob->read_offset = 0;return 1;}/* Reset the read pointer of an IoBuffer */int attribute_hidden R_IoBufferReadReset(IoBuffer *iob){if (iob == NULL || iob->start_buf == NULL)return 0;iob->read_buf = iob->start_buf;iob->read_ptr = iob->read_buf->buf;iob->read_offset = 0;return 1;}/* Allocate an initial BufferListItem for IoBuffer *//* Initialize the counts and pointers. */int attribute_hidden R_IoBufferInit(IoBuffer *iob){if (iob == NULL) return 0;iob->start_buf = (BufferListItem*)malloc(sizeof(BufferListItem));if (iob->start_buf == NULL) return 0;iob->start_buf->next = NULL;return R_IoBufferWriteReset(iob);}/* Free any BufferListItem's associated with an IoBuffer *//* This resets pointers to NULL, which could be detected *//* in other calls. */int attribute_hidden R_IoBufferFree(IoBuffer *iob){BufferListItem *thisItem, *nextItem;if (iob == NULL || iob->start_buf == NULL)return 0;thisItem = iob->start_buf;while (thisItem) {nextItem = thisItem->next;free(thisItem);thisItem = nextItem;}return 1;}/* Add a character to an IoBuffer */int attribute_hidden R_IoBufferPutc(int c, IoBuffer *iob){if (iob->write_offset == IOBSIZE)NextWriteBufferListItem(iob);*(iob->write_ptr)++ = c;iob->write_offset++;return 0;/*not used*/}/* Add a (null terminated) string to an IoBuffer */int attribute_hidden R_IoBufferPuts(char *s, IoBuffer *iob){char *p;int n = 0;for (p = s; *p; p++) {R_IoBufferPutc(*p, iob);n++;}return n;}/* Read a character from an IoBuffer */int attribute_hidden R_IoBufferGetc(IoBuffer *iob){if (iob->read_buf == iob->write_buf &&iob->read_offset >= iob->write_offset)return EOF;if (iob->read_offset == IOBSIZE) NextReadBufferListItem(iob);iob->read_offset++;return *(iob->read_ptr)++;}/* Initialization code for text buffers */static void transferChars(unsigned char *p, const char *q){while (*q) *p++ = *q++;*p++ = '\n';*p++ = '\0';}int attribute_hidden R_TextBufferInit(TextBuffer *txtb, SEXP text){int i, k, l, n;if (isString(text)) {n = length(text);l = 0;for (i = 0; i < n; i++) {if (STRING_ELT(text, i) != R_NilValue) {k = strlen(translateChar(STRING_ELT(text, i)));if (k > l)l = k;}}txtb->vmax = vmaxget();txtb->buf = (unsigned char *)R_alloc(l+2, sizeof(char)); /* '\n' and '\0' */txtb->bufp = txtb->buf;txtb->text = text;txtb->ntext = n;txtb->offset = 0;transferChars(txtb->buf,translateChar(STRING_ELT(txtb->text, txtb->offset)));txtb->offset++;return 1;}else {txtb->vmax = vmaxget();txtb->buf = NULL;txtb->bufp = NULL;txtb->text = R_NilValue;txtb->ntext = 0;txtb->offset = 1;return 0;}}/* Finalization code for text buffers */int attribute_hidden R_TextBufferFree(TextBuffer *txtb){vmaxset(txtb->vmax);return 0;/* not used */}/* Getc for text buffers */int attribute_hidden R_TextBufferGetc(TextBuffer *txtb){if (txtb->buf == NULL)return EOF;if (*(txtb->bufp) == '\0') {if (txtb->offset == txtb->ntext) {txtb->buf = NULL;return EOF;}else {transferChars(txtb->buf,translateChar(STRING_ELT(txtb->text, txtb->offset)));txtb->bufp = txtb->buf;txtb->offset++;}}return *txtb->bufp++;}