746 lines
16 KiB
C
746 lines
16 KiB
C
|
/*
|
||
|
Copyright (c) 2006-2020 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 "cut-prv.h"
|
||
|
#include "hawk-prv.h"
|
||
|
#include <hawk-chr.h>
|
||
|
|
||
|
static int hawk_cut_init (hawk_cut_t* cut, hawk_mmgr_t* mmgr, hawk_cmgr_t* cmgr);
|
||
|
static void hawk_cut_fini (hawk_cut_t* cut);
|
||
|
|
||
|
#define SETERR0(cut,num) \
|
||
|
do { hawk_cut_seterrnum (cut, HAWK_NULL, num); } while (0)
|
||
|
|
||
|
#define DFL_LINE_CAPA 256
|
||
|
|
||
|
static int add_selector_block (hawk_cut_t* cut)
|
||
|
{
|
||
|
hawk_cut_sel_blk_t* b;
|
||
|
|
||
|
b = (hawk_cut_sel_blk_t*)hawk_cut_allocmem(cut, HAWK_SIZEOF(*b));
|
||
|
if (HAWK_UNLIKELY(!b)) return -1;
|
||
|
|
||
|
HAWK_MEMSET(b, 0, HAWK_SIZEOF(*b));
|
||
|
b->next = HAWK_NULL;
|
||
|
b->len = 0;
|
||
|
|
||
|
cut->sel.lb->next = b;
|
||
|
cut->sel.lb = b;
|
||
|
cut->sel.count = 0;
|
||
|
cut->sel.fcount = 0;
|
||
|
cut->sel.ccount = 0;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void free_all_selector_blocks (hawk_cut_t* cut)
|
||
|
{
|
||
|
hawk_cut_sel_blk_t* b;
|
||
|
|
||
|
for (b = cut->sel.fb.next; b != HAWK_NULL; )
|
||
|
{
|
||
|
hawk_cut_sel_blk_t* nxt = b->next;
|
||
|
hawk_cut_freemem(cut, b);
|
||
|
b = nxt;
|
||
|
}
|
||
|
|
||
|
cut->sel.lb = &cut->sel.fb;
|
||
|
cut->sel.lb->len = 0;
|
||
|
cut->sel.lb->next = HAWK_NULL;
|
||
|
cut->sel.count = 0;
|
||
|
cut->sel.fcount = 0;
|
||
|
cut->sel.ccount = 0;
|
||
|
}
|
||
|
|
||
|
hawk_cut_t* hawk_cut_open (hawk_mmgr_t* mmgr, hawk_oow_t xtnsize, hawk_cmgr_t* cmgr, hawk_errnum_t* errnum)
|
||
|
{
|
||
|
hawk_cut_t* cut;
|
||
|
|
||
|
cut = (hawk_cut_t*)HAWK_MMGR_ALLOC(mmgr, HAWK_SIZEOF(hawk_cut_t) + xtnsize);
|
||
|
if (HAWK_LIKELY(cut))
|
||
|
{
|
||
|
if (hawk_cut_init(cut, mmgr, cmgr) <= -1)
|
||
|
{
|
||
|
if (errnum) *errnum = hawk_cut_geterrnum(cut);
|
||
|
HAWK_MMGR_FREE (mmgr, cut);
|
||
|
cut = HAWK_NULL;
|
||
|
}
|
||
|
else HAWK_MEMSET(cut + 1, 0, xtnsize);
|
||
|
}
|
||
|
else if (errnum) *errnum = HAWK_ENOMEM;
|
||
|
|
||
|
return cut;
|
||
|
}
|
||
|
|
||
|
void hawk_cut_close (hawk_cut_t* cut)
|
||
|
{
|
||
|
hawk_cut_fini (cut);
|
||
|
HAWK_MMGR_FREE (hawk_cut_getmmgr(cut), cut);
|
||
|
}
|
||
|
|
||
|
static int hawk_cut_init (hawk_cut_t* cut, hawk_mmgr_t* mmgr, hawk_cmgr_t* cmgr)
|
||
|
{
|
||
|
HAWK_MEMSET (cut, 0, HAWK_SIZEOF(*cut));
|
||
|
|
||
|
cut->_instsize = HAWK_SIZEOF(*cut);
|
||
|
cut->_gem.mmgr = mmgr;
|
||
|
cut->_gem.cmgr = cmgr;
|
||
|
|
||
|
/* initialize error handling fields */
|
||
|
cut->_gem.errnum = HAWK_ENOERR;
|
||
|
cut->_gem.errmsg[0] = '\0';
|
||
|
cut->_gem.errloc.line = 0;
|
||
|
cut->_gem.errloc.colm = 0;
|
||
|
cut->_gem.errloc.file = HAWK_NULL;
|
||
|
cut->_gem.errstr = hawk_dfl_errstr;
|
||
|
|
||
|
|
||
|
/* on init, the last points to the first */
|
||
|
cut->sel.lb = &cut->sel.fb;
|
||
|
/* the block has no data yet */
|
||
|
cut->sel.fb.len = 0;
|
||
|
|
||
|
cut->e.in.cflds = HAWK_COUNTOF(cut->e.in.sflds);
|
||
|
cut->e.in.flds = cut->e.in.sflds;
|
||
|
|
||
|
if (hawk_ooecs_init(&cut->e.in.line, hawk_cut_getgem(cut), DFL_LINE_CAPA) <= -1) return -1;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void hawk_cut_fini (hawk_cut_t* cut)
|
||
|
{
|
||
|
free_all_selector_blocks (cut);
|
||
|
if (cut->e.in.flds != cut->e.in.sflds) hawk_cut_freemem(cut, cut->e.in.flds);
|
||
|
hawk_ooecs_fini(&cut->e.in.line);
|
||
|
}
|
||
|
|
||
|
void hawk_cut_setoption (hawk_cut_t* cut, int option)
|
||
|
{
|
||
|
cut->option = option;
|
||
|
}
|
||
|
|
||
|
int hawk_cut_getoption (hawk_cut_t* cut)
|
||
|
{
|
||
|
return cut->option;
|
||
|
}
|
||
|
|
||
|
void hawk_cut_clear (hawk_cut_t* cut)
|
||
|
{
|
||
|
free_all_selector_blocks (cut);
|
||
|
if (cut->e.in.flds != cut->e.in.sflds) hawk_cut_freemem(cut, cut->e.in.flds);
|
||
|
cut->e.in.cflds = HAWK_COUNTOF(cut->e.in.sflds);
|
||
|
cut->e.in.flds = cut->e.in.sflds;
|
||
|
|
||
|
hawk_ooecs_clear(&cut->e.in.line);
|
||
|
hawk_ooecs_setcapa(&cut->e.in.line, DFL_LINE_CAPA);
|
||
|
}
|
||
|
|
||
|
int hawk_cut_comp (hawk_cut_t* cut, const hawk_ooch_t* str, hawk_oow_t len)
|
||
|
{
|
||
|
const hawk_ooch_t* p = str;
|
||
|
const hawk_ooch_t* xnd = str + len;
|
||
|
hawk_ooci_t c;
|
||
|
int sel = HAWK_SED_SEL_CHAR;
|
||
|
|
||
|
#define CC(x,y) (((x) <= (y))? ((hawk_ooci_t)*(x)): HAWK_OOCI_EOF)
|
||
|
#define NC(x,y) (((x) < (y))? ((hawk_ooci_t)*(++(x))): HAWK_OOCI_EOF)
|
||
|
#define EOF(x) ((x) == HAWK_OOCI_EOF)
|
||
|
#define MASK_START (1 << 1)
|
||
|
#define MASK_END (1 << 2)
|
||
|
#define MAX HAWK_TYPE_MAX(hawk_oow_t)
|
||
|
|
||
|
/* free selector blocks compiled previously */
|
||
|
free_all_selector_blocks (cut);
|
||
|
|
||
|
/* set the default delimiters */
|
||
|
cut->sel.din = HAWK_T(' ');
|
||
|
cut->sel.dout = HAWK_T(' ');
|
||
|
|
||
|
/* if the selector string is empty, don't need to proceed */
|
||
|
if (len <= 0) return 0;
|
||
|
|
||
|
/* compile the selector string */
|
||
|
xnd--; c = CC (p, xnd);
|
||
|
while (1)
|
||
|
{
|
||
|
hawk_oow_t start = 0, end = 0;
|
||
|
int mask = 0;
|
||
|
|
||
|
while (hawk_is_ooch_space(c)) c = NC(p, xnd);
|
||
|
if (EOF(c))
|
||
|
{
|
||
|
if (cut->sel.count > 0)
|
||
|
{
|
||
|
SETERR0 (cut, HAWK_CUT_ESELNV);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (c == HAWK_T('d'))
|
||
|
{
|
||
|
/* the next character is the input delimiter.
|
||
|
* the output delimiter defaults to the input
|
||
|
* delimiter. */
|
||
|
c = NC(p, xnd);
|
||
|
if (EOF(c))
|
||
|
{
|
||
|
SETERR0 (cut, HAWK_CUT_ESELNV);
|
||
|
return -1;
|
||
|
}
|
||
|
cut->sel.din = c;
|
||
|
cut->sel.dout = c;
|
||
|
|
||
|
c = NC(p, xnd);
|
||
|
}
|
||
|
else if (c == HAWK_T('D'))
|
||
|
{
|
||
|
/* the next two characters are the input and
|
||
|
* the output delimiter each. */
|
||
|
c = NC(p, xnd);
|
||
|
if (EOF(c))
|
||
|
{
|
||
|
SETERR0 (cut, HAWK_CUT_ESELNV);
|
||
|
return -1;
|
||
|
}
|
||
|
cut->sel.din = c;
|
||
|
|
||
|
c = NC(p, xnd);
|
||
|
if (EOF(c))
|
||
|
{
|
||
|
SETERR0 (cut, HAWK_CUT_ESELNV);
|
||
|
return -1;
|
||
|
}
|
||
|
cut->sel.dout = c;
|
||
|
|
||
|
c = NC(p, xnd);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (c == HAWK_T('c') || c == HAWK_T('f'))
|
||
|
{
|
||
|
sel = c;
|
||
|
c = NC(p, xnd);
|
||
|
while (hawk_is_ooch_space(c)) c = NC(p, xnd);
|
||
|
}
|
||
|
|
||
|
if (hawk_is_ooch_digit(c))
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
start = start * 10 + (c - HAWK_T('0'));
|
||
|
c = NC(p, xnd);
|
||
|
}
|
||
|
while (hawk_is_ooch_digit(c));
|
||
|
|
||
|
while (hawk_is_ooch_space(c)) c = NC(p, xnd);
|
||
|
mask |= MASK_START;
|
||
|
}
|
||
|
else start++;
|
||
|
|
||
|
if (c == HAWK_T('-'))
|
||
|
{
|
||
|
c = NC(p, xnd);
|
||
|
while (hawk_is_ooch_space(c)) c = NC(p, xnd);
|
||
|
|
||
|
if (hawk_is_ooch_digit(c))
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
end = end * 10 + (c - HAWK_T('0'));
|
||
|
c = NC(p, xnd);
|
||
|
}
|
||
|
while (hawk_is_ooch_digit(c));
|
||
|
mask |= MASK_END;
|
||
|
}
|
||
|
else end = MAX;
|
||
|
|
||
|
while (hawk_is_ooch_space(c)) c = NC(p, xnd);
|
||
|
}
|
||
|
else end = start;
|
||
|
|
||
|
if (!(mask & (MASK_START | MASK_END)))
|
||
|
{
|
||
|
SETERR0 (cut, HAWK_CUT_ESELNV);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (cut->sel.lb->len >= HAWK_COUNTOF(cut->sel.lb->range))
|
||
|
{
|
||
|
if (add_selector_block (cut) <= -1)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cut->sel.lb->range[cut->sel.lb->len].id = sel;
|
||
|
cut->sel.lb->range[cut->sel.lb->len].start = start;
|
||
|
cut->sel.lb->range[cut->sel.lb->len].end = end;
|
||
|
cut->sel.lb->len++;
|
||
|
cut->sel.count++;
|
||
|
if (sel == HAWK_SED_SEL_FIELD) cut->sel.fcount++;
|
||
|
else cut->sel.ccount++;
|
||
|
}
|
||
|
|
||
|
if (EOF(c)) break;
|
||
|
if (c == HAWK_T(',')) c = NC(p, xnd);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int read_char (hawk_cut_t* cut, hawk_ooch_t* c)
|
||
|
{
|
||
|
hawk_ooi_t n;
|
||
|
|
||
|
if (cut->e.in.pos >= cut->e.in.len)
|
||
|
{
|
||
|
n = cut->e.in.fun(cut, HAWK_CUT_IO_READ, &cut->e.in.arg, cut->e.in.buf, HAWK_COUNTOF(cut->e.in.buf));
|
||
|
if (n <= -1) return -1;
|
||
|
if (n == 0) return 0; /* end of file */
|
||
|
|
||
|
cut->e.in.len = n;
|
||
|
cut->e.in.pos = 0;
|
||
|
}
|
||
|
|
||
|
*c = cut->e.in.buf[cut->e.in.pos++];
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int read_line (hawk_cut_t* cut)
|
||
|
{
|
||
|
hawk_oow_t len = 0;
|
||
|
hawk_ooch_t c;
|
||
|
int n;
|
||
|
|
||
|
hawk_ooecs_clear(&cut->e.in.line);
|
||
|
if (cut->e.in.eof) return 0;
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
n = read_char(cut, &c);
|
||
|
if (n <= -1) return -1;
|
||
|
if (n == 0)
|
||
|
{
|
||
|
cut->e.in.eof = 1;
|
||
|
if (len == 0) return 0;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (c == HAWK_T('\n'))
|
||
|
{
|
||
|
/* don't include the line terminater to a line */
|
||
|
/* TODO: support different line end convension */
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (hawk_ooecs_ccat(&cut->e.in.line, c) == (hawk_oow_t)-1) return -1;
|
||
|
len++;
|
||
|
}
|
||
|
|
||
|
cut->e.in.num++;
|
||
|
|
||
|
if (cut->option & HAWK_CUT_TRIMSPACE) hawk_ooecs_trim(&cut->e.in.line, HAWK_TRIM_LEFT | HAWK_TRIM_RIGHT);
|
||
|
if (cut->option & HAWK_CUT_NORMSPACE) hawk_ooecs_compact(&cut->e.in.line);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int flush (hawk_cut_t* cut)
|
||
|
{
|
||
|
hawk_oow_t pos = 0;
|
||
|
hawk_ooi_t n;
|
||
|
|
||
|
while (cut->e.out.len > 0)
|
||
|
{
|
||
|
n = cut->e.out.fun(cut, HAWK_CUT_IO_WRITE, &cut->e.out.arg, &cut->e.out.buf[pos], cut->e.out.len);
|
||
|
if (n <= -1) return -1;
|
||
|
if (n == 0) return -1; /* reached the end of file - this is also an error */
|
||
|
|
||
|
pos += n;
|
||
|
cut->e.out.len -= n;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int write_char (hawk_cut_t* cut, hawk_ooch_t c)
|
||
|
{
|
||
|
cut->e.out.buf[cut->e.out.len++] = c;
|
||
|
if (c == HAWK_T('\n') || cut->e.out.len >= HAWK_COUNTOF(cut->e.out.buf)) return flush(cut);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int write_linebreak (hawk_cut_t* cut)
|
||
|
{
|
||
|
/* TODO: different line termination convention */
|
||
|
return write_char(cut, HAWK_T('\n'));
|
||
|
}
|
||
|
|
||
|
static int write_str (hawk_cut_t* cut, const hawk_ooch_t* str, hawk_oow_t len)
|
||
|
{
|
||
|
hawk_oow_t i;
|
||
|
|
||
|
for (i = 0; i < len; i++)
|
||
|
{
|
||
|
if (write_char(cut, str[i]) <= -1) return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int cut_chars (hawk_cut_t* cut, hawk_oow_t start, hawk_oow_t end, int delim)
|
||
|
{
|
||
|
const hawk_ooch_t* ptr = HAWK_OOECS_PTR(&cut->e.in.line);
|
||
|
hawk_oow_t len = HAWK_OOECS_LEN(&cut->e.in.line);
|
||
|
|
||
|
if (len <= 0) return 0;
|
||
|
|
||
|
if (start <= end)
|
||
|
{
|
||
|
if (start <= len && end > 0)
|
||
|
{
|
||
|
if (start >= 1) start--;
|
||
|
if (end >= 1) end--;
|
||
|
|
||
|
if (end >= len) end = len - 1;
|
||
|
|
||
|
if (delim && write_char(cut, cut->sel.dout) <= -1) return -1;
|
||
|
if (write_str(cut, &ptr[start], end-start+1) <= -1) return -1;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (start > 0 && end <= len)
|
||
|
{
|
||
|
hawk_oow_t i;
|
||
|
|
||
|
if (start >= 1) start--;
|
||
|
if (end >= 1) end--;
|
||
|
|
||
|
if (start >= len) start = len - 1;
|
||
|
|
||
|
if (delim && write_char (cut, cut->sel.dout) <= -1)
|
||
|
return -1;
|
||
|
|
||
|
for (i = start; i >= end; i--)
|
||
|
{
|
||
|
if (write_char (cut, ptr[i]) <= -1)
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int isdelim (hawk_cut_t* cut, hawk_ooch_t c)
|
||
|
{
|
||
|
return ((cut->option & HAWK_CUT_WHITESPACE) && hawk_is_ooch_space(c)) ||
|
||
|
(!(cut->option & HAWK_CUT_WHITESPACE) && c == cut->sel.din);
|
||
|
}
|
||
|
|
||
|
static int split_line (hawk_cut_t* cut)
|
||
|
{
|
||
|
const hawk_ooch_t* ptr = HAWK_OOECS_PTR(&cut->e.in.line);
|
||
|
hawk_oow_t len = HAWK_OOECS_LEN(&cut->e.in.line);
|
||
|
hawk_oow_t i, x = 0, xl = 0;
|
||
|
|
||
|
cut->e.in.delimited = 0;
|
||
|
cut->e.in.flds[x].ptr = ptr;
|
||
|
for (i = 0; i < len; )
|
||
|
{
|
||
|
hawk_ooch_t c = ptr[i++];
|
||
|
if (isdelim(cut,c))
|
||
|
{
|
||
|
if (cut->option & HAWK_CUT_FOLDDELIMS)
|
||
|
{
|
||
|
while (i < len && isdelim(cut,ptr[i])) i++;
|
||
|
}
|
||
|
|
||
|
cut->e.in.flds[x++].len = xl;
|
||
|
|
||
|
if (x >= cut->e.in.cflds)
|
||
|
{
|
||
|
hawk_oocs_t* tmp;
|
||
|
hawk_oow_t nsz;
|
||
|
|
||
|
nsz = cut->e.in.cflds;
|
||
|
if (nsz > 100000) nsz += 100000;
|
||
|
else nsz *= 2;
|
||
|
|
||
|
tmp = hawk_cut_allocmem(cut, HAWK_SIZEOF(*tmp) * nsz);
|
||
|
if (HAWK_UNLIKELY(!tmp)) return -1;
|
||
|
|
||
|
HAWK_MEMCPY (tmp, cut->e.in.flds, HAWK_SIZEOF(*tmp) * cut->e.in.cflds);
|
||
|
|
||
|
if (cut->e.in.flds != cut->e.in.sflds) hawk_cut_freemem(cut, cut->e.in.flds);
|
||
|
cut->e.in.flds = tmp;
|
||
|
cut->e.in.cflds = nsz;
|
||
|
}
|
||
|
|
||
|
xl = 0;
|
||
|
cut->e.in.flds[x].ptr = &ptr[i];
|
||
|
cut->e.in.delimited = 1;
|
||
|
}
|
||
|
else xl++;
|
||
|
}
|
||
|
cut->e.in.flds[x].len = xl;
|
||
|
cut->e.in.nflds = ++x;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int cut_fields (hawk_cut_t* cut, hawk_oow_t start, hawk_oow_t end, int delim)
|
||
|
{
|
||
|
hawk_oow_t len = cut->e.in.nflds;
|
||
|
|
||
|
if (!cut->e.in.delimited /*|| len <= 0*/) return 0;
|
||
|
|
||
|
HAWK_ASSERT (len > 0);
|
||
|
if (start <= end)
|
||
|
{
|
||
|
if (start <= len && end > 0)
|
||
|
{
|
||
|
hawk_oow_t i;
|
||
|
|
||
|
if (start >= 1) start--;
|
||
|
if (end >= 1) end--;
|
||
|
|
||
|
if (end >= len) end = len - 1;
|
||
|
|
||
|
if (delim && write_char(cut, cut->sel.dout) <= -1) return -1;
|
||
|
|
||
|
for (i = start; i <= end; i++)
|
||
|
{
|
||
|
if (write_str(cut, cut->e.in.flds[i].ptr, cut->e.in.flds[i].len) <= -1) return -1;
|
||
|
if (i < end && write_char(cut, cut->sel.dout) <= -1) return -1;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (start > 0 && end <= len)
|
||
|
{
|
||
|
hawk_oow_t i;
|
||
|
|
||
|
if (start >= 1) start--;
|
||
|
if (end >= 1) end--;
|
||
|
|
||
|
if (start >= len) start = len - 1;
|
||
|
|
||
|
if (delim && write_char (cut, cut->sel.dout) <= -1)
|
||
|
return -1;
|
||
|
|
||
|
for (i = start; i >= end; i--)
|
||
|
{
|
||
|
if (write_str(cut, cut->e.in.flds[i].ptr, cut->e.in.flds[i].len) <= -1) return -1;
|
||
|
if (i > end && write_char (cut, cut->sel.dout) <= -1) return -1;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int hawk_cut_exec (hawk_cut_t* cut, hawk_cut_io_impl_t inf, hawk_cut_io_impl_t outf)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
hawk_ooi_t n;
|
||
|
|
||
|
cut->e.out.fun = outf;
|
||
|
cut->e.out.eof = 0;
|
||
|
cut->e.out.len = 0;
|
||
|
|
||
|
cut->e.in.fun = inf;
|
||
|
cut->e.in.eof = 0;
|
||
|
cut->e.in.len = 0;
|
||
|
cut->e.in.pos = 0;
|
||
|
cut->e.in.num = 0;
|
||
|
|
||
|
n = cut->e.in.fun(cut, HAWK_CUT_IO_OPEN, &cut->e.in.arg, HAWK_NULL, 0);
|
||
|
if (n <= -1)
|
||
|
{
|
||
|
ret = -1;
|
||
|
goto done3;
|
||
|
}
|
||
|
if (n == 0)
|
||
|
{
|
||
|
/* EOF reached upon opening an input stream.
|
||
|
* no data to process. this is success */
|
||
|
goto done2;
|
||
|
}
|
||
|
|
||
|
n = cut->e.out.fun (cut, HAWK_CUT_IO_OPEN, &cut->e.out.arg, HAWK_NULL, 0);
|
||
|
if (n <= -1)
|
||
|
{
|
||
|
ret = -1;
|
||
|
goto done2;
|
||
|
}
|
||
|
if (n == 0)
|
||
|
{
|
||
|
/* still don't know if we will write something.
|
||
|
* just mark EOF on the output stream and continue */
|
||
|
cut->e.out.eof = 1;
|
||
|
}
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
hawk_cut_sel_blk_t* b;
|
||
|
int id = 0; /* mark 'no output' so far */
|
||
|
int delimited = 0;
|
||
|
int linebreak = 0;
|
||
|
|
||
|
n = read_line (cut);
|
||
|
if (n <= -1) { ret = -1; goto done; }
|
||
|
if (n == 0) goto done;
|
||
|
|
||
|
if (cut->sel.fcount > 0)
|
||
|
{
|
||
|
if (split_line (cut) <= -1) { ret = -1; goto done; }
|
||
|
delimited = cut->e.in.delimited;
|
||
|
}
|
||
|
|
||
|
for (b = &cut->sel.fb; b != HAWK_NULL; b = b->next)
|
||
|
{
|
||
|
hawk_oow_t i;
|
||
|
|
||
|
for (i = 0; i < b->len; i++)
|
||
|
{
|
||
|
if (b->range[i].id == HAWK_SED_SEL_CHAR)
|
||
|
{
|
||
|
n = cut_chars (
|
||
|
cut,
|
||
|
b->range[i].start,
|
||
|
b->range[i].end,
|
||
|
id == 2
|
||
|
);
|
||
|
if (n >= 1)
|
||
|
{
|
||
|
/* mark a char's been output */
|
||
|
id = 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
n = cut_fields (
|
||
|
cut,
|
||
|
b->range[i].start,
|
||
|
b->range[i].end,
|
||
|
id > 0
|
||
|
);
|
||
|
if (n >= 1)
|
||
|
{
|
||
|
/* mark a field's been output */
|
||
|
id = 2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (n <= -1) { ret = -1; goto done; }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cut->sel.ccount > 0)
|
||
|
{
|
||
|
/* so long as there is a character selector,
|
||
|
* a newline must be printed */
|
||
|
linebreak = 1;
|
||
|
}
|
||
|
else if (cut->sel.fcount > 0)
|
||
|
{
|
||
|
/* if only field selectors are specified */
|
||
|
|
||
|
if (delimited)
|
||
|
{
|
||
|
/* and if the input line is delimited,
|
||
|
* write a line break */
|
||
|
linebreak = 1;
|
||
|
}
|
||
|
else if (!(cut->option & HAWK_CUT_DELIMONLY))
|
||
|
{
|
||
|
/* if not delimited, write the
|
||
|
* entire undelimited input line depending
|
||
|
* on the option set. */
|
||
|
if (write_str(cut, HAWK_OOECS_PTR(&cut->e.in.line), HAWK_OOECS_LEN(&cut->e.in.line)) <= -1)
|
||
|
{
|
||
|
ret = -1; goto done;
|
||
|
}
|
||
|
|
||
|
/* a line break is needed in this case */
|
||
|
linebreak = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (linebreak && write_linebreak(cut) <= -1)
|
||
|
{
|
||
|
ret = -1; goto done;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
done:
|
||
|
cut->e.out.fun (cut, HAWK_CUT_IO_CLOSE, &cut->e.out.arg, HAWK_NULL, 0);
|
||
|
done2:
|
||
|
cut->e.in.fun (cut, HAWK_CUT_IO_CLOSE, &cut->e.in.arg, HAWK_NULL, 0);
|
||
|
done3:
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* -------------------------------------- */
|
||
|
|
||
|
void* hawk_cut_allocmem (hawk_cut_t* cut, hawk_oow_t size)
|
||
|
{
|
||
|
void* ptr = HAWK_MMGR_ALLOC(hawk_cut_getmmgr(cut), size);
|
||
|
if (HAWK_UNLIKELY(!ptr)) hawk_cut_seterrnum(cut, HAWK_NULL, HAWK_ENOMEM);
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
void* hawk_cut_callocmem (hawk_cut_t* cut, hawk_oow_t size)
|
||
|
{
|
||
|
void* ptr = HAWK_MMGR_ALLOC(hawk_cut_getmmgr(cut), size);
|
||
|
if (HAWK_LIKELY(ptr)) HAWK_MEMSET(ptr, 0, size);
|
||
|
else hawk_cut_seterrnum(cut, HAWK_NULL, HAWK_ENOMEM);
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
void* hawk_cut_reallocmem (hawk_cut_t* cut, void* ptr, hawk_oow_t size)
|
||
|
{
|
||
|
void* nptr = HAWK_MMGR_REALLOC(hawk_cut_getmmgr(cut), ptr, size);
|
||
|
if (HAWK_UNLIKELY(!nptr)) hawk_cut_seterrnum(cut, HAWK_NULL, HAWK_ENOMEM);
|
||
|
return nptr;
|
||
|
}
|
||
|
|
||
|
void hawk_cut_freemem (hawk_cut_t* cut, void* ptr)
|
||
|
{
|
||
|
HAWK_MMGR_FREE(hawk_cut_getmmgr(cut), ptr);
|
||
|
}
|