home *** CD-ROM | disk | FTP | other *** search
- /*
- *******************************************************************************
- * *
- * COPYRIGHT: *
- * (C) Copyright International Business Machines Corporation, 1998 *
- * Licensed Material - Program-Property of IBM - All Rights Reserved. *
- * US Government Users Restricted Rights - Use, duplication, or disclosure *
- * restricted by GSA ADP Schedule Contract with IBM Corp. *
- * *
- *******************************************************************************
- *
- * File uscanf.c
- *
- * Modification History:
- *
- * Date Name Description
- * 12/02/98 stephen Creation.
- * 03/13/99 stephen Modified for new C API.
- *******************************************************************************
- */
-
- #include "uchar.h"
-
- #include "uscanf.h"
- #include "uscanf_p.h"
- #include "uscanset.h"
- #include "ustdio.h"
- #include "ufile.h"
- #include "ustring.h"
- #include "locbund.h"
- #include "umutex.h"
- #include "unum.h"
- #include "udat.h"
-
- #include <string.h>
- #include <stdlib.h>
- #include <float.h>
- #include <limits.h>
- #include <wchar.h>
-
-
- u_scanf_handler g_u_scanf_handlers [256];
- u_scanf_info g_u_scanf_infos [256];
- bool_t g_u_scanf_inited = FALSE;
-
- int32_t
- u_fscanf( UFILE *f,
- const char *patternSpecification,
- ... )
- {
- va_list ap;
- int32_t converted;
-
- va_start(ap, patternSpecification);
- converted = u_vfscanf(f, patternSpecification, ap);
- va_end(ap);
-
- return converted;
- }
-
- int32_t
- u_fscanf_u( UFILE *f,
- const UChar *patternSpecification,
- ... )
- {
- va_list ap;
- int32_t converted;
-
- va_start(ap, patternSpecification);
- converted = u_vfscanf_u(f, patternSpecification, ap);
- va_end(ap);
-
- return converted;
- }
-
- int32_t
- u_vfscanf( UFILE *f,
- const char *patternSpecification,
- va_list ap)
- {
- int32_t converted;
- UChar *pattern;
-
- /* convert from the default codepage to Unicode */
- pattern = ufmt_defaultCPToUnicode(patternSpecification,
- strlen(patternSpecification));
- if(pattern == 0) {
- return 0;
- }
-
- /* do the work */
- converted = u_vfscanf_u(f, pattern, ap);
-
- /* clean up */
- free(pattern);
-
- return converted;
- }
-
- int32_t
- u_scanf_register_handler (UChar spec,
- u_scanf_info info,
- u_scanf_handler handler)
- {
- /* lock the cache */
- umtx_lock(0);
-
- /* add to our list of function pointers */
- g_u_scanf_infos[ (unsigned char) spec ] = info;
- g_u_scanf_handlers[ (unsigned char) spec ] = handler;
-
- /* unlock the cache */
- umtx_unlock(0);
- return 0;
- }
-
- int32_t
- u_scanf_skip_leading_ws(UFILE *stream,
- UChar pad)
- {
- UChar c;
- int32_t count = 0;
-
- /* skip all leading ws in the stream */
- while( ((c = u_fgetc(stream)) != 0xFFFF) && (c == pad || ufmt_isws(c)) )
- ++count;
-
- /* put the final character back on the stream */
- if(c != 0xFFFF)
- u_fungetc(c, stream);
-
- return count;
- }
-
- int32_t
- u_scanf_simple_percent_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* we don't need any arguments */
- return 0;
- }
-
- int32_t
- u_scanf_simple_percent_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- /* make sure the next character in the stream is a percent */
- if(u_fgetc(stream) != 0x0025)
- return -1;
- else
- return 0;
- }
-
- int32_t
- u_scanf_string_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type string */
- argtypes[0] = ufmt_string;
- return 1;
- }
-
- int32_t
- u_scanf_string_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- UChar c;
- int32_t count;
- const UChar *source;
- UConverter *conv;
- UErrorCode status = U_ZERO_ERROR;
- char *arg = (char*)(args[0].ptrValue);
- char *alias = arg;
- char *limit;
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* get the string one character at a time, truncating to the width */
- count = 0;
-
- /* open the default converter */
- conv = ucnv_open(ucnv_getDefaultName(), &status);
-
- if(U_FAILURE(status))
- return -1;
-
- /* since there is no real limit, just use a reasonable value */
- limit = alias + 2048;
-
- while( ((c = u_fgetc(stream)) != 0xFFFF) &&
- (c != info->fPadChar && ! ufmt_isws(c)) &&
- (info->fWidth == -1 || count < info->fWidth) ) {
-
- /* put the character from the stream onto the target */
- source = &c;
-
- /* convert the character to the default codepage */
- ucnv_fromUnicode(conv, &alias, limit, &source, source + 1,
- NULL, TRUE, &status);
-
- if(U_FAILURE(status))
- return -1;
-
- /* increment the count */
- ++count;
- }
-
- /* put the final character we read back on the stream */
- if(c != 0xFFFF)
- u_fungetc(c, stream);
-
- /* add the terminator */
- *alias = 0x00;
-
- /* clean up */
- ucnv_close(conv);
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_ustring_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type ustring */
- argtypes[0] = ufmt_ustring;
- return 1;
- }
-
- int32_t
- u_scanf_ustring_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- UChar c;
- int32_t count;
- UChar *arg = (UChar*)(args[0].ptrValue);
- UChar *alias = arg;
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* get the string one character at a time, truncating to the width */
- count = 0;
-
- while( ((c = u_fgetc(stream)) != 0xFFFF) &&
- (c != info->fPadChar && ! ufmt_isws(c)) &&
- (info->fWidth == -1 || count < info->fWidth) ) {
-
- /* put the character from the stream onto the target */
- *alias++ = c;
-
- /* increment the count */
- ++count;
- }
-
- /* put the final character we read back on the stream */
- if(c != 0xFFFF)
- u_fungetc(c, stream);
-
- /* add the terminator */
- *alias = 0x0000;
-
- /* we converted 1 arg */
- return 1;
- }
-
-
- int32_t
- u_scanf_count_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type count */
- argtypes[0] = ufmt_count;
- return 1;
- }
-
- int32_t
- u_scanf_count_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int *converted = (int*)(args[0].ptrValue);
-
- /* in the special case of count, the u_scanf_spec_info's width */
- /* will contain the # of items converted thus far */
- *converted = info->fWidth;
-
- /* we converted 0 args */
- return 0;
- }
-
- int32_t
- u_scanf_integer_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type int */
- argtypes[0] = ufmt_int;
- return 1;
- }
-
- int32_t
- u_scanf_integer_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- long *num = (long*) (args[0].ptrValue);
- UNumberFormat *format;
- int32_t parsePos = 0;
- UErrorCode status = U_ZERO_ERROR;
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* get the formatter */
- format = u_locbund_getNumberFormat(stream->fBundle);
-
- /* handle error */
- if(format == 0)
- return 0;
-
- /* parse the number */
- *num = unum_parse(format, stream->fUCPos, len, &parsePos, &status);
-
- /* mask off any necessary bits */
- if(info->fIsShort)
- *num &= SHRT_MAX;
- else if(! info->fIsLong || ! info->fIsLongLong)
- *num &= INT_MAX;
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += parsePos;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_double_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type double */
- argtypes[0] = ufmt_double;
- return 1;
- }
-
- int32_t
- u_scanf_double_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- double *num = (double*) (args[0].ptrValue);
- UNumberFormat *format;
- int32_t parsePos = 0;
- UErrorCode status = U_ZERO_ERROR;
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* get the formatter */
- format = u_locbund_getNumberFormat(stream->fBundle);
-
- /* handle error */
- if(format == 0)
- return 0;
-
- /* parse the number */
- *num = unum_parseDouble(format, stream->fUCPos, len, &parsePos, &status);
-
- /* mask off any necessary bits */
- /* if(! info->fIsLong_double)
- num &= DBL_MAX;*/
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += parsePos;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_scientific_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type double */
- argtypes[0] = ufmt_double;
- return 1;
- }
-
- int32_t
- u_scanf_scientific_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- double *num = (double*) (args[0].ptrValue);
- UNumberFormat *format;
- int32_t parsePos = 0;
- UErrorCode status = U_ZERO_ERROR;
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* get the formatter */
- format = u_locbund_getScientificFormat(stream->fBundle);
-
- /* handle error */
- if(format == 0)
- return 0;
-
- /* parse the number */
- *num = unum_parseDouble(format, stream->fUCPos, len, &parsePos, &status);
-
- /* mask off any necessary bits */
- /* if(! info->fIsLong_double)
- num &= DBL_MAX;*/
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += parsePos;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_scidbl_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type double */
- argtypes[0] = ufmt_double;
- return 1;
- }
-
- int32_t
- u_scanf_scidbl_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- double *num = (double*) (args[0].ptrValue);
- UNumberFormat *scientificFormat, *genericFormat;
- int32_t scientificResult, genericResult;
- int32_t scientificParsePos = 0, genericParsePos = 0;
- UErrorCode scientificStatus = U_ZERO_ERROR;
- UErrorCode genericStatus = U_ZERO_ERROR;
- bool_t useScientific;
-
-
- /* since we can't determine by scanning the characters whether */
- /* a number was formatted in the 'f' or 'g' styles, parse the */
- /* string with both formatters, and assume whichever one */
- /* parsed the most is the correct formatter to use */
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* get the formatters */
- scientificFormat = u_locbund_getScientificFormat(stream->fBundle);
- genericFormat = u_locbund_getNumberFormat(stream->fBundle);
-
- /* handle error */
- if(scientificFormat == 0 || genericFormat == 0)
- return 0;
-
- /* parse the number using each format*/
-
- scientificResult = unum_parseDouble(scientificFormat, stream->fUCPos, len,
- &scientificParsePos, &scientificStatus);
-
- genericResult = unum_parseDouble(genericFormat, stream->fUCPos, len,
- &genericParsePos, &genericStatus);
-
- /* determine which parse made it farther */
- useScientific = scientificParsePos > genericParsePos;
-
- /* stash the result in num */
- *num = useScientific ? scientificResult : genericResult;
-
- /* mask off any necessary bits */
- /* if(! info->fIsLong_double)
- num &= DBL_MAX;*/
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += useScientific ? scientificParsePos : genericParsePos;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_currency_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type double */
- argtypes[0] = ufmt_double;
- return 1;
- }
-
- int32_t
- u_scanf_currency_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- double *num = (double*) (args[0].ptrValue);
- UNumberFormat *format;
- int32_t parsePos = 0;
- UErrorCode status = U_ZERO_ERROR;
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* get the formatter */
- format = u_locbund_getCurrencyFormat(stream->fBundle);
-
- /* handle error */
- if(format == 0)
- return 0;
-
- /* parse the number */
- *num = unum_parseDouble(format, stream->fUCPos, len, &parsePos, &status);
-
- /* mask off any necessary bits */
- /* if(! info->fIsLong_double)
- num &= DBL_MAX;*/
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += parsePos;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_percent_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type double */
- argtypes[0] = ufmt_double;
- return 1;
- }
-
- int32_t
- u_scanf_percent_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- double *num = (double*) (args[0].ptrValue);
- UNumberFormat *format;
- int32_t parsePos = 0;
- UErrorCode status = U_ZERO_ERROR;
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* get the formatter */
- format = u_locbund_getPercentFormat(stream->fBundle);
-
- /* handle error */
- if(format == 0)
- return 0;
-
- /* parse the number */
- *num = unum_parseDouble(format, stream->fUCPos, len, &parsePos, &status);
-
- /* mask off any necessary bits */
- /* if(! info->fIsLong_double)
- num &= DBL_MAX;*/
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += parsePos;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_date_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type Date */
- argtypes[0] = ufmt_date;
- return 1;
- }
-
- int32_t
- u_scanf_date_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- UDate *date = (UDate*) (args[0].ptrValue);
- UDateFormat *format;
- int32_t parsePos = 0;
- UErrorCode status = U_ZERO_ERROR;
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* get the formatter */
- format = u_locbund_getDateFormat(stream->fBundle);
-
- /* handle error */
- if(format == 0)
- return 0;
-
- /* parse the number */
- *date = udat_parse(format, stream->fUCPos, len, &parsePos, &status);
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += parsePos;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_time_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type Date */
- argtypes[0] = ufmt_date;
- return 1;
- }
-
- int32_t
- u_scanf_time_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- UDate *time = (UDate*) (args[0].ptrValue);
- UDateFormat *format;
- int32_t parsePos = 0;
- UErrorCode status = U_ZERO_ERROR;
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* get the formatter */
- format = u_locbund_getTimeFormat(stream->fBundle);
-
- /* handle error */
- if(format == 0)
- return 0;
-
- /* parse the number */
- *time = udat_parse(format, stream->fUCPos, len, &parsePos, &status);
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += parsePos;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_char_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type char */
- argtypes[0] = ufmt_char;
- return 1;
- }
-
- int32_t
- u_scanf_char_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- UChar uc;
- char *result;
- char *c = (char*)(args[0].ptrValue);
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* get the character from the stream, truncating to the width */
- if(info->fWidth == -1 || info->fWidth > 1)
- uc = u_fgetc(stream);
-
- /* handle EOF */
- if(uc == 0xFFFF)
- return -1;
-
- /* convert the character to the default codepage */
- result = ufmt_unicodeToDefaultCP(&uc, 1);
- *c = result[0];
-
- /* clean up */
- free(result);
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_uchar_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type uchar */
- argtypes[0] = ufmt_uchar;
- return 1;
- }
-
- int32_t
- u_scanf_uchar_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- UChar *c = (UChar*)(args[0].ptrValue);
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* get the character from the stream, truncating to the width */
- if(info->fWidth == -1 || info->fWidth > 1)
- *c = u_fgetc(stream);
-
- /* handle EOF */
- if(*c == 0xFFFF)
- return -1;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_spellout_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type double */
- argtypes[0] = ufmt_double;
- return 1;
- }
-
- int32_t
- u_scanf_spellout_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- double *num = (double*) (args[0].ptrValue);
- UNumberFormat *format;
- int32_t parsePos = 0;
- UErrorCode status = U_ZERO_ERROR;
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* get the formatter */
- format = u_locbund_getSpelloutFormat(stream->fBundle);
-
- /* handle error */
- if(format == 0)
- return 0;
-
- /* parse the number */
- *num = unum_parseDouble(format, stream->fUCPos, len, &parsePos, &status);
-
- /* mask off any necessary bits */
- /* if(! info->fIsLong_double)
- num &= DBL_MAX;*/
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += parsePos;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_hex_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type int */
- argtypes[0] = ufmt_int;
- return 1;
- }
-
- int32_t
- u_scanf_hex_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- long *num = (long*) (args[0].ptrValue);
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* check for alternate form */
- if( *(stream->fUCPos) == 0x0030 &&
- (*(stream->fUCPos + 1) == 0x0078 || *(stream->fUCPos + 1) == 0x0058) ) {
-
- /* skip the '0' and 'x' or 'X' if present */
- stream->fUCPos += 2;
- len -= 2;
- }
-
- /* parse the number */
- *num = ufmt_utol(stream->fUCPos, &len, 16);
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += len;
-
- /* mask off any necessary bits */
- if(info->fIsShort)
- *num &= SHRT_MAX;
- else if(! info->fIsLong || ! info->fIsLongLong)
- *num &= INT_MAX;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_octal_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type int */
- argtypes[0] = ufmt_int;
- return 1;
- }
-
- int32_t
- u_scanf_octal_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- long *num = (long*) (args[0].ptrValue);
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* parse the number */
- *num = ufmt_utol(stream->fUCPos, &len, 8);
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += len;
-
- /* mask off any necessary bits */
- if(info->fIsShort)
- *num &= SHRT_MAX;
- else if(! info->fIsLong || ! info->fIsLongLong)
- *num &= INT_MAX;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_pointer_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type void* */
- argtypes[0] = ufmt_pointer;
- return 1;
- }
-
- int32_t
- u_scanf_pointer_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- int32_t len;
- void *p = (void*)(args[0].ptrValue);
-
-
- /* skip all ws in the stream */
- u_scanf_skip_leading_ws(stream, info->fPadChar);
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* parse the pointer - cast to void** to assign to *p */
- *(void**)p = (void*) ufmt_utol(stream->fUCPos, &len, 16);
-
- /* update the stream's position to reflect consumed data */
- stream->fUCPos += len;
-
- /* we converted 1 arg */
- return 1;
- }
-
- int32_t
- u_scanf_scanset_info(const u_scanf_spec_info *info,
- int32_t *argtypes,
- int32_t n)
- {
- /* handle error */
- if(n < 1)
- return 0;
-
- /* we need 1 argument of type char* */
- argtypes[0] = ufmt_string;
- return 1;
- }
-
- int32_t
- u_scanf_scanset_handler(UFILE *stream,
- const u_scanf_spec_info *info,
- ufmt_args *args,
- const UChar *fmt,
- int32_t *consumed)
- {
- u_scanf_scanset scanset;
- int32_t len;
- bool_t success;
- UChar c;
- const UChar *source;
- UConverter *conv;
- UErrorCode status = U_ZERO_ERROR;
- char *s = (char*) (args[0].ptrValue);
- char *alias, *limit;
-
-
- /* fill the stream's internal buffer */
- ufile_fill_uchar_buffer(stream);
-
- /* determine the size of the stream's buffer */
- len = stream->fUCLimit - stream->fUCPos;
-
- /* truncate to the width, if specified */
- if(info->fWidth != -1)
- len = ufmt_min(len, info->fWidth);
-
- /* alias the target */
- alias = s;
- limit = alias + len;
-
- /* parse the scanset from the fmt string */
- *consumed = u_strlen(fmt);
- success = u_scanf_scanset_init(&scanset, fmt, consumed);
-
- /* increment consumed by one to eat the final ']' */
- ++(*consumed);
-
- /* open the default converter */
- conv = ucnv_open(ucnv_getDefaultName(), &status);
-
- /* verify that the parse was successful and the converter opened */
- if(! success || U_FAILURE(status))
- return -1;
-
- /* grab characters one at a time and make sure they are in the scanset */
- while( (c = u_fgetc(stream)) != 0xFFFF && alias < limit) {
- if(u_scanf_scanset_in(&scanset, c)) {
- source = &c;
- /* convert the character to the default codepage */
- ucnv_fromUnicode(conv, &alias, limit, &source, source + 1,
- NULL, TRUE, &status);
-
- if(U_FAILURE(status))
- return -1;
- }
- /* if the character's not in the scanset, break out */
- else {
- break;
- }
- }
-
- /* put the final character we read back on the stream */
- if(c != 0xFFFF)
- u_fungetc(c, stream);
-
- /* if we didn't match at least 1 character, fail */
- if(alias == s)
- return -1;
- /* otherwise, add the terminator */
- else
- *alias = 0x00;
-
- /* clean up */
- ucnv_close(conv);
-
- /* we converted 1 arg */
- return 1;
- }
-
- void
- u_scanf_init()
- {
- int32_t i;
- /*Mutex *lock;*/
-
- /* if we're already inited, do nothing */
- if(g_u_scanf_inited)
- return;
-
- /* lock the cache */
- umtx_lock(0);
-
- /* if we're already inited, do nothing */
- if(g_u_scanf_inited) {
- umtx_unlock(0);
- return;
- }
-
- /* initialize all handlers and infos to 0 */
- for(i = 0; i < 256; ++i) {
- g_u_scanf_infos[i] = 0;
- g_u_scanf_handlers[i] = 0;
- }
-
- /* register the handlers for standard specifiers */
- /* don't use u_scanf_register_handler to avoid mutex creation */
-
- /* handle '%' */
- g_u_scanf_infos[ 0x0025 ] = u_scanf_simple_percent_info;
- g_u_scanf_handlers[ 0x0025 ] = u_scanf_simple_percent_handler;
-
- /* handle 's' */
- g_u_scanf_infos[ 0x0073 ] = u_scanf_string_info;
- g_u_scanf_handlers[ 0x0073 ] = u_scanf_string_handler;
-
- /* handle 'U' */
- g_u_scanf_infos[ 0x0055 ] = u_scanf_ustring_info;
- g_u_scanf_handlers[ 0x0055 ] = u_scanf_ustring_handler;
-
- /* handle 'n' */
- g_u_scanf_infos[ 0x006E ] = u_scanf_count_info;
- g_u_scanf_handlers[ 0x006E ] = u_scanf_count_handler;
-
- /* handle 'd' */
- g_u_scanf_infos[ 0x0064 ] = u_scanf_integer_info;
- g_u_scanf_handlers[ 0x0064 ] = u_scanf_integer_handler;
-
- /* handle 'i' */
- g_u_scanf_infos[ 0x0069 ] = u_scanf_integer_info;
- g_u_scanf_handlers[ 0x0069 ] = u_scanf_integer_handler;
-
- /* handle 'u' */
- g_u_scanf_infos[ 0x0075 ] = u_scanf_integer_info;
- g_u_scanf_handlers[ 0x0075 ] = u_scanf_integer_handler;
-
- /* handle 'f' */
- g_u_scanf_infos[ 0x0066 ] = u_scanf_double_info;
- g_u_scanf_handlers[ 0x0066 ] = u_scanf_double_handler;
-
- /* handle 'e' */
- g_u_scanf_infos[ 0x0065 ] = u_scanf_scientific_info;
- g_u_scanf_handlers[ 0x0065 ] = u_scanf_scientific_handler;
-
- /* handle 'E' */
- g_u_scanf_infos[ 0x0045 ] = u_scanf_scientific_info;
- g_u_scanf_handlers[ 0x0045 ] = u_scanf_scientific_handler;
-
- /* handle 'g' */
- g_u_scanf_infos[ 0x0067 ] = u_scanf_scidbl_info;
- g_u_scanf_handlers[ 0x0067 ] = u_scanf_scidbl_handler;
-
- /* handle 'G' */
- g_u_scanf_infos[ 0x0047 ] = u_scanf_scidbl_info;
- g_u_scanf_handlers[ 0x0047 ] = u_scanf_scidbl_handler;
-
- /* handle 'M' */
- g_u_scanf_infos[ 0x004D ] = u_scanf_currency_info;
- g_u_scanf_handlers[ 0x004D ] = u_scanf_currency_handler;
-
- /* handle 'P' */
- g_u_scanf_infos[ 0x0050 ] = u_scanf_percent_info;
- g_u_scanf_handlers[ 0x0050 ] = u_scanf_percent_handler;
-
- /* handle 'D' */
- g_u_scanf_infos[ 0x0044 ] = u_scanf_date_info;
- g_u_scanf_handlers[ 0x0044 ] = u_scanf_date_handler;
-
- /* handle 'T' */
- g_u_scanf_infos[ 0x0054 ] = u_scanf_time_info;
- g_u_scanf_handlers[ 0x0054 ] = u_scanf_time_handler;
-
- /* handle 'c' */
- g_u_scanf_infos[ 0x0063 ] = u_scanf_char_info;
- g_u_scanf_handlers[ 0x0063 ] = u_scanf_char_handler;
-
- /* handle 'K' */
- g_u_scanf_infos[ 0x004B ] = u_scanf_uchar_info;
- g_u_scanf_handlers[ 0x004B ] = u_scanf_uchar_handler;
-
- /* handle 'V' */
- g_u_scanf_infos[ 0x0056 ] = u_scanf_spellout_info;
- g_u_scanf_handlers[ 0x0056 ] = u_scanf_spellout_handler;
-
- /* handle 'x' */
- g_u_scanf_infos[ 0x0078 ] = u_scanf_hex_info;
- g_u_scanf_handlers[ 0x0078 ] = u_scanf_hex_handler;
-
- /* handle 'X' */
- g_u_scanf_infos[ 0x0058 ] = u_scanf_hex_info;
- g_u_scanf_handlers[ 0x0058 ] = u_scanf_hex_handler;
-
- /* handle 'o' */
- g_u_scanf_infos[ 0x006F ] = u_scanf_octal_info;
- g_u_scanf_handlers[ 0x006F ] = u_scanf_octal_handler;
-
- /* handle 'p' */
- g_u_scanf_infos[ 0x0070 ] = u_scanf_pointer_info;
- g_u_scanf_handlers[ 0x0070 ] = u_scanf_pointer_handler;
-
- /* handle '[' */
- g_u_scanf_infos[ 0x005B ] = u_scanf_scanset_info;
- g_u_scanf_handlers[ 0x005B ] = u_scanf_scanset_handler;
-
- /* we're finished */
- g_u_scanf_inited = TRUE;
-
- /* unlock the cache */
- umtx_unlock(0);
- }
-
-
- #define U_SCANF_MAX_ARGS 32
- #define UP_PERCENT 0x0025
-
- int32_t
- u_vfscanf_u( UFILE *f,
- const UChar *patternSpecification,
- va_list ap)
- {
- u_scanf_spec spec;
- const UChar *alias;
- int32_t count, converted, temp;
-
- int32_t num_args_wanted;
- int32_t ufmt_types [U_SCANF_MAX_ARGS];
- ufmt_args args [U_SCANF_MAX_ARGS];
-
- u_scanf_info info;
- u_scanf_handler handler;
-
- int32_t cur_arg;
-
-
- /* init our function tables */
- if(! g_u_scanf_inited)
- u_scanf_init();
-
- /* alias the pattern */
- alias = patternSpecification;
-
- /* haven't converted anything yet */
- converted = 0;
-
- /* iterate through the pattern */
- for(;;) {
-
- /* match any characters up to the next '%' */
- while(*alias != UP_PERCENT && *alias != 0x0000 && u_fgetc(f) == *alias) {
- *alias++;
- }
-
- /* if we aren't at a '%', or if we're at end of string, break*/
- if(*alias != UP_PERCENT || *alias == 0x0000)
- break;
-
- /* parse the specifier */
- count = u_scanf_parse_spec(alias, &spec);
-
- /* update the pointer in pattern */
- alias += count;
-
- /* skip the argument, if necessary */
- if(spec.fSkipArg)
- va_arg(ap, int);
-
- /* query the info function for argument information */
- info = g_u_scanf_infos[ (unsigned char) spec.fInfo.fSpec ];
- if(info != 0) {
- num_args_wanted = (*info)(&spec.fInfo,
- ufmt_types,
- U_SCANF_MAX_ARGS);
- }
- else
- num_args_wanted = 0;
-
- /* fill in the requested arguments */
- for(cur_arg = 0;
- cur_arg < num_args_wanted && cur_arg < U_SCANF_MAX_ARGS;
- ++cur_arg) {
-
- switch(ufmt_types[cur_arg]) {
-
- case ufmt_count:
- args[cur_arg].intValue = va_arg(ap, int);
- /* set the spec's width to the # of items converted */
- spec.fInfo.fWidth = converted;
- break;
-
- case ufmt_int:
- args[cur_arg].ptrValue = va_arg(ap, int*);
- break;
-
- case ufmt_char:
- args[cur_arg].ptrValue = va_arg(ap, int*);
- break;
-
- case ufmt_wchar:
- args[cur_arg].ptrValue = va_arg(ap, wchar_t*);
- break;
-
- case ufmt_string:
- args[cur_arg].ptrValue = va_arg(ap, char*);
- break;
-
- case ufmt_wstring:
- args[cur_arg].ptrValue = va_arg(ap, wchar_t*);
- break;
-
- case ufmt_pointer:
- args[cur_arg].ptrValue = va_arg(ap, void*);
- break;
-
- case ufmt_float:
- args[cur_arg].ptrValue = va_arg(ap, float*);
- break;
-
- case ufmt_double:
- args[cur_arg].ptrValue = va_arg(ap, double*);
- break;
-
- case ufmt_date:
- args[cur_arg].ptrValue = va_arg(ap, UDate*);
- break;
-
- case ufmt_ustring:
- args[cur_arg].ptrValue = va_arg(ap, UChar*);
- break;
-
- case ufmt_uchar:
- args[cur_arg].ptrValue = va_arg(ap, int*);
- break;
- }
- }
-
- /* call the handler function */
- handler = g_u_scanf_handlers[ (unsigned char) spec.fInfo.fSpec ];
- if(handler != 0) {
-
- /* reset count */
- count = 0;
-
- temp = (*handler)(f, &spec.fInfo, args, alias, &count);
-
- /* if the handler encountered an error condition, break */
- if(temp == -1)
- break;
-
- /* add to the # of items converted */
- converted += temp;
-
- /* update the pointer in pattern */
- alias += count;
- }
-
- /* just ignore unknown tags */
-
- }
-
- /* return # of items converted */
- return converted;
- }
-
-