📄 pcsl_string.c
字号:
return data - str->data; } } } } else if (IS_UNICODE_CODE_POINT(ch)) { jchar code_unit[2]; jsize unit_length; pcsl_string_status status = pcsl_code_point_to_utf16_code_unit(ch, code_unit, &unit_length); if (from_index >= str->length - 1) { from_index = str->length - 2; } if (status != PCSL_STRING_OK) { return -1; } else { const jchar high_surrogate = code_unit[0]; const jchar low_surrogate = code_unit[1]; const jchar * data = str->data + from_index; for ( ; data >= str->data; data--) { if (*data == high_surrogate && *(data + 1) == low_surrogate) { return data - str->data; } } } } else { return -1; } return -1;}/** * Removes white spaces from both sides of the string. * * @param str string to handle * @param dst storage for the trimmed string * @return status of trimming */pcsl_string_status pcsl_string_trim(const pcsl_string * str, pcsl_string * dst) { if (str == NULL || dst == NULL || (str->length > 0 && str->data == NULL)) { return PCSL_STRING_EINVAL; } if (str->length < 2) { /* null or empty string */ if(pcsl_string_is_null(str)) { *dst = PCSL_STRING_NULL; } else { *dst = PCSL_STRING_EMPTY; } return PCSL_STRING_OK; } { /* the character that precedes the end-of-string zero */ const jchar * data_start = str->data; const jchar * data_end = str->data + str->length - 2; jsize trimmed_length = 0; jchar * trimmed_buffer = NULL; // start spaces for ( ; data_end >= data_start && ((*data_start == 0x9) || (*data_start == 0x20)); data_start++) {} // end spaces for ( ; data_end >= data_start && ((*data_end == 0x9) || (*data_end == 0x20)); data_end--) {} trimmed_length = data_end - data_start + 2; trimmed_buffer = pcsl_mem_malloc(trimmed_length * sizeof(jchar)); if (trimmed_buffer == NULL) { * dst = PCSL_STRING_NULL; return PCSL_STRING_ENOMEM; } (void)memcpy(trimmed_buffer, data_start, (trimmed_length - 1) * sizeof(jchar)); /* Terminating zero */ trimmed_buffer[trimmed_length - 1] = 0; dst->data = trimmed_buffer; dst->length = trimmed_length; dst->flags = PCSL_STRING_IN_HEAP; return PCSL_STRING_OK; }}/** * Removes white spaces from the end of the string. * * @param str string to handle * @param dst storage for the trimmed string * @return status of trimming */pcsl_string_status pcsl_string_trim_from_end(const pcsl_string * str, pcsl_string * dst) { if (str == NULL || dst == NULL || (str->length > 0 && str->data == NULL)) { return PCSL_STRING_EINVAL; } if (str->length < 2) { /* null or empty string */ if(pcsl_string_is_null(str)) { *dst = PCSL_STRING_NULL; } else { *dst = PCSL_STRING_EMPTY; } return PCSL_STRING_OK; } { /* the character that precedes the end-of-string zero */ const jchar * data = str->data + str->length - 2; jsize trimmed_length = 0; jchar * trimmed_buffer = NULL; for ( ; data >= str->data && ((*data == 0x9) || (*data == 0x20)); data--) {} trimmed_length = data - str->data + 2; trimmed_buffer = pcsl_mem_malloc(trimmed_length * sizeof(jchar)); if (trimmed_buffer == NULL) { * dst = PCSL_STRING_NULL; return PCSL_STRING_ENOMEM; } (void)memcpy(trimmed_buffer, str->data, (trimmed_length - 1) * sizeof(jchar)); /* Terminating zero */ trimmed_buffer[trimmed_length - 1] = 0; dst->data = trimmed_buffer; dst->length = trimmed_length; dst->flags = PCSL_STRING_IN_HEAP; return PCSL_STRING_OK; }}/** * Parses the string argument as a signed decimal integer. The * characters in the string must all be decimal digits, except that * the first character may be an ASCII minus sign to indicate * a negative value or plus to indicate positive value. * The value must fit into 32-bit signed integer. * <p> * The parsed integer value is written to the memory location specified by * 'value'. Fails if 'value' is NULL. * <p> * If parsing fails, nothing is written and the return value indicates the * failure status. * * @param str the string to be parsed * @param value storage for the parsed value * @return parsing status */pcsl_string_status pcsl_string_convert_to_jint(const pcsl_string * str, jint * value) { jlong value_long; pcsl_string_status ret_val; if (value == NULL) { return PCSL_STRING_EINVAL; } ret_val = pcsl_string_convert_to_jlong(str, &value_long); if (ret_val == PCSL_STRING_OK) { /* check result */ jint value_int = (jint)value_long; if ((jlong)value_int == value_long) { *value = value_int; } else { ret_val = PCSL_STRING_OVERFLOW; } } return ret_val;}/** * Creates a new string representing the specified 32-bit signed integer value. * The integer value is converted to signed decimal representation. * <p> * An address of the created string is written to the memory location specified * by 'str'. Fails if 'str' is NULL. * * @param value the value to be converted * @param str storage for the created string * @return conversion status */pcsl_string_status pcsl_string_convert_from_jint(jint value, pcsl_string * str) { return pcsl_string_convert_from_jlong((jlong)value, str);}/** * Parses the string argument as a signed decimal integer. The * characters in the string must all be decimal digits, except that * the first character may be an ASCII minus sign to indicate * a negative value. The value must fit into 64-bit signed integer. * <p> * The parsed integer value is written to the memory location specified by * 'value'. Fails if 'value' is NULL. * <p> * If parsing fails, nothing is written and the return value indicates the * failure status. * * @param str the string to be parsed * @param value storage for the parsed value * @return parsing status *//* 0xCCC,CCCC,CCCC,CCCC *//* we don't write (jlong)0xCcccCccc to avoid conversion from negative signed */#define MAXINT_DIV_10 ( (((jlong)0x0cccCccc) << 32 ) \ | (((jlong)0x33333333) << 2 ) \ )#define LONG_SIZE_IN_BITS 64#define MIN_LONG (((jlong)1) << (LONG_SIZE_IN_BITS - 1))pcsl_string_status pcsl_string_convert_to_jlong(const pcsl_string * str, jlong * value) { jint length; if (str == NULL || str->data == NULL || value == NULL) { return PCSL_STRING_EINVAL; } { length = pcsl_string_length(str); /* String length doesn't include trailing zero character */ if (length == 0) { /* Empty string */ return PCSL_STRING_EINVAL; } } { const jchar* src = str->data; jlong ret_val = 0; int isNegative = 0; int i = 0; /* maybe first symbol is '-' or '+' */ switch (src[0]) { case '-': isNegative = 1; case '+': i++; /* no break here */ } /* loop along string */ for ( ; i < length; i++) { if (ret_val > MAXINT_DIV_10 || ret_val < 0) { return PCSL_STRING_OVERFLOW; } if ( '0' <= src[i] && src[i] <= '9') { ret_val = ret_val * RADIX + (jlong)(src[i] - '0'); if (ret_val < 0 && ret_val != MIN_LONG ) { /* arithmetic overflow */ return PCSL_STRING_OVERFLOW; } } else { return PCSL_STRING_EINVAL; /* non-digit symbol */ } } if (isNegative) { ret_val = - ret_val; /* once */ } else if (ret_val == MIN_LONG) { /* arithmetic overflow */ return PCSL_STRING_OVERFLOW; } *value = ret_val; return PCSL_STRING_OK; }}/** * Creates a new string representing the specified 64-bit signed integer value. * The integer value is converted to signed decimal representation. * <p> * An address of the created string is written to the memory location specified * by 'str'. Fails if 'str' is NULL. * * @param value the value to be converted * @param str storage for the created string * @return conversion status */#define DIGIT(x) ('0'+((char)(x)))/* Max length has MIN_LONG = -9223372036854775808 */#define TEXT_BUF_FOR_LONG_SIZE 20pcsl_string_status pcsl_string_convert_from_jlong(jlong value, pcsl_string * str) { if (str == NULL) { return PCSL_STRING_EINVAL; } { PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_START(PCSL_STRING_MIN_JLONG) { '-', '9', '2', '2', '3', '3', '7', '2', '0', '3', '6', '8', '5', '4', '7', '7', '5', '8', '0', '8', 0} PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_END(PCSL_STRING_MIN_JLONG); jchar buf[TEXT_BUF_FOR_LONG_SIZE]; /* filling buffer from the end */ int charPos = TEXT_BUF_FOR_LONG_SIZE - 1 ; int negative = (value < 0); jchar * new_buffer = NULL; int buf_length; /* MIN_LONG 0x8000000000000000 */ if (negative && value == MIN_LONG) { *str = PCSL_STRING_MIN_JLONG; return PCSL_STRING_OK; } /* Platform-undependent division: dividend and divisor must be positive */ if (negative) { value = -value; } /* Trailing 0 */ buf[charPos--] = 0; while (value >= RADIX) { buf[charPos--] = DIGIT(value % RADIX); value /= RADIX; } buf[charPos] = DIGIT(value); if (negative) { buf[--charPos] = '-'; } /* Allocate need memory */ buf_length = sizeof(jchar) * (TEXT_BUF_FOR_LONG_SIZE - charPos); new_buffer = pcsl_mem_malloc(buf_length); if (new_buffer == NULL) { return PCSL_STRING_ENOMEM; } /* Filling the buffer */ memcpy(new_buffer, &buf[charPos], buf_length); str->data = new_buffer; str->length = TEXT_BUF_FOR_LONG_SIZE - charPos; str->flags = PCSL_STRING_IN_HEAP; return PCSL_STRING_OK; }}/** * Frees the string. * Sets the freed pcsl_string to PCSL_STRING_NULL. * * @param str string to free * @return status */pcsl_string_status pcsl_string_free(pcsl_string * str) { if (str == NULL) { return PCSL_STRING_EINVAL; } if (str->flags & PCSL_STRING_IN_HEAP) { if (str->data != NULL) { pcsl_mem_free(str->data); } } * str = PCSL_STRING_NULL; return PCSL_STRING_OK;}/** * Returns UTF-8 representation for the specified string. * Returns NULL in case of failure. * <p> * If not NULL, the returned pointer points to an internal buffer that contains * UTF-8 representation of the string. You can safely read up to * <code>pcsl_string_utf8_length(str)</code> bytes from this buffer. * <p> * Do not write into the returned buffer, honor the 'const' modifier. * The implementation is not required to synchronize the buffer contents with * the actual string value. * <p> * To release the buffer, invoke <code>pcsl_string_release_utf8_data()</code> * when you are done and pass this pointer as an argument. * * @param str the string * @return UTF-8 representation for the specified string */const jbyte * pcsl_string_get_utf8_data(const pcsl_string * str) { if (str == NULL) { return NULL; } else { /* The returned length doesn't include the terminating zero. */ const jsize length = pcsl_string_utf8_length(str) + 1; jbyte * buffer = pcsl_mem_malloc(length * sizeof(jbyte)); if (buffer == NULL) { return NULL; } if (pcsl_string_convert_to_utf8(str, buffer, length, NULL) != PCSL_STRING_OK) { pcsl_mem_free(buffer); return NULL; } return buffer; }}/** * Releases the internal buffer that pointed to by <code>buf</code>. * The pointer must have been returned by a previous call to * <code>pcsl_string_get_utf8_data()</code>, otherwise the behavior is not * specified. * * @param buf pointer to the buffer * @param str the string from which this buffer was obtained */void pcsl_string_release_utf8_data(const jbyte * buf, const pcsl_string * str) { pcsl_mem_free((void*)buf);}/** * Returns UTF-16 representation for the specified string. * Returns NULL in case of failure. * <p> * If not NULL, the returned pointer points to an internal buffer that contains * UTF-16 representation of the string. You can safely read up to * <code>pcsl_string_utf16_length(str)</code> 16-bit units from this buffer. * <p> * Do not write into the returned buffer, honor the 'const' modifier. * The implementation is not required to synchronize the buffer contents with * the actual string value. * <p> * To release the buffer, invoke <code>pcsl_string_release_utf16_data()</code> * when you are done and pass this pointer as an argument. * * @param str the string * @return UTF-8 representation for the specified string */const jchar * pcsl_string_get_utf16_data(const pcsl_string * str) { if (str != NULL) { return str->data; } return NULL;}/** * Releases the internal buffer that pointed to by <code>buf</code>. * The pointer must have been returned by a previous call to * <code>pcsl_string_get_data_utf16()</code>, otherwise the behavior is not * specified. * * @param buf pointer to the buffer * @param str the string from which this buffer was obtained */void pcsl_string_release_utf16_data(const jchar * buf, const pcsl_string * str) { (void)buf; (void)str;}/** * Compares the given string with PCSL_STRING_NULL. * * @param str the string to compare * @return PCSL_TRUE if str is not NULL and is equal to PCSL_STRING_NULL, * PCSL_FALSE otherwise */jboolean pcsl_string_is_null(const pcsl_string * str) { return (str != NULL && str->data == NULL) ? PCSL_TRUE : PCSL_FALSE;}static jchar empty_string_data = 0;/* Empty zero-terminated string */const pcsl_string PCSL_STRING_EMPTY = { &empty_string_data, 1, 0 };/* NULL string */const pcsl_string PCSL_STRING_NULL = { NULL, 0, 0 };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -