302 lines
7.1 KiB
C++
302 lines
7.1 KiB
C++
/*
|
|
* $Id$
|
|
*
|
|
Copyright (c) 2006-2019 Chung, Hyung-Hwan. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <qse/sed/StdSed.hpp>
|
|
#include <qse/si/fio.h>
|
|
#include <qse/si/sio.h>
|
|
#include "sed-prv.h"
|
|
#include "../cmn/mem-prv.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(qse_sed_getmmgr((StdSed::sed_t*)io), 0, file, flags);
|
|
if (sio == QSE_NULL)
|
|
{
|
|
qse_cstr_t ea;
|
|
ea.ptr = (StdSed::char_t*)file;
|
|
ea.len = qse_strlen (file);
|
|
((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 StdSed::char_t* std_names[] =
|
|
{
|
|
QSE_T("stdin"),
|
|
QSE_T("stdout"),
|
|
QSE_T("stderr"),
|
|
};
|
|
|
|
sio = qse_sio_openstd(qse_sed_getmmgr((StdSed::sed_t*)io), 0, std, flags);
|
|
if (sio == QSE_NULL)
|
|
{
|
|
qse_cstr_t ea;
|
|
ea.ptr = (StdSed::char_t*)std_names[std];
|
|
ea.len = qse_strlen (std_names[std]);
|
|
((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 | QSE_SIO_LINEBREAK;
|
|
|
|
if (ioname == QSE_NULL)
|
|
{
|
|
//
|
|
// a normal console is indicated by a null name or a dash
|
|
//
|
|
if (io.getMode() == READ)
|
|
{
|
|
sio = (infile == QSE_NULL || (infile[0] == QSE_T('-') && infile[1] == QSE_T('\0')))?
|
|
open_sio_std (io, QSE_SIO_STDIN, oflags):
|
|
open_sio (io, infile, oflags);
|
|
}
|
|
else
|
|
{
|
|
sio = (outfile == QSE_NULL || (outfile[0] == QSE_T('-') && outfile[1] == QSE_T('\0')))?
|
|
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 = (char_t*)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 = (char_t*)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)
|
|
/////////////////////////////////
|