/* * $Id$ * Copyright 2006-2012 Chung, Hyung-Hwan. This file is part of QSE. QSE is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. QSE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with QSE. If not, see . */ #include #include #include #include "sed.h" #include "../cmn/mem.h" ///////////////////////////////// QSE_BEGIN_NAMESPACE(QSE) ///////////////////////////////// static qse_sio_t* open_sio (StdSed::Stream::Data& io, const qse_char_t* file, int flags) { qse_sio_t* sio; sio = qse_sio_open (((StdSed::sed_t*)io)->mmgr, 0, file, flags); if (sio == QSE_NULL) { qse_cstr_t ea; ea.ptr = file; ea.len = qse_strlen (file); ((StdSed::Sed*)io)->setError (QSE_SED_EIOFIL, &ea); } return sio; } static qse_sio_t* open_sio_std (StdSed::Stream::Data& io, qse_sio_std_t std, int flags) { qse_sio_t* sio; static const qse_char_t* std_names[] = { QSE_T("stdin"), QSE_T("stdout"), QSE_T("stderr"), }; sio = qse_sio_openstd (((StdSed::sed_t*)io)->mmgr, 0, std, flags); if (sio == QSE_NULL) { qse_cstr_t ea; ea.ptr = std_names[std]; ea.len = qse_strlen (std_names[std]); ((StdSed::Sed*)io)->setError (QSE_SED_EIOFIL, &ea); } return sio; } int StdSed::FileStream::open (Data& io) { qse_sio_t* sio; const char_t* ioname = io.getName(); int oflags; if (io.getMode() == READ) oflags = QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR; else oflags = QSE_SIO_WRITE | QSE_SIO_CREATE | QSE_SIO_TRUNCATE | QSE_SIO_IGNOREMBWCERR; if (ioname == QSE_NULL) { // // a normal console is indicated by a null name // if (io.getMode() == READ) { sio = (infile == QSE_NULL)? open_sio_std (io, QSE_SIO_STDIN, oflags): open_sio (io, infile, oflags); } else { sio = (outfile == QSE_NULL)? open_sio_std (io, QSE_SIO_STDOUT, oflags): open_sio (io, outfile, oflags); } } else { // // if ioname is not empty, it is a file name // sio = open_sio (io, ioname, oflags); } if (sio == QSE_NULL) return -1; if (this->cmgr) qse_sio_setcmgr (sio, this->cmgr); io.setHandle (sio); return 1; } int StdSed::FileStream::close (Data& io) { qse_sio_close ((qse_sio_t*)io.getHandle()); return 0; } StdSed::ssize_t StdSed::FileStream::read (Data& io, char_t* buf, size_t len) { ssize_t n = qse_sio_getstrn ((qse_sio_t*)io.getHandle(), buf, len); if (n == -1) { if (io.getName() == QSE_NULL && infile != QSE_NULL) { // if writing to outfile, set the error message // explicitly. other cases are handled by // the caller in sed.c. qse_cstr_t ea; ea.ptr = infile; ea.len = qse_strlen (infile); ((Sed*)io)->setError (QSE_SED_EIOFIL, &ea); } } return n; } StdSed::ssize_t StdSed::FileStream::write (Data& io, const char_t* buf, size_t len) { ssize_t n = qse_sio_putstrn ((qse_sio_t*)io.getHandle(), buf, len); if (n == -1) { if (io.getName() == QSE_NULL && outfile != QSE_NULL) { // if writing to outfile, set the error message // explicitly. other cases are handled by // the caller in sed.c. qse_cstr_t ea; ea.ptr = outfile; ea.len = qse_strlen (outfile); ((Sed*)io)->setError (QSE_SED_EIOFIL, &ea); } } return n; } StdSed::StringStream::StringStream (const char_t* in) { this->in.ptr = in; this->in.end = in + qse_strlen(in); this->out.inited = false; } StdSed::StringStream::StringStream (const char_t* in, size_t len) { this->in.ptr = in; this->in.end = in + len; this->out.inited = false; } StdSed::StringStream::~StringStream () { if (out.inited) qse_str_fini (&out.buf); } int StdSed::StringStream::open (Data& io) { const char_t* ioname = io.getName (); if (ioname == QSE_NULL) { // open a main data stream if (io.getMode() == READ) { in.cur = in.ptr; io.setHandle ((void*)in.ptr); } else { if (!out.inited) { if (qse_str_init (&out.buf, ((Sed*)io)->getMmgr(), 256) <= -1) { ((Sed*)io)->setError (QSE_SED_ENOMEM); return -1; } out.inited = true; } qse_str_clear (&out.buf); io.setHandle (&out.buf); } } else { // open files for a r or w command qse_sio_t* sio; int mode = (io.getMode() == READ)? QSE_SIO_READ: (QSE_SIO_WRITE|QSE_SIO_CREATE|QSE_SIO_TRUNCATE); sio = qse_sio_open (((Sed*)io)->getMmgr(), 0, ioname, mode); if (sio == QSE_NULL) return -1; io.setHandle (sio); } return 1; } int StdSed::StringStream::close (Data& io) { const void* handle = io.getHandle(); if (handle != in.ptr && handle != &out.buf) qse_sio_close ((qse_sio_t*)handle); return 0; } StdSed::ssize_t StdSed::StringStream::read (Data& io, char_t* buf, size_t len) { const void* handle = io.getHandle(); if (len == (size_t)-1) len--; // shrink buffer if too long if (handle == in.ptr) { size_t n = 0; while (in.cur < in.end && n < len) buf[n++] = *in.cur++; return (ssize_t)n; } else { QSE_ASSERT (handle != &out.buf); return qse_sio_getstrn ((qse_sio_t*)handle, buf, len); } } StdSed::ssize_t StdSed::StringStream::write (Data& io, const char_t* data, size_t len) { const void* handle = io.getHandle(); if (len == (qse_size_t)-1) len--; // shrink data if too long if (handle == &out.buf) { if (qse_str_ncat (&out.buf, data, len) == (qse_size_t)-1) { ((Sed*)io)->setError (QSE_SED_ENOMEM); return -1; } return len; } else { QSE_ASSERT (handle != in.ptr); return qse_sio_putstrn ((qse_sio_t*)handle, data, len); } } const StdSed::char_t* StdSed::StringStream::getInput (size_t* len) const { if (len) *len = in.end - in.ptr; return in.ptr; } const StdSed::char_t* StdSed::StringStream::getOutput (size_t* len) const { if (out.inited) { if (len) *len = QSE_STR_LEN(&out.buf); return QSE_STR_PTR(&out.buf); } else { if (len) *len = 0; return QSE_T(""); } } ///////////////////////////////// QSE_END_NAMESPACE(QSE) /////////////////////////////////