📄 pcsl_string.c
字号:
src2 = (pcsl_string *)&PCSL_STRING_EMPTY; } else { src2 = (pcsl_string *)str2; if (src2->length > 0 && src2->data == NULL) { return PCSL_STRING_EINVAL; } } { /* Strip the terminating zero at the end of the first string. */ jsize length1, length2, cat_length; jchar * cat_buffer; length1 = src1->length; length2 = src2->length; if (length1 < 2 && length2 < 2) { /* both strings are empty or NULL */ *str = PCSL_STRING_EMPTY; return PCSL_STRING_OK; } if (length1 > 0 && length2 > 0) length1--; cat_length = length1 + length2; cat_buffer = pcsl_mem_malloc(cat_length * sizeof(jchar)); if (cat_buffer == NULL) { * str = PCSL_STRING_NULL; return PCSL_STRING_ENOMEM; } if (length1 > 0) { memcpy(cat_buffer, src1->data, length1 * sizeof(jchar)); } if (length2 > 0) { memcpy(cat_buffer + length1, src2->data, length2 * sizeof(jchar)); } str->data = cat_buffer; str->length = cat_length; str->flags = PCSL_STRING_IN_HEAP; return PCSL_STRING_OK; }}/** * Creates a new string that is a duplicate of this string. * * @param str string * @param dst storage for the created duplicate * @return status of the operation */pcsl_string_status pcsl_string_dup(const pcsl_string * src, pcsl_string * dst) { /* Return error status when any argument is NULL */ if (dst == NULL || src == NULL) { return PCSL_STRING_EINVAL; } /* Return error status when string is damaged */ if (src->length > 0 && src->data == NULL) { return PCSL_STRING_EINVAL; } /* When src is not in heap (frequently NULL and EMPTY string), * it is not need to duplicate source string */ if (!(src->flags & PCSL_STRING_IN_HEAP)) { *dst = *src; return PCSL_STRING_OK; } switch (src->length) { case 0: /* NULL string */ *dst = PCSL_STRING_NULL; break; case 1: /* EMPTY string */ *dst = PCSL_STRING_EMPTY; break; default: /* String is not empty */ { const jsize dup_length = src->length; jchar * dup_buffer = pcsl_mem_malloc(dup_length * sizeof(jchar)); if (dup_buffer == NULL) { * dst = PCSL_STRING_NULL; return PCSL_STRING_ENOMEM; } memcpy(dup_buffer, src->data, dup_length * sizeof(jchar)); dst->data = dup_buffer; dst->length = dup_length; dst->flags = PCSL_STRING_IN_HEAP; } /* End of default */ } /* End of switch */ return PCSL_STRING_OK;}/** * Append a string to an existing destination string. * All buffers obtained from the string must be released before the string * is changed by this function. * * @param dst the destination string, that grows * @param src the source string whose text gets appended to the destination string * @return status code */pcsl_string_status pcsl_string_append(pcsl_string* dst, const pcsl_string* src) { /* IMPL_NOTE: write up an optimized implementation */ pcsl_string tmpres; pcsl_string_status rc; rc = pcsl_string_cat(dst,src,&tmpres); if (PCSL_STRING_OK != rc) { return rc; } pcsl_string_free(dst); *dst = tmpres; return rc;}/** * Append a character to an existing destination string. * All buffers obtained from the string must be released before the string * is changed by this function. * * @param dst the destination string, that grows * @param newchar the character that gets appended to the destination string * @return status code */pcsl_string_status pcsl_string_append_char(pcsl_string* dst, const jchar newchar) { /* IMPL_NOTE: write up an optimized implementation */ jchar tmp[1]; tmp[0] = newchar; return pcsl_string_append_buf(dst, tmp, 1);}/** * Append text in a jchar array to an existing destination string. * All buffers obtained from the string must be released before the string * is changed by this function. * * @param dst the destination string, that grows * @param newtext the character array that gets appended to the destination string * @param textsize the size of the text in the character array * @return status code */pcsl_string_status pcsl_string_append_buf(pcsl_string* dst, const jchar* newtext, const jint textsize) { /* IMPL_NOTE: write up an optimized implementation */ pcsl_string text_str; pcsl_string_status rc; rc = pcsl_string_convert_from_utf16(newtext,textsize,&text_str); if (PCSL_STRING_OK == rc) { rc = pcsl_string_append(dst,&text_str); pcsl_string_free(&text_str); } return rc;}/** * Set string buffer capacity to the specified value. * All buffers obtained from a string must be released before the string * is changed by this function. * * This function is a hint that allows an efficient implementation * of concatenation of multiple strings using the append functions * (see pcsl_string_append, pcsl_string_append_buf, pcsl_string_append_char). * Before appending, invoke this function to specify the final string length. * * Nevertheless, an implementation may choose to implement this function * as a nothing-doer. There is no guarantee that the append functions * will not cause buffer reallocation. * * This function does not fail: if the resize request fails, it leaves * the string unchanged. * * @param str the string whose buffers's capacity is desired to be changed * @param size the desired new string buffer capacity * */void pcsl_string_predict_size(pcsl_string* str, jint size) { /* IMPL_NOTE: write up an optimized implementation */ (void) str; (void) size;}/** * Creates a new string that is a substring of this string. The * substring begins with the character at the specified begin_index * and extends to the character at the index end_index-1. * * @param str string to look in * @param begin_index the beginning index, inclusive * @param end_index the ending index, exclusive * @param dst storage for the created substring * @return status of the operation */pcsl_string_status pcsl_string_substring(const pcsl_string * str, jint begin_index, jint end_index, pcsl_string * dst) { jsize sub_length = end_index - begin_index; if (dst == NULL || str == NULL || str->data == NULL) { return PCSL_STRING_EINVAL; } { jsize src_length = pcsl_string_length(str); if (src_length < 0 || begin_index < 0 || sub_length < 0 || end_index > src_length) { return PCSL_STRING_EINVAL; } } if (sub_length == 0) { * dst = PCSL_STRING_EMPTY; return PCSL_STRING_OK; } else { const jchar * str_data = str->data; jchar * sub_buffer = NULL; sub_buffer = pcsl_mem_malloc((sub_length + 1) * sizeof(jchar)); if (sub_buffer == NULL) { * dst = PCSL_STRING_NULL; return PCSL_STRING_ENOMEM; } memcpy(sub_buffer, str->data + begin_index, sub_length * sizeof(jchar)); /* Append the terminating zero. */ sub_buffer[sub_length] = 0; dst->data = sub_buffer; dst->length = sub_length + 1; dst->flags = PCSL_STRING_IN_HEAP; return PCSL_STRING_OK; }}/** * Tests if this string starts with the specified prefix * * @param str string to look in * @param prefix prefix to look for * @param offset offset from start * @return PCSL_TRUE if the string and the prefix are not NULL and * the starts with the specified prefix, PCSL_FALSE otherwise */jboolean pcsl_string_starts_with(const pcsl_string * str, const pcsl_string * prefix) { if (prefix == NULL) { /* NULL is part of any string */ return PCSL_TRUE; } if (str == NULL) { /* Null string couldn't contain not-null substring */ return PCSL_FALSE; } /* NULL data is part of any other data */ if (prefix->data == NULL) { return PCSL_TRUE; } if (str->data == NULL) { /* Null data couldn't contain not-null subdata */ return PCSL_FALSE; } /* Substring couldn't be longer than target string */ if (str->length < prefix->length) { return PCSL_FALSE; } /* Empty or null prefix is a part of any string */ if (prefix->length < 2) { return PCSL_TRUE; } return (0 == memcmp(str->data, prefix->data, /* Do not count terminating '\0' */ (prefix->length - 1) * sizeof(jchar))) ? PCSL_TRUE : PCSL_FALSE;}/** * Tests if this string ends with the specified suffix. * * @param str string to look in * @param suffix suffix to look for * @return PCSL_TRUE if the string and the suffix are not NULL and * the ends with the specified suffix, PCSL_FALSE otherwise */jboolean pcsl_string_ends_with(const pcsl_string * str, const pcsl_string * suffix) { if (suffix == NULL) { /* NULL is part of any string */ return PCSL_TRUE; } if (str == NULL) { /* Null string couldn't contain not-null substring */ return PCSL_FALSE; } /* NULL data is part of any other data */ if (suffix->data == NULL) { return PCSL_TRUE; } if (str->data == NULL) { /* Null data couldn't contain not-null subdata */ return PCSL_FALSE; } /* Substring couldn't be longer than target string */ if (str->length < suffix->length) { return PCSL_FALSE; } /* Empty or null suffix is a part of any string */ if (suffix->length < 2) { return PCSL_TRUE; } return memcmp(str->data + str->length - suffix->length, suffix->data, suffix->length * sizeof(jchar)) == 0 ? PCSL_TRUE : PCSL_FALSE;}/** * Returns an index of the first occurrence of the abstract character * in the abstract character sequence specified by the given string. * The abstract character is specified by the Unicode code point. * <p> * Returns -1 if the specified integer value is not in the Unicode codespace, * or the specified integer value is a surrogate code point, * or the string is NULL, or the character doesn't occur. * Otherwise, * the returned index must be 0 <= index <= pcsl_string_length(str)-1. * * @param str string to look in * @param c Unicode code point to look for * @return index of the first occurence of the character */jint pcsl_string_index_of(const pcsl_string * str, jint ch) { return pcsl_string_index_of_from(str, ch, 0);}/** * Returns an index of the first occurrence of the abstract character * in the abstract character sequence specified by the given string, * starting the search at the specified from_index. * The abstract character is specified by the Unicode code point. * <p> * Returns -1 if the specified integer value is not in the Unicode codespace, * or the specified integer value is a surrogate code point, * or the string is NULL, or the character doesn't occur. * Otherwise, * the returned index must be from_index <= index <= pcsl_string_length(str)-1. * <p> * * @param str string to look in * @param c Unicode code point to look for * @return index of the first occurence of the character in the string */jint pcsl_string_index_of_from(const pcsl_string * str, jint ch, jint from_index) { if (str == NULL || str->data == NULL || str->length == 0) { return -1; } if (from_index >= str->length) { return -1; } if (from_index < 0) { from_index = 0; } if (IS_BMP_CODE_POINT(ch)) { if (IS_SURROGATE_CODE_POINT(ch)) { return -1; } else { /* handle most cases here */ const jchar * data = str->data + from_index; const jchar * data_end = str->data + str->length; for ( ; data < data_end; data++) { if (*data == ch) { 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 (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; const jchar * data_end = str->data + str->length - 1; for ( ; data < data_end; data++) { if (*data == high_surrogate && *(data + 1) == low_surrogate) { return data - str->data; } } } } else { return -1; } return -1;}/** * Returns an index of the last occurrence of the abstract character * in the abstract character sequence specified by the given string. * The abstract character is specified by the Unicode code point. * <p> * Returns -1 if the specified integer value is not in the Unicode codespace, * or the specified integer value is a surrogate code point, * or the string is NULL, or the character doesn't occur. * Otherwise, * the returned index must be 0 <= index <= pcsl_string_length(str)-1. * * @param str string to look in * @param c Unicode code point to look for * @return index of the last occurence of the character in the string */jint pcsl_string_last_index_of(const pcsl_string * str, jint ch) { if (str == NULL || str->data == NULL || str->length == 0) { return -1; } return pcsl_string_last_index_of_from(str, ch, str->length - 1);}/** * Returns an index of the last occurrence of the abstract character * in the abstract character sequence specified by the given string, * searching backward starting at the specified from_index. * The abstract character is specified by the Unicode code point. * <p> * Returns -1 if the specified integer value is not in the Unicode codespace, * or the specified integer value is a surrogate code point, * or the string is NULL, or the character doesn't occur. * Otherwise, * the returned index must be 0 <= index <= from_index. * * @param str string to look in * @param c Unicode code point to look for * @return index of the last occurence of the character in the string */jint pcsl_string_last_index_of_from(const pcsl_string * str, jint ch, jint from_index) { if (str == NULL || str->data == NULL || str->length == 0) { return -1; } if (from_index >= str->length) { from_index = str->length - 1; } if (from_index < 0) { return -1; } if (IS_BMP_CODE_POINT(ch)) { if (IS_SURROGATE_CODE_POINT(ch)) { return -1; } else { /* handle most cases here */ const jchar * data = str->data + from_index; for ( ; data >= str->data; data--) { if (*data == ch) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -