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 + -
显示快捷键?