⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prscanf.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//*  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape Portable Runtime (NSPR). *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* * Scan functions for NSPR types * * Author: Wan-Teh Chang * * Acknowledgment: The implementation is inspired by the source code * in P.J. Plauger's "The Standard C Library," Prentice-Hall, 1992. */#include <limits.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#ifdef SUNOS4#include "md/sunos4.h"  /* for strtoul */#endif#include "prprf.h"#include "prdtoa.h"#include "prlog.h"#include "prerror.h"/* * A function that reads a character from 'stream'. * Returns the character read, or EOF if end of stream is reached. */typedef int (*_PRGetCharFN)(void *stream);/* * A function that pushes the character 'ch' back to 'stream'. */typedef void (*_PRUngetCharFN)(void *stream, int ch); /* * The size specifier for the integer and floating point number * conversions in format control strings. */typedef enum {    _PR_size_none,  /* No size specifier is given */    _PR_size_h,     /* The 'h' specifier, suggesting "short" */    _PR_size_l,     /* The 'l' specifier, suggesting "long" */    _PR_size_L,     /* The 'L' specifier, meaning a 'long double' */    _PR_size_ll     /* The 'll' specifier, suggesting "long long" */} _PRSizeSpec;/* * The collection of data that is passed between the scan function * and its subordinate functions.  The fields of this structure * serve as the input or output arguments for these functions. */typedef struct {    _PRGetCharFN get;        /* get a character from input stream */    _PRUngetCharFN unget;    /* unget (push back) a character */    void *stream;            /* argument for get and unget */    va_list ap;              /* the variable argument list */    int nChar;               /* number of characters read from 'stream' */    PRBool assign;           /* assign, or suppress assignment? */    int width;               /* field width */    _PRSizeSpec sizeSpec;    /* 'h', 'l', 'L', or 'll' */    PRBool converted;        /* is the value actually converted? */} ScanfState;#define GET(state) ((state)->nChar++, (state)->get((state)->stream))#define UNGET(state, ch) \        ((state)->nChar--, (state)->unget((state)->stream, ch))/* * The following two macros, GET_IF_WITHIN_WIDTH and WITHIN_WIDTH, * are always used together. * * GET_IF_WITHIN_WIDTH calls the GET macro and assigns its return * value to 'ch' only if we have not exceeded the field width of * 'state'.  Therefore, after GET_IF_WITHIN_WIDTH, the value of * 'ch' is valid only if the macro WITHIN_WIDTH evaluates to true. */#define GET_IF_WITHIN_WIDTH(state, ch) \        if (--(state)->width >= 0) { \            (ch) = GET(state); \        }#define WITHIN_WIDTH(state) ((state)->width >= 0)/* * _pr_strtoull: *     Convert a string to an unsigned 64-bit integer.  The string *     'str' is assumed to be a representation of the integer in *     base 'base'. * * Warning:  *     - Only handle base 8, 10, and 16. *     - No overflow checking. */static PRUint64_pr_strtoull(const char *str, char **endptr, int base){    static const int BASE_MAX = 16;    static const char digits[] = "0123456789abcdef";    char *digitPtr;    PRUint64 x;    /* return value */    PRInt64 base64;    const char *cPtr;    PRBool negative;    const char *digitStart;    PR_ASSERT(base == 0 || base == 8 || base == 10 || base == 16);    if (base < 0 || base == 1 || base > BASE_MAX) {        if (endptr) {            *endptr = (char *) str;            return LL_ZERO;        }    }    cPtr = str;    while (isspace(*cPtr)) {        ++cPtr;    }    negative = PR_FALSE;    if (*cPtr == '-') {        negative = PR_TRUE;        cPtr++;    } else if (*cPtr == '+') {        cPtr++;    }    if (base == 16) {        if (*cPtr == '0' && (cPtr[1] == 'x' || cPtr[1] == 'X')) {            cPtr += 2;        }    } else if (base == 0) {        if (*cPtr != '0') {            base = 10;        } else if (cPtr[1] == 'x' || cPtr[1] == 'X') {            base = 16;            cPtr += 2;        } else {            base = 8;        }     }    PR_ASSERT(base != 0);    LL_I2L(base64, base);    digitStart = cPtr;    /* Skip leading zeros */    while (*cPtr == '0') {        cPtr++;    }    LL_I2L(x, 0);    while ((digitPtr = (char*)memchr(digits, tolower(*cPtr), base)) != NULL) {        PRUint64 d;        LL_I2L(d, (digitPtr - digits));        LL_MUL(x, x, base64);        LL_ADD(x, x, d);        cPtr++;    }    if (cPtr == digitStart) {        if (endptr) {            *endptr = (char *) str;        }        return LL_ZERO;    }    if (negative) {#ifdef HAVE_LONG_LONG        /* The cast to a signed type is to avoid a compiler warning */        x = -(PRInt64)x;#else        LL_NEG(x, x);#endif    }    if (endptr) {        *endptr = (char *) cPtr;    }    return x;}/* * The maximum field width (in number of characters) that is enough * (may be more than necessary) to represent a 64-bit integer or * floating point number. */#define FMAX 31#define DECIMAL_POINT '.'static PRStatusGetInt(ScanfState *state, int code){    char buf[FMAX + 1], *p;    int ch;    static const char digits[] = "0123456789abcdefABCDEF";    PRBool seenDigit = PR_FALSE;    int base;    int dlen;    switch (code) {        case 'd': case 'u':            base = 10;            break;        case 'i':            base = 0;            break;        case 'x': case 'X': case 'p':            base = 16;            break;        case 'o':            base = 8;            break;        default:            return PR_FAILURE;    }    if (state->width == 0 || state->width > FMAX) {        state->width = FMAX;    }    p = buf;    GET_IF_WITHIN_WIDTH(state, ch);    if (WITHIN_WIDTH(state) && (ch == '+' || ch == '-')) {        *p++ = ch;        GET_IF_WITHIN_WIDTH(state, ch);    }    if (WITHIN_WIDTH(state) && ch == '0') {        seenDigit = PR_TRUE;        *p++ = ch;        GET_IF_WITHIN_WIDTH(state, ch);        if (WITHIN_WIDTH(state)                && (ch == 'x' || ch == 'X')                && (base == 0 || base == 16)) {            base = 16;            *p++ = ch;            GET_IF_WITHIN_WIDTH(state, ch);        } else if (base == 0) {            base = 8;        }    }    if (base == 0 || base == 10) {        dlen = 10;    } else if (base == 8) {        dlen = 8;    } else {        PR_ASSERT(base == 16);        dlen = 16 + 6; /* 16 digits, plus 6 in uppercase */    }    while (WITHIN_WIDTH(state) && memchr(digits, ch, dlen)) {        *p++ = ch;        GET_IF_WITHIN_WIDTH(state, ch);        seenDigit = PR_TRUE;    }    if (WITHIN_WIDTH(state)) {        UNGET(state, ch);    }    if (!seenDigit) {        return PR_FAILURE;    }    *p = '\0';    if (state->assign) {        if (code == 'd' || code == 'i') {            if (state->sizeSpec == _PR_size_ll) {                PRInt64 llval = _pr_strtoull(buf, NULL, base);                *va_arg(state->ap, PRInt64 *) = llval;            } else {                long lval = strtol(buf, NULL, base);                if (state->sizeSpec == _PR_size_none) {                    *va_arg(state->ap, PRIntn *) = lval;                } else if (state->sizeSpec == _PR_size_h) {                    *va_arg(state->ap, PRInt16 *) = (PRInt16)lval;                } else if (state->sizeSpec == _PR_size_l) {                    *va_arg(state->ap, PRInt32 *) = lval;                } else {                    return PR_FAILURE;                }            }        } else {            if (state->sizeSpec == _PR_size_ll) {                PRUint64 llval = _pr_strtoull(buf, NULL, base);                *va_arg(state->ap, PRUint64 *) = llval;            } else {                unsigned long lval = strtoul(buf, NULL, base);                if (state->sizeSpec == _PR_size_none) {                    *va_arg(state->ap, PRUintn *) = lval;                } else if (state->sizeSpec == _PR_size_h) {                    *va_arg(state->ap, PRUint16 *) = (PRUint16)lval;                } else if (state->sizeSpec == _PR_size_l) {                    *va_arg(state->ap, PRUint32 *) = lval;                } else {                    return PR_FAILURE;                }            }        }        state->converted = PR_TRUE;    }    return PR_SUCCESS;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -