utils.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,268 行 · 第 1/5 页

C
2,268
字号
	case 0xE0:	    /* 1110xxxx 10xxxxxx 10xxxxxx */	    t = ((utfchar&0xf)<<6) | ((*utf8Bytes++)&0x3f);	    *unicodeChars++ = (t<<6) | ((*utf8Bytes++)&0x3f);	    nutf+= 3;	    continue;	} /* end of switch */    }    return nutf;}/* * Copy a utf8 array into a unicode array. */void CVMutfCopyIntoCharArray(const char* utf8Bytes, CVMJavaChar* unicodeChars){    int i = 0;    while (*utf8Bytes != 0) {	unicodeChars[i] = CVMutfNextUnicodeChar(&utf8Bytes);	i++;    }}/* * Copy a unicode array into a utf8 array.  Returns pointer to end of array. * * Code stolen from JDK unicode2utf(). */char *CVMutfCopyFromCharArray(const CVMJavaChar* unicodeChars,                        char* utf8Bytes, CVMInt32 count){    while (--count >= 0) {	CVMJavaChar ch = *unicodeChars++;        if ((ch != 0) && (ch <=0x7f)) {            *utf8Bytes++ = (char)ch;        } else if (ch <= 0x7FF) {            /* 11 bits or less. */            CVMUint8 high_five = ch >> 6;            CVMUint8 low_six = ch & 0x3F;            *utf8Bytes++ = high_five | 0xC0; /* 110xxxxx */            *utf8Bytes++ = low_six | 0x80;   /* 10xxxxxx */        } else {            /* possibly full 16 bits. */            CVMInt8 high_four = ch >> 12;            CVMInt8 mid_six = (ch >> 6) & 0x3F;            CVMInt8 low_six = ch & 0x3f;            *utf8Bytes++ = high_four | 0xE0; /* 1110xxxx */            *utf8Bytes++ = mid_six | 0x80;   /* 10xxxxxx */            *utf8Bytes++ = low_six | 0x80;   /* 10xxxxxx*/        }    }    return utf8Bytes;}/* * Return the next unicode character in the utf8 string and update * utf8String_p to point after the unicode characater return. * * This is the same as the JDK next_utf2unicode function. */extern CVMJavaCharCVMutfNextUnicodeChar(const char** utf8String_p){    CVMUint8* ptr = (CVMUint8*)(*utf8String_p);    CVMUint8 ch, ch2, ch3;    int length = 1;		/* default length */    CVMJavaChar result = 0x80;	/* default bad result; */    switch ((ch = ptr[0]) >> 4) {        default:	    result = ch;	    break;	case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:	    /* Shouldn't happen. */	    break;	case 0xC: case 0xD:		    /* 110xxxxx  10xxxxxx */	    if (((ch2 = ptr[1]) & 0xC0) == 0x80) {		unsigned char high_five = ch & 0x1F;		unsigned char low_six = ch2 & 0x3F;		result = (high_five << 6) + low_six;		length = 2;	    } 	    break;	case 0xE:	    /* 1110xxxx 10xxxxxx 10xxxxxx */	    if (((ch2 = ptr[1]) & 0xC0) == 0x80) {		if (((ch3 = ptr[2]) & 0xC0) == 0x80) {		    unsigned char high_four = ch & 0x0f;		    unsigned char mid_six = ch2 & 0x3f;		    unsigned char low_six = ch3 & 0x3f;		    result = (((high_four << 6) + mid_six) << 6) + low_six;		    length = 3;		} else {		    length = 2;		}	    }	    break;	} /* end of switch */    *utf8String_p = (char *)(ptr + length);    return result;}/* * Allocate a java/lang/String and copy the specifed utf8 string into it. */voidCVMnewStringUTF(CVMExecEnv* ee, CVMStringICell* stringICell,		const char* utf8Bytes){#undef STACK_CHAR_BUF_SIZE#define STACK_CHAR_BUF_SIZE 128    CVMJavaChar  buf[STACK_CHAR_BUF_SIZE];    CVMJavaChar* unicodeChars;    CVMSize len = CVMutfLength(utf8Bytes);    if (len > STACK_CHAR_BUF_SIZE) {	unicodeChars = (CVMJavaChar *)malloc(len * sizeof(CVMJavaChar));	if (unicodeChars == 0) {	    CVMID_icellSetNull(stringICell);	    return;	}    } else {	unicodeChars = buf;    }    CVMutfCopyIntoCharArray(utf8Bytes, unicodeChars);    CVMnewString(ee, stringICell, unicodeChars, (CVMUint32)len);    if (unicodeChars != buf) {	free(unicodeChars);    }}/* * Allocate a java/lang/String and copied to specifed unicode string into it. */voidCVMnewString(CVMExecEnv* ee, CVMStringICell* stringICell,	     const CVMJavaChar* unicodeChars, CVMUint32 len){    /*      * Allocate the java/lang/String object first, and store it away     * in stringICell.     */    CVMID_allocNewInstance( 	    ee, (CVMClassBlock*)CVMsystemClass(java_lang_String), stringICell);    if (CVMID_icellIsNull(stringICell)) {	goto finish;    }    {	CVMArrayOfCharICell* charArrayICell =	    (CVMArrayOfCharICell*)CVMmiscICell(ee);	CVMassert(CVMID_icellIsNull(charArrayICell));	/*	 * Allocate the char array. 	 */	CVMID_allocNewArray(		ee, CVM_T_CHAR, 		(CVMClassBlock*)CVMbasicTypeArrayClassblocks[CVM_T_CHAR],		len, (CVMObjectICell*)charArrayICell);	if (CVMID_icellIsNull(charArrayICell)) {	    /* null result if anything failed. */	    CVMID_icellSetNull(stringICell);	} else {	    /*	     * Fill in the char array.	     */	    CVMD_gcUnsafeExec(ee, {		CVMArrayOfChar* charArray =		    CVMID_icellDirect(ee, charArrayICell);		CVMD_arrayWriteBodyChar(unicodeChars, charArray, 0, len);	    });	    /*	     * Assign all the fields of the String object. Note that	     * directObj may have moved during the array allocation,	     * so we need to recache it. 	     */	    CVMID_fieldWriteRef(ee, stringICell, 				CVMoffsetOfjava_lang_String_value,				(CVMObjectICell*)charArrayICell);	    CVMID_fieldWriteInt(ee, stringICell,				CVMoffsetOfjava_lang_String_offset,				0);	    CVMID_fieldWriteInt(ee, stringICell, 				CVMoffsetOfjava_lang_String_count,				len);	    /*	     * Set this to null when we're done. The misc icell is	     * needed elsewhere, and the nullness is used to detect	     * errors.	     */	    CVMID_icellSetNull(charArrayICell);	}    } finish:    CVMassert(!CVMlocalExceptionOccurred(ee));}/* * Build a formatted string.  Special formats include: * * code	     arg		      result * * %P    CVMFrame*	   The class name, method name, source file name *                         and line number of the pc in the frame. * %O    CVMObject*	   The class name and object hash. * %I    CVMObjectICell*   The class name and object hash. * %C    CVMClassBlock*	   CVMclassname2String(CVMcbClassName(cb)) * %F	 CVMFieldBlock*	   CVMtypeidFieldNameToCString(CVMfbNameAndTypeID(fb)) * %M	 CVMMethodBlock*   CVMtypeidMethodNameToCString(CVMmbNameAndTypeID(mb)) * * -%C,%F, and %M support the '!' modifier if you want to pass the typeid *  rather than the cb, fb, or mb. * -Supports all ANSI formats except for %n. * -Does not support field modifiers on %C, %F, and %M fields. * * Returns total size of formatted result, untruncated. * * WARNING: This function is not bulletproof like sprintf. You must obey * the following rules to avoid a crash. * 1. No single expanded field, other than %C, %F, and %M fields, can *    expand bigger than bufSize. This means, for example, if you pass *    a format of "%20d" and a bufSize of 10, the buffer will still get *    20 bytes stored in, thus corrupting memory. It also means if you *    pass a format of "%s" with a string argument larger than bufsize, *    you will also corrupt memory. * 2. You cannot pass in a bufSize of 0 if you use %O, %C, %M, or %F. */#undef MIN#define MIN(x,y) ((x) < (y) ? (x) : (y))#ifdef CVM_CSTACKANALYSIS/* * Instead of putting stack redzone check in CVMformatStringVaList, * a dummy recursive function is a place holder to put stack redzone check * for a one level deep recursion that only happens in a debug build * through CVMformatStringVaList->CVMpc2string->CVMformatString-> * CVMformatStringVaList */static CVMBoolCVMCstackDummy2CVMformatStringVaList(CVMExecEnv* ee, void *frame, char p,                                     char *tmp, size_t bufSize){    /* C stack checks */    if (!CVMCstackCheckSize(            ee, CVM_REDZONE_CVMCstackCVMpc2string,	    "CVMformatStringVaList2CVMpc2string", CVM_TRUE))    {        return CVM_FALSE;    }    if (p == '!') {	CVMframeIterate2string((CVMFrameIterator *)frame, tmp, tmp + bufSize);    } else {	CVMframe2string((CVMFrame *)frame, tmp, tmp + bufSize);    }    return CVM_TRUE;}static CVMBoolCVMCstackDummy2CVMconsolePrintf(CVMExecEnv* ee,                                CVMObjectICell* indirectObj,                                const CVMClassBlock* cb){    /* C stack checks */    if (!CVMCstackCheckSize(             ee, CVM_REDZONE_CVMCstackCVMID_objectGetClassAndHashSafe,            "CVMformatStringVaList2CVMID_objectGetClassAndHashSafe", CVM_TRUE))    {        return CVM_FALSE;    }    CVMID_objectGetClass(ee, indirectObj, cb);    return CVM_TRUE;}static CVMInt32CVMCstackDummy2CVMobjectGetHashSafe(CVMExecEnv* ee,                                    CVMObjectICell* indirectObj){    /* C stack checks */    if (!CVMCstackCheckSize(ee,        CVM_REDZONE_CVMCstackCVMID_objectGetClassAndHashSafe,        "CVMformatStringVaList2CVMGetHashSafe", CVM_TRUE)) {        return 0;    }    return CVMobjectGetHashSafe(ee, indirectObj);}#endif /* CVM_CSTACKANALYSIS */size_tCVMformatStringVaList(char* buf, size_t bufSize, const char* format,		      va_list ap){    CVMExecEnv *ee = CVMgetEE();    const char* f = format;    const char* s;    char* tmp;    size_t      length  = 0;    int         result = 0;    char gbuf[256];    char format2[17]; /* must be bigger than the biggest known format.		       * "%-+ #<num>.<num>wc" is the biggest. If we		       * limit <num> to a resonable 4 digits, this gives		       * us a total size of 17.		       */    if (buf == NULL) {	/* Just sizing result */	tmp = NULL;	bufSize = 0;    } else {	if (sizeof(gbuf) >= bufSize) {	    tmp = gbuf;	} else {	    tmp = (char*)malloc(bufSize);	    if (tmp == NULL) {		char* errStr = "** CVMformatStringVaList: out of memory **";		strncpy(buf, errStr, bufSize - 1);		buf[strlen(buf)] = '\0';		return 0;	    }	}	/* save room for terminating \0 */	bufSize -= 1;    }    while (*f != '\0') {	char* p;	char c;	size_t l;	p = strchr(f, '%');	l = (p == NULL ? strlen(f) : p - f);	/* copy everything up to the % */	if (bufSize > 0) {	    l = MIN(bufSize, l);	    strncpy(buf, f, l);	    buf += l;	    bufSize -= l;            length += l;	}	if (p == NULL) {	    /* There are no more %'s, so we are done */	    break;	}	/* skip modifier fields */	f = p;  /* f points to the % */	p++; /* skip the % */	while ((c = *p) != 0) {	    if (c == '%') {		break;	    }	    /* alphabetic characters usually mark the end of the modifiers	     * fields, except for a few alphabetic modifiers we suport.	     */	    if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {		CVMBool needBreak = CVM_TRUE;		switch (c) {		    case 'w':		    case 'h':		    case 'l':		    case 'L': {			needBreak = CVM_FALSE;		    }		}		if (needBreak) {			    break;		}	    }	    p++;	}	/* copy everything from the % char up to and including the field	 * type char into format2. We need to do this since we don't	 * want the sprintf calls to look past the field type char.	 */	l = p - f + 1;	CVMassert(l + 1 <= sizeof(format2));	strncpy(format2, f, l);	format2[l] = 0;	switch (c) {	case 'd':	case 'i':	case 'o':	case 'u':	case 'x':	case 'X': {	    int i = va_arg(ap, int);	    result = sprintf(tmp, format2, i);	    goto copy_string;	}	/* 	 * Scalar variables intended to hold memory dimensions	 * have to be of the type CVMAddr which is 4 byte on	 * 32 bit platforms and 8 byte on 64 bit platforms.	 */	case 'p': {	    CVMAddr a = va_arg(ap, CVMAddr);	    result = sprintf(tmp, format2, a);	    goto copy_string;	}	case 'f':	case 'e':	case 'E':	case 'g':	case 'G': {	    double f1 = va_arg(ap, double);	    result = sprintf(tmp, format2, f1);	    goto copy_string;	}	case 'c':  {	    char c = va_arg(ap, int);	    result = sprintf(tmp, format2, c);	    goto copy_string;	}	case 's': {	    const char* c = va_arg(ap, const char*);	    /*	     * If the format string is a simple "%s", then we just copy	     * the argument string directly into buf and also check for	     * overflow. Otherwise, we role the dice and let sprintf	     * handle it. This means that if you ever use a format modifier	     * with %s, you better make sure your buffer is big enough because	     * we don't do any overflow checking here.	     */            if (c == NULL) {                f = p + 1;                continue;            } else if (format2[1] == 's') {		l = strlen(c);		if (bufSize > 0) {		    l = MIN(bufSize, l);		    strncpy(buf, c, l);		    buf += l;		    bufSize -= l;                    length += l;		}		f = p + 1;		continue;	    } else {

⌨️ 快捷键说明

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