/** Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>* All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions are met:** * Redistributions of source code must retain the above copyright notice,* this list of conditions and the following disclaimer.* * 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.* * Neither the name of Redis nor the names of its contributors may be used* to endorse or promote products derived from this software without* specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.*/#ifdef _WIN32#include "Win32_Interop/Win32_Portability.h"#include "Win32_Interop/win32fixes.h"#include "Win32_Interop/Win32_Time.h"#include <process.h> // for getpid#include <direct.h> // for getcwd#include <shlwapi.h> // for PathIsRelative#endif#include "fmacros.h"#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <limits.h>#include <math.h>POSIX_ONLY(#include <unistd.h>)POSIX_ONLY(#include <sys/time.h>)#include <float.h>#include <stdint.h>#include <errno.h>#include <time.h>#include "util.h"#include "sha1.h"/* Glob-style pattern matching. */int stringmatchlen(const char *pattern, int patternLen,const char *string, int stringLen, int nocase){while(patternLen && stringLen) {switch(pattern[0]) {case '*':while (pattern[1] == '*') {pattern++;patternLen--;}if (patternLen == 1)return 1; /* match */while(stringLen) {if (stringmatchlen(pattern+1, patternLen-1,string, stringLen, nocase))return 1; /* match */string++;stringLen--;}return 0; /* no match */break;case '?':if (stringLen == 0)return 0; /* no match */string++;stringLen--;break;case '[':{int not, match;pattern++;patternLen--;not = pattern[0] == '^';if (not) {pattern++;patternLen--;}match = 0;while(1) {if (pattern[0] == '\\' && patternLen >= 2) {pattern++;patternLen--;if (pattern[0] == string[0])match = 1;} else if (pattern[0] == ']') {break;} else if (patternLen == 0) {pattern--;patternLen++;break;} else if (pattern[1] == '-' && patternLen >= 3) {int start = pattern[0];int end = pattern[2];int c = string[0];if (start > end) {int t = start;start = end;end = t;}if (nocase) {start = tolower(start);end = tolower(end);c = tolower(c);}pattern += 2;patternLen -= 2;if (c >= start && c <= end)match = 1;} else {if (!nocase) {if (pattern[0] == string[0])match = 1;} else {if (tolower((int)pattern[0]) == tolower((int)string[0]))match = 1;}}pattern++;patternLen--;}if (not)match = !match;if (!match)return 0; /* no match */string++;stringLen--;break;}case '\\':if (patternLen >= 2) {pattern++;patternLen--;}/* fall through */default:if (!nocase) {if (pattern[0] != string[0])return 0; /* no match */} else {if (tolower((int)pattern[0]) != tolower((int)string[0]))return 0; /* no match */}string++;stringLen--;break;}pattern++;patternLen--;if (stringLen == 0) {while(*pattern == '*') {pattern++;patternLen--;}break;}}if (patternLen == 0 && stringLen == 0)return 1;return 0;}int stringmatch(const char *pattern, const char *string, int nocase) {return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase);}/* Fuzz stringmatchlen() trying to crash it with bad input. */int stringmatchlen_fuzz_test(void) {char str[32];char pat[32];int cycles = 10000000;int total_matches = 0;while(cycles--) {int strlen = rand() % sizeof(str);int patlen = rand() % sizeof(pat);for (int j = 0; j < strlen; j++) str[j] = rand() % 128;for (int j = 0; j < patlen; j++) pat[j] = rand() % 128;total_matches += stringmatchlen(pat, patlen, str, strlen, 0);}return total_matches;}/* Convert a string representing an amount of memory into the number of* bytes, so for instance memtoll("1Gb") will return 1073741824 that is* (1024*1024*1024).** On parsing error, if *err is not NULL, it's set to 1, otherwise it's* set to 0. On error the function return value is 0, regardless of the* fact 'err' is NULL or not. */PORT_LONGLONG memtoll(const char *p, int *err) {const char *u;char buf[128];PORT_LONG mul; /* unit multiplier */PORT_LONGLONG val;unsigned int digits;if (err) *err = 0;/* Search the first non digit character. */u = p;if (*u == '-') u++;while(*u && isdigit(*u)) u++;if (*u == '0円' || !strcasecmp(u,"b")) {mul = 1;} else if (!strcasecmp(u,"k")) {mul = 1000;} else if (!strcasecmp(u,"kb")) {mul = 1024;} else if (!strcasecmp(u,"m")) {mul = 1000*1000;} else if (!strcasecmp(u,"mb")) {mul = 1024*1024;} else if (!strcasecmp(u,"g")) {mul = 1000L*1000*1000;} else if (!strcasecmp(u,"gb")) {mul = 1024L*1024*1024;} else {if (err) *err = 1;return 0;}/* Copy the digits into a buffer, we'll use strtoll() to convert* the digit (without the unit) into a number. */digits = (unsigned int)(u-p); WIN_PORT_FIX /* cast (unsigned int) */if (digits >= sizeof(buf)) {if (err) *err = 1;return 0;}memcpy(buf,p,digits);buf[digits] = '0円';char *endptr;errno = 0;val = strtoll(buf,&endptr,10);if ((val == 0 && errno == EINVAL) || *endptr != '0円') {if (err) *err = 1;return 0;}return val*mul;}/* Return the number of digits of 'v' when converted to string in radix 10.* See ll2string() for more information. */uint32_t digits10(uint64_t v) {if (v < 10) return 1;if (v < 100) return 2;if (v < 1000) return 3;if (v < 1000000000000UL) {if (v < 100000000UL) {if (v < 1000000) {if (v < 10000) return 4;return 5 + (v >= 100000);}return 7 + (v >= 10000000UL);}if (v < 10000000000UL) {return 9 + (v >= 1000000000UL);}return 11 + (v >= 100000000000UL);}return 12 + digits10(v / 1000000000000UL);}/* Like digits10() but for signed values. */uint32_t sdigits10(int64_t v) {if (v < 0) {/* Abs value of LLONG_MIN requires special handling. */uint64_t uv = (v != LLONG_MIN) ?(uint64_t)-v : ((uint64_t) LLONG_MAX)+1;return digits10(uv)+1; /* +1 for the minus. */} else {return digits10(v);}}/* Convert a long long into a string. Returns the number of* characters needed to represent the number.* If the buffer is not big enough to store the string, 0 is returned.** Based on the following article (that apparently does not provide a* novel approach but only publicizes an already used technique):** https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920** Modified in order to handle signed integers since the original code was* designed for unsigned integers. */int ll2string(char *dst, size_t dstlen, PORT_LONGLONG svalue) {static const char digits[201] ="0001020304050607080910111213141516171819""2021222324252627282930313233343536373839""4041424344454647484950515253545556575859""6061626364656667686970717273747576777879""8081828384858687888990919293949596979899";int negative;PORT_ULONGLONG value;/* The main loop works with 64bit unsigned integers for simplicity, so* we convert the number here and remember if it is negative. */if (svalue < 0) {if (svalue != LLONG_MIN) {value = -svalue;} else {value = ((PORT_ULONGLONG) LLONG_MAX)+1;}negative = 1;} else {value = svalue;negative = 0;}/* Check length. */uint32_t const length = digits10(value)+negative;if (length >= dstlen) return 0;/* Null term. */uint32_t next = length;dst[next] = '0円';next--;while (value >= 100) {int const i = (value % 100) * 2;value /= 100;dst[next] = digits[i + 1];dst[next - 1] = digits[i];next -= 2;}/* Handle last 1-2 digits. */if (value < 10) {dst[next] = '0' + (uint32_t) value;} else {int i = (uint32_t) value * 2;dst[next] = digits[i + 1];dst[next - 1] = digits[i];}/* Add sign. */if (negative) dst[0] = '-';return length;}/* Convert a string into a long long. Returns 1 if the string could be parsed* into a (non-overflowing) long long, 0 otherwise. The value will be set to* the parsed value when appropriate.** Note that this function demands that the string strictly represents* a long long: no spaces or other characters before or after the string* representing the number are accepted, nor zeroes at the start if not* for the string "0" representing the zero number.** Because of its strictness, it is safe to use this function to check if* you can convert a string into a long long, and obtain back the string* from the number without any loss in the string representation. */int string2ll(const char *s, size_t slen, PORT_LONGLONG *value) {const char *p = s;size_t plen = 0;int negative = 0;PORT_ULONGLONG v;/* A zero length string is not a valid number. */if (plen == slen)return 0;/* Special case: first and only digit is 0. */if (slen == 1 && p[0] == '0') {if (value != NULL) *value = 0;return 1;}/* Handle negative numbers: just set a flag and continue like if it* was a positive number. Later convert into negative. */if (p[0] == '-') {negative = 1;p++; plen++;/* Abort on only a negative sign. */if (plen == slen)return 0;}/* First digit should be 1-9, otherwise the string should just be 0. */if (p[0] >= '1' && p[0] <= '9') {v = p[0]-'0';p++; plen++;} else {return 0;}/* Parse all the other digits, checking for overflow at every step. */while (plen < slen && p[0] >= '0' && p[0] <= '9') {if (v > (ULLONG_MAX / 10)) /* Overflow. */return 0;v *= 10;if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */return 0;v += p[0]-'0';p++; plen++;}/* Return if not all bytes were used. */if (plen < slen)return 0;/* Convert to negative if needed, and do the final overflow check when* converting from unsigned long long to long long. */if (negative) {if (v > ((PORT_ULONGLONG)(-(LLONG_MIN+1))+1)) /* Overflow. */return 0;if (value != NULL) *value = -v;} else {if (v > LLONG_MAX) /* Overflow. */return 0;if (value != NULL) *value = v;}return 1;}/* Convert a string into a long. Returns 1 if the string could be parsed into a* (non-overflowing) long, 0 otherwise. The value will be set to the parsed* value when appropriate. */int string2l(const char *s, size_t slen, PORT_LONG *lval) {PORT_LONGLONG llval;if (!string2ll(s,slen,&llval))return 0;if (llval < PORT_LONG_MIN || llval > PORT_LONG_MAX)return 0;*lval = (PORT_LONG)llval;return 1;}/* Convert a string into a double. Returns 1 if the string could be parsed* into a (non-overflowing) double, 0 otherwise. The value will be set to* the parsed value when appropriate.** Note that this function demands that the string strictly represents* a double: no spaces or other characters before or after the string* representing the number are accepted. */int string2ld(const char *s, size_t slen, PORT_LONGDOUBLE *dp) {char buf[MAX_LONG_DOUBLE_CHARS];PORT_LONGDOUBLE value;char *eptr;if (slen >= sizeof(buf)) return 0;memcpy(buf,s,slen);buf[slen] = '0円';errno = 0;value = strtold(buf, &eptr);if (isspace(buf[0]) || eptr[0] != '0円' ||(errno == ERANGE &&(value == HUGE_VAL || value == -HUGE_VAL || value == 0)) ||errno == EINVAL ||isnan(value))return 0;if (dp) *dp = value;return 1;}/* Convert a double to a string representation. Returns the number of bytes* required. The representation should always be parsable by strtod(3).* This function does not support human-friendly formatting like ld2string* does. It is intended mainly to be used inside t_zset.c when writing scores* into a ziplist representing a sorted set. */int d2string(char *buf, size_t len, double value) {if (isnan(value)) {len = snprintf(buf,len,"nan");} else if (isinf(value)) {if (value < 0)len = snprintf(buf,len,"-inf");elselen = snprintf(buf,len,"inf");} else if (value == 0) {/* See: http://en.wikipedia.org/wiki/Signed_zero, "Comparisons". */if (1.0/value < 0)len = snprintf(buf,len,"-0");elselen = snprintf(buf,len,"0");} else {#if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)/* Check if the float is in a safe range to be casted into a* long long. We are assuming that long long is 64 bit here.* Also we are assuming that there are no implementations around where* double has precision < 52 bit.** Under this assumptions we test if a double is inside an interval* where casting to long long is safe. Then using two castings we* make sure the decimal part is zero. If all this is true we use* integer printing function that is much faster. */double min = -4503599627370495; /* (2^52)-1 */double max = 4503599627370496; /* -(2^52) */if (value > min && value < max && value == ((double)((PORT_LONGLONG)value)))len = ll2string(buf,len,(PORT_LONGLONG)value);else#endiflen = snprintf(buf,len,"%.17g",value);}return (int)len; WIN_PORT_FIX /* cast (int) */}/* Convert a long double into a string. If humanfriendly is non-zero* it does not use exponential format and trims trailing zeroes at the end,* however this results in loss of precision. Otherwise exp format is used* and the output of snprintf() is not modified.** The function returns the length of the string or zero if there was not* enough buffer room to store it. */int ld2string(char *buf, size_t len, PORT_LONGDOUBLE value, int humanfriendly) {size_t l;if (isinf(value)) {/* Libc in odd systems (Hi Solaris!) will format infinite in a* different way, so better to handle it in an explicit way. */if (len < 5) return 0; /* No room. 5 is "-inf0円" */if (value > 0) {memcpy(buf,"inf",3);l = 3;} else {memcpy(buf,"-inf",4);l = 4;}} else if (humanfriendly) {/* We use 17 digits precision since with 128 bit floats that precision* after rounding is able to represent most small decimal numbers in a* way that is "non surprising" for the user (that is, most small* decimal numbers will be represented in a way that when converted* back into a string are exactly the same as what the user typed.) */l = snprintf(buf,len,"%.17Lf", value);if (l+1 > len) return 0; /* No room. *//* Now remove trailing zeroes after the '.' */if (strchr(buf,'.') != NULL) {char *p = buf+l-1;while(*p == '0') {p--;l--;}if (*p == '.') l--;}} else {l = snprintf(buf,len,"%.17Lg", value);if (l+1 > len) return 0; /* No room. */}buf[l] = '0円';return l;}/* Get random bytes, attempts to get an initial seed from /dev/urandom and* the uses a one way hash function in counter mode to generate a random* stream. However if /dev/urandom is not available, a weaker seed is used.** This function is not thread safe, since the state is global. */void getRandomBytes(unsigned char *p, size_t len) {/* Global state. */static int seed_initialized = 0;static unsigned char seed[20]; /* The SHA1 seed, from /dev/urandom. */static uint64_t counter = 0; /* The counter we hash with the seed. */if (!seed_initialized) {/* Initialize a seed and use SHA1 in counter mode, where we hash* the same seed with a progressive counter. For the goals of this* function we just need non-colliding strings, there are no* cryptographic security needs. */FILE *fp = fopen("/dev/urandom","r");if (fp == NULL || fread(seed,sizeof(seed),1,fp) != 1) {/* Revert to a weaker seed, and in this case reseed again* at every call.*/for (unsigned int j = 0; j < sizeof(seed); j++) {struct timeval tv;gettimeofday(&tv,NULL);pid_t pid = getpid();seed[j] = tv.tv_sec ^ tv.tv_usec ^ pid ^ (PORT_LONG)fp;}} else {seed_initialized = 1;}if (fp) fclose(fp);}while(len) {unsigned char digest[20];SHA1_CTX ctx;unsigned int copylen = len > 20 ? 20 : len;SHA1Init(&ctx);SHA1Update(&ctx, seed, sizeof(seed));SHA1Update(&ctx, (unsigned char*)&counter,sizeof(counter));SHA1Final(digest, &ctx);counter++;memcpy(p,digest,copylen);len -= copylen;p += copylen;}}/* Generate the Redis "Run ID", a SHA1-sized random number that identifies a* given execution of Redis, so that if you are talking with an instance* having run_id == A, and you reconnect and it has run_id == B, you can be* sure that it is either a different instance or it was restarted. */void getRandomHexChars(char *p, size_t len) {char *charset = "0123456789abcdef";size_t j;getRandomBytes((unsigned char*)p,len);for (j = 0; j < len; j++) p[j] = charset[p[j] & 0x0F];}/* Given the filename, return the absolute path as an SDS string, or NULL* if it fails for some reason. Note that "filename" may be an absolute path* already, this will be detected and handled correctly.** The function does not try to normalize everything, but only the obvious* case of one or more "../" appearing at the start of "filename"* relative path. */#ifdef _WIN32sds getAbsolutePath(char *filename) {char fullPath[MAX_PATH];DWORD gfpnResult;sds abspath;sds relpath = sdsnew(filename);relpath = sdstrim(relpath, " \r\n\t");if (!PathIsRelative(relpath)) return relpath;gfpnResult = GetFullPathNameA(relpath, sizeof(fullPath), fullPath, NULL);sdsfree(relpath);if (gfpnResult == 0 || gfpnResult > sizeof(fullPath)) {return NULL;}abspath = sdsnew(fullPath);return abspath;}#elsesds getAbsolutePath(char *filename) {char cwd[1024];sds abspath;sds relpath = sdsnew(filename);relpath = sdstrim(relpath," \r\n\t");if (relpath[0] == '/') return relpath; /* Path is already absolute. *//* If path is relative, join cwd and relative path. */if (getcwd(cwd,sizeof(cwd)) == NULL) {sdsfree(relpath);return NULL;}abspath = sdsnew(cwd);if (sdslen(abspath) && abspath[sdslen(abspath)-1] != '/')abspath = sdscat(abspath,"/");/* At this point we have the current path always ending with "/", and* the trimmed relative path. Try to normalize the obvious case of* trailing ../ elements at the start of the path.** For every "../" we find in the filename, we remove it and also remove* the last element of the cwd, unless the current cwd is "/". */while (sdslen(relpath) >= 3 &&relpath[0] == '.' && relpath[1] == '.' && relpath[2] == '/'){sdsrange(relpath,3,-1);if (sdslen(abspath) > 1) {char *p = abspath + sdslen(abspath)-2;int trimlen = 1;while(*p != '/') {p--;trimlen++;}sdsrange(abspath,0,-(trimlen+1));}}/* Finally glue the two parts together. */abspath = sdscatsds(abspath,relpath);sdsfree(relpath);return abspath;}#endif/** Gets the proper timezone in a more portable fashion* i.e timezone variables are linux specific.*/PORT_ULONG getTimeZone(void) {#ifdef __linux__return timezone;#elsestruct timeval tv;struct timezone tz;gettimeofday(&tv, &tz);return tz.tz_minuteswest * 60UL;#endif}/* Return true if the specified path is just a file basename without any* relative or absolute path. This function just checks that no / or \* character exists inside the specified path, that's enough in the* environments where Redis runs. */int pathIsBaseName(char *path) {return strchr(path,'/') == NULL && strchr(path,'\\') == NULL;}#ifdef REDIS_TEST#include <assert.h>static void test_string2ll(void) {char buf[32];PORT_LONGLONG v;/* May not start with +. */strcpy(buf,"+1");assert(string2ll(buf,strlen(buf),&v) == 0);/* Leading space. */strcpy(buf," 1");assert(string2ll(buf,strlen(buf),&v) == 0);/* Trailing space. */strcpy(buf,"1 ");assert(string2ll(buf,strlen(buf),&v) == 0);/* May not start with 0. */strcpy(buf,"01");assert(string2ll(buf,strlen(buf),&v) == 0);strcpy(buf,"-1");assert(string2ll(buf,strlen(buf),&v) == 1);assert(v == -1);strcpy(buf,"0");assert(string2ll(buf,strlen(buf),&v) == 1);assert(v == 0);strcpy(buf,"1");assert(string2ll(buf,strlen(buf),&v) == 1);assert(v == 1);strcpy(buf,"99");assert(string2ll(buf,strlen(buf),&v) == 1);assert(v == 99);strcpy(buf,"-99");assert(string2ll(buf,strlen(buf),&v) == 1);assert(v == -99);strcpy(buf,"-9223372036854775808");assert(string2ll(buf,strlen(buf),&v) == 1);assert(v == LLONG_MIN);strcpy(buf,"-9223372036854775809"); /* overflow */assert(string2ll(buf,strlen(buf),&v) == 0);strcpy(buf,"9223372036854775807");assert(string2ll(buf,strlen(buf),&v) == 1);assert(v == LLONG_MAX);strcpy(buf,"9223372036854775808"); /* overflow */assert(string2ll(buf,strlen(buf),&v) == 0);}static void test_string2l(void) {char buf[32];PORT_LONG v;/* May not start with +. */strcpy(buf,"+1");assert(string2l(buf,strlen(buf),&v) == 0);/* May not start with 0. */strcpy(buf,"01");assert(string2l(buf,strlen(buf),&v) == 0);strcpy(buf,"-1");assert(string2l(buf,strlen(buf),&v) == 1);assert(v == -1);strcpy(buf,"0");assert(string2l(buf,strlen(buf),&v) == 1);assert(v == 0);strcpy(buf,"1");assert(string2l(buf,strlen(buf),&v) == 1);assert(v == 1);strcpy(buf,"99");assert(string2l(buf,strlen(buf),&v) == 1);assert(v == 99);strcpy(buf,"-99");assert(string2l(buf,strlen(buf),&v) == 1);assert(v == -99);#if PORT_LONG_MAX != LLONG_MAXstrcpy(buf,"-2147483648");assert(string2l(buf,strlen(buf),&v) == 1);assert(v == PORT_LONG_MIN);strcpy(buf,"-2147483649"); /* overflow */assert(string2l(buf,strlen(buf),&v) == 0);strcpy(buf,"2147483647");assert(string2l(buf,strlen(buf),&v) == 1);assert(v == PORT_LONG_MAX);strcpy(buf,"2147483648"); /* overflow */assert(string2l(buf,strlen(buf),&v) == 0);#endif}static void test_ll2string(void) {char buf[32];PORT_LONGLONG v;int sz;v = 0;sz = ll2string(buf, sizeof buf, v);assert(sz == 1);assert(!strcmp(buf, "0"));v = -1;sz = ll2string(buf, sizeof buf, v);assert(sz == 2);assert(!strcmp(buf, "-1"));v = 99;sz = ll2string(buf, sizeof buf, v);assert(sz == 2);assert(!strcmp(buf, "99"));v = -99;sz = ll2string(buf, sizeof buf, v);assert(sz == 3);assert(!strcmp(buf, "-99"));v = -2147483648;sz = ll2string(buf, sizeof buf, v);assert(sz == 11);assert(!strcmp(buf, "-2147483648"));v = LLONG_MIN;sz = ll2string(buf, sizeof buf, v);assert(sz == 20);assert(!strcmp(buf, "-9223372036854775808"));v = LLONG_MAX;sz = ll2string(buf, sizeof buf, v);assert(sz == 19);assert(!strcmp(buf, "9223372036854775807"));}#define UNUSED(x) (void)(x)int utilTest(int argc, char **argv) {UNUSED(argc);UNUSED(argv);test_string2ll();test_string2l();test_ll2string();return 0;}#endif
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。