📄 prscanf.c
字号:
static PRStatusGetFloat(ScanfState *state){ char buf[FMAX + 1], *p; int ch; PRBool seenDigit = PR_FALSE; 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); } while (WITHIN_WIDTH(state) && isdigit(ch)) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); seenDigit = PR_TRUE; } if (WITHIN_WIDTH(state) && ch == DECIMAL_POINT) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); while (WITHIN_WIDTH(state) && isdigit(ch)) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); seenDigit = PR_TRUE; } } /* * This is not robust. For example, "1.2e+" would confuse * the code below to read 'e' and '+', only to realize that * it should have stopped at "1.2". But we can't push back * more than one character, so there is nothing I can do. */ /* Parse exponent */ if (WITHIN_WIDTH(state) && (ch == 'e' || ch == 'E') && seenDigit) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); if (WITHIN_WIDTH(state) && (ch == '+' || ch == '-')) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); } while (WITHIN_WIDTH(state) && isdigit(ch)) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); } } if (WITHIN_WIDTH(state)) { UNGET(state, ch); } if (!seenDigit) { return PR_FAILURE; } *p = '\0'; if (state->assign) { PRFloat64 dval = PR_strtod(buf, NULL); state->converted = PR_TRUE; if (state->sizeSpec == _PR_size_l) { *va_arg(state->ap, PRFloat64 *) = dval; } else if (state->sizeSpec == _PR_size_L) {#if defined(OSF1) || defined(IRIX) *va_arg(state->ap, double *) = dval;#else *va_arg(state->ap, long double *) = dval;#endif } else { *va_arg(state->ap, float *) = (float) dval; } } return PR_SUCCESS;}/* * Convert, and return the end of the conversion spec. * Return NULL on error. */static const char *Convert(ScanfState *state, const char *fmt){ const char *cPtr; int ch; char *cArg = NULL; state->converted = PR_FALSE; cPtr = fmt; if (*cPtr != 'c' && *cPtr != 'n' && *cPtr != '[') { do { ch = GET(state); } while (isspace(ch)); UNGET(state, ch); } switch (*cPtr) { case 'c': if (state->assign) { cArg = va_arg(state->ap, char *); } if (state->width == 0) { state->width = 1; } for (; state->width > 0; state->width--) { ch = GET(state); if (ch == EOF) { return NULL; } else if (state->assign) { *cArg++ = ch; } } if (state->assign) { state->converted = PR_TRUE; } break; case 'p': case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': if (GetInt(state, *cPtr) == PR_FAILURE) { return NULL; } break; case 'e': case 'E': case 'f': case 'g': case 'G': if (GetFloat(state) == PR_FAILURE) { return NULL; } break; case 'n': /* do not consume any input */ if (state->assign) { switch (state->sizeSpec) { case _PR_size_none: *va_arg(state->ap, PRIntn *) = state->nChar; break; case _PR_size_h: *va_arg(state->ap, PRInt16 *) = state->nChar; break; case _PR_size_l: *va_arg(state->ap, PRInt32 *) = state->nChar; break; case _PR_size_ll: LL_I2L(*va_arg(state->ap, PRInt64 *), state->nChar); break; default: PR_ASSERT(0); } } break; case 's': if (state->width == 0) { state->width = INT_MAX; } if (state->assign) { cArg = va_arg(state->ap, char *); } for (; state->width > 0; state->width--) { ch = GET(state); if ((ch == EOF) || isspace(ch)) { UNGET(state, ch); break; } if (state->assign) { *cArg++ = ch; } } if (state->assign) { *cArg = '\0'; state->converted = PR_TRUE; } break; case '%': ch = GET(state); if (ch != '%') { UNGET(state, ch); return NULL; } break; case '[': { PRBool complement = PR_FALSE; const char *closeBracket; size_t n; if (*++cPtr == '^') { complement = PR_TRUE; cPtr++; } closeBracket = strchr(*cPtr == ']' ? cPtr + 1 : cPtr, ']'); if (closeBracket == NULL) { return NULL; } n = closeBracket - cPtr; if (state->width == 0) { state->width = INT_MAX; } if (state->assign) { cArg = va_arg(state->ap, char *); } for (; state->width > 0; state->width--) { ch = GET(state); if ((ch == EOF) || (!complement && !memchr(cPtr, ch, n)) || (complement && memchr(cPtr, ch, n))) { UNGET(state, ch); break; } if (state->assign) { *cArg++ = ch; } } if (state->assign) { *cArg = '\0'; state->converted = PR_TRUE; } cPtr = closeBracket; } break; default: return NULL; } return cPtr;}static PRInt32DoScanf(ScanfState *state, const char *fmt){ PRInt32 nConverted = 0; const char *cPtr; int ch; state->nChar = 0; cPtr = fmt; while (1) { if (isspace(*cPtr)) { /* white space: skip */ do { cPtr++; } while (isspace(*cPtr)); do { ch = GET(state); } while (isspace(ch)); UNGET(state, ch); } else if (*cPtr == '%') { /* format spec: convert */ cPtr++; state->assign = PR_TRUE; if (*cPtr == '*') { cPtr++; state->assign = PR_FALSE; } for (state->width = 0; isdigit(*cPtr); cPtr++) { state->width = state->width * 10 + *cPtr - '0'; } state->sizeSpec = _PR_size_none; if (*cPtr == 'h') { cPtr++; state->sizeSpec = _PR_size_h; } else if (*cPtr == 'l') { cPtr++; if (*cPtr == 'l') { cPtr++; state->sizeSpec = _PR_size_ll; } else { state->sizeSpec = _PR_size_l; } } else if (*cPtr == 'L') { cPtr++; state->sizeSpec = _PR_size_L; } cPtr = Convert(state, cPtr); if (cPtr == NULL) { return (nConverted > 0 ? nConverted : EOF); } if (state->converted) { nConverted++; } cPtr++; } else { /* others: must match */ if (*cPtr == '\0') { return nConverted; } ch = GET(state); if (ch != *cPtr) { UNGET(state, ch); return nConverted; } cPtr++; } }}static intStringGetChar(void *stream){ char *cPtr = *((char **) stream); if (*cPtr == '\0') { return EOF; } else { *((char **) stream) = cPtr + 1; return *cPtr; }}static voidStringUngetChar(void *stream, int ch){ char *cPtr = *((char **) stream); if (ch != EOF) { *((char **) stream) = cPtr - 1; }}PR_IMPLEMENT(PRInt32)PR_sscanf(const char *buf, const char *fmt, ...){ PRInt32 rv; ScanfState state; state.get = &StringGetChar; state.unget = &StringUngetChar; state.stream = (void *) &buf; va_start(state.ap, fmt); rv = DoScanf(&state, fmt); va_end(state.ap); return rv;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -