📄 bdf.c
字号:
FT_FREE( list->field );
FT_ZERO( list );
}
}
static FT_Error
_bdf_list_ensure( _bdf_list_t* list,
int num_items )
{
FT_Error error = BDF_Err_Ok;
if ( num_items > (int)list->size )
{
int oldsize = list->size;
int newsize = oldsize + ( oldsize >> 1 ) + 4;
int bigsize = FT_INT_MAX / sizeof ( char* );
FT_Memory memory = list->memory;
if ( oldsize == bigsize )
{
error = BDF_Err_Out_Of_Memory;
goto Exit;
}
else if ( newsize < oldsize || newsize > bigsize )
newsize = bigsize;
if ( FT_RENEW_ARRAY( list->field, oldsize, newsize ) )
goto Exit;
list->size = newsize;
}
Exit:
return error;
}
static void
_bdf_list_shift( _bdf_list_t* list,
unsigned long n )
{
unsigned long i, u;
if ( list == 0 || list->used == 0 || n == 0 )
return;
if ( n >= list->used )
{
list->used = 0;
return;
}
for ( u = n, i = 0; u < list->used; i++, u++ )
list->field[i] = list->field[u];
list->used -= n;
}
static char *
_bdf_list_join( _bdf_list_t* list,
int c,
unsigned long *alen )
{
unsigned long i, j;
char *fp, *dp;
*alen = 0;
if ( list == 0 || list->used == 0 )
return 0;
dp = list->field[0];
for ( i = j = 0; i < list->used; i++ )
{
fp = list->field[i];
while ( *fp )
dp[j++] = *fp++;
if ( i + 1 < list->used )
dp[j++] = (char)c;
}
dp[j] = 0;
*alen = j;
return dp;
}
/* An empty string for empty fields. */
static const char empty[1] = { 0 }; /* XXX eliminate this */
static FT_Error
_bdf_list_split( _bdf_list_t* list,
char* separators,
char* line,
unsigned long linelen )
{
int mult, final_empty;
char *sp, *ep, *end;
char seps[32];
FT_Error error = BDF_Err_Ok;
/* Initialize the list. */
list->used = 0;
/* If the line is empty, then simply return. */
if ( linelen == 0 || line[0] == 0 )
goto Exit;
/* In the original code, if the `separators' parameter is NULL or */
/* empty, the list is split into individual bytes. We don't need */
/* this, so an error is signaled. */
if ( separators == 0 || *separators == 0 )
{
error = BDF_Err_Invalid_Argument;
goto Exit;
}
/* Prepare the separator bitmap. */
FT_MEM_ZERO( seps, 32 );
/* If the very last character of the separator string is a plus, then */
/* set the `mult' flag to indicate that multiple separators should be */
/* collapsed into one. */
for ( mult = 0, sp = separators; sp && *sp; sp++ )
{
if ( *sp == '+' && *( sp + 1 ) == 0 )
mult = 1;
else
setsbit( seps, *sp );
}
/* Break the line up into fields. */
for ( final_empty = 0, sp = ep = line, end = sp + linelen;
sp < end && *sp; )
{
/* Collect everything that is not a separator. */
for ( ; *ep && !sbitset( seps, *ep ); ep++ )
;
/* Resize the list if necessary. */
if ( list->used == list->size )
{
error = _bdf_list_ensure( list, list->used + 1 );
if ( error )
goto Exit;
}
/* Assign the field appropriately. */
list->field[list->used++] = ( ep > sp ) ? sp : (char*)empty;
sp = ep;
if ( mult )
{
/* If multiple separators should be collapsed, do it now by */
/* setting all the separator characters to 0. */
for ( ; *ep && sbitset( seps, *ep ); ep++ )
*ep = 0;
}
else if ( *ep != 0 )
/* Don't collapse multiple separators by making them 0, so just */
/* make the one encountered 0. */
*ep++ = 0;
final_empty = ( ep > sp && *ep == 0 );
sp = ep;
}
/* Finally, NULL-terminate the list. */
if ( list->used + final_empty >= list->size )
{
error = _bdf_list_ensure( list, list->used + final_empty + 1 );
if ( error )
goto Exit;
}
if ( final_empty )
list->field[list->used++] = (char*)empty;
list->field[list->used] = 0;
Exit:
return error;
}
#define NO_SKIP 256 /* this value cannot be stored in a 'char' */
static FT_Error
_bdf_readstream( FT_Stream stream,
_bdf_line_func_t callback,
void* client_data,
unsigned long *lno )
{
_bdf_line_func_t cb;
unsigned long lineno, buf_size;
int refill, bytes, hold, to_skip;
int start, end, cursor, avail;
char* buf = 0;
FT_Memory memory = stream->memory;
FT_Error error = BDF_Err_Ok;
if ( callback == 0 )
{
error = BDF_Err_Invalid_Argument;
goto Exit;
}
/* initial size and allocation of the input buffer */
buf_size = 1024;
if ( FT_NEW_ARRAY( buf, buf_size ) )
goto Exit;
cb = callback;
lineno = 1;
buf[0] = 0;
start = 0;
end = 0;
avail = 0;
cursor = 0;
refill = 1;
to_skip = NO_SKIP;
bytes = 0; /* make compiler happy */
for (;;)
{
if ( refill )
{
bytes = (int)FT_Stream_TryRead( stream, (FT_Byte*)buf + cursor,
(FT_ULong)(buf_size - cursor) );
avail = cursor + bytes;
cursor = 0;
refill = 0;
}
end = start;
/* should we skip an optional character like \n or \r? */
if ( start < avail && buf[start] == to_skip )
{
start += 1;
to_skip = NO_SKIP;
continue;
}
/* try to find the end of the line */
while ( end < avail && buf[end] != '\n' && buf[end] != '\r' )
end++;
/* if we hit the end of the buffer, try shifting its content */
/* or even resizing it */
if ( end >= avail )
{
if ( bytes == 0 ) /* last line in file doesn't end in \r or \n */
break; /* ignore it then exit */
if ( start == 0 )
{
/* this line is definitely too long; try resizing the input */
/* buffer a bit to handle it. */
FT_ULong new_size;
if ( buf_size >= 65536UL ) /* limit ourselves to 64KByte */
{
error = BDF_Err_Invalid_Argument;
goto Exit;
}
new_size = buf_size * 2;
if ( FT_RENEW_ARRAY( buf, buf_size, new_size ) )
goto Exit;
cursor = buf_size;
buf_size = new_size;
}
else
{
bytes = avail - start;
FT_MEM_COPY( buf, buf + start, bytes );
cursor = bytes;
avail -= bytes;
start = 0;
}
refill = 1;
continue;
}
/* Temporarily NUL-terminate the line. */
hold = buf[end];
buf[end] = 0;
/* XXX: Use encoding independent value for 0x1a */
if ( buf[start] != '#' && buf[start] != 0x1a && end > start )
{
error = (*cb)( buf + start, end - start, lineno,
(void*)&cb, client_data );
if ( error )
break;
}
lineno += 1;
buf[end] = (char)hold;
start = end + 1;
if ( hold == '\n' )
to_skip = '\r';
else if ( hold == '\r' )
to_skip = '\n';
else
to_skip = NO_SKIP;
}
*lno = lineno;
Exit:
FT_FREE( buf );
return error;
}
/* XXX: make this work with EBCDIC also */
static const unsigned char a2i[128] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char odigits[32] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char ddigits[32] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char hdigits[32] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define isdigok( m, d ) (m[(d) >> 3] & ( 1 << ( (d) & 7 ) ) )
/* Routine to convert an ASCII string into an unsigned long integer. */
static unsigned long
_bdf_atoul( char* s,
char** end,
int base )
{
unsigned long v;
const unsigned char* dmap;
if ( s == 0 || *s == 0 )
return 0;
/* Make sure the radix is something recognizable. Default to 10. */
switch ( base )
{
case 8:
dmap = odigits;
break;
case 16:
dmap = hdigits;
break;
default:
base = 10;
dmap = ddigits;
break;
}
/* Check for the special hex prefix. */
if ( *s == '0' &&
( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )
{
base = 16;
dmap = hdigits;
s += 2;
}
for ( v = 0; isdigok( dmap, *s ); s++ )
v = v * base + a2i[(int)*s];
if ( end != 0 )
*end = s;
return v;
}
/* Routine to convert an ASCII string into an signed long integer. */
static long
_bdf_atol( char* s,
char** end,
int base )
{
long v, neg;
const unsigned char* dmap;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -