📄 pcsl_string.c
字号:
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <limits.h>#include <util/utf.h>#include <pcsl_string.h>#include <pcsl_memory.h>/* * Radix value for pcsl convertings. */#define RADIX 10static jboolean pcsl_string_active = PCSL_FALSE;/** * Returns whether the string system is active. * The string subsystem is active after it is initialized and * before it is finalized. * * @return PCSL_TRUE if the string system is active, * PCSL_FALSE otherwise */jboolean pcsl_string_is_active(void) { return pcsl_string_active;}/** * Performs platform-specific initialization of the string system. * This function must be invoked before any other functions of * the string subsystem. * * @return initialization status */pcsl_string_status pcsl_string_initialize(void) { pcsl_string_active = PCSL_TRUE; return PCSL_STRING_OK;}/** * Performs platform-specific finalization of the string system. * No functions of the string subsystem should be used after * the string system is finalized. * * @return finalization status */pcsl_string_status pcsl_string_finalize() { pcsl_string_active = PCSL_FALSE; return PCSL_STRING_OK;}/** * Returns the number of abstract characters in the specified string, * not including the terminating zero character. * Returns -1 if str is NULL or doesn't represent a valid abstract character * sequence. * See Unicode Glossary at http://www.unicode.org/glossary/. * * @param str string * @return number of abstract characters in the string */jsize pcsl_string_length(const pcsl_string * str) { if (str == NULL || str->data == NULL) { return -1; } return utf16_string_length(str->data, str->length) - 1;}/** * Returns the number of 16-bit units in the UTF-16 representation * of the specified string, not including the terminating zero character. * Returns -1 if str is NULL. * * @param str string * @return length of UTF-16 representation of the string */jsize pcsl_string_utf16_length(const pcsl_string * str) { if (str == NULL || str->data == NULL) { return -1; } /* Do not count terminating '\0' */ return str->length - 1;}/** * Returns the number of bytes in the UTF-8 representation * of the specified string, not including the terminating zero character. * Returns -1 if str is NULL. * * @param str string * @return length of UTF-8 representation of the string */jsize pcsl_string_utf8_length(const pcsl_string * str) { if (str == NULL || str->data == NULL) { return -1; } { jsize utf8_length = 0; pcsl_string_status status = pcsl_utf16_convert_to_utf8(str->data, str->length, NULL, 0, &utf8_length); if (status == PCSL_STRING_OK) { /* Do not count terminating '\0' */ return utf8_length - 1; } else { return -1; } }}/** * Converts the string to UTF-16. * If the buffer length is not sufficient, the conversion is not performed and * the function returns PCSL_STRING_BUFFER_OVERFLOW. * If converted_length is not NULL and the specified string has a valid UTF-8 * representation, the number of 16-bit units in the UTF-16 representation * of the string is written to converted_length. * * @param str string to convert * @param buffer buffer to store the result of conversion * @param buffer_length length of buffer (number of 16-bit units) * @param converted_length * storage for the number of 16-bit units in UTF-16 representation * of the string * @return status of the operation */pcsl_string_status pcsl_string_convert_to_utf16(const pcsl_string * str, jchar * buffer, jsize buffer_length, jsize * converted_length) { if (str == NULL || str->data == NULL || buffer == NULL) { return PCSL_STRING_EINVAL; } /* Do not count the terminating zero character. */ if (converted_length != NULL) { * converted_length = str->length - 1; } if (str->length > buffer_length) { return PCSL_STRING_BUFFER_OVERFLOW; } (void)memcpy(buffer, str->data, str->length * sizeof(jchar)); return PCSL_STRING_OK;}/** * Converts the string to UTF-8. * If the buffer length is not sufficient, the conversion is not performed and * the function returns PCSL_STRING_BUFFER_OVERFLOW. * If converted_length is not NULL and the specified string has a valid UTF-8 * representation, the number of bytes in the UTF-8 representation * of the string is written to converted_length. * * @param str string to convert * @param buffer buffer to store the result of conversion * @param buffer_length length of buffer (number of bytes) * @param converted_length * storage for the number of bytes in UTF-8 representation * of the string * @return status of the operation */pcsl_string_status pcsl_string_convert_to_utf8(const pcsl_string * str, jbyte * buffer, jsize buffer_length, jsize * converted_length) { if (str == NULL || str->data == NULL || buffer == NULL) { return PCSL_STRING_EINVAL; } { pcsl_string_status status = pcsl_utf16_convert_to_utf8(str->data, str->length, buffer, buffer_length, converted_length); /* Do not count the terminating zero character. */ if (status == PCSL_STRING_OK && converted_length != NULL) { (*converted_length)--; } return status; }}/** * Creates a new string from the specified array of UTF-16 characters * and saves a pointer to that string into the specified storage 'string'. * Fails if either 'buffer' or 'string' is NULL. * If the last character in the specified array is not zero, * a zero character is appended at the end of string. * * @param buffer array of UTF-16 characters * @param buffer_length number of 16-bit units in the array * @param string storage for the created string * @return status of the operation */pcsl_string_status pcsl_string_convert_from_utf16(const jchar * buffer, jsize buffer_length, pcsl_string * string) { jchar * new_buffer = NULL; if (buffer == NULL || string == NULL) { return PCSL_STRING_EINVAL; } * string = PCSL_STRING_NULL; if (buffer_length < 0) { return PCSL_STRING_EINVAL; } { jsize new_buffer_length = buffer_length; /* Strip trailing zero characters. */ for ( ; new_buffer_length > 0 && buffer[new_buffer_length - 1] == 0; new_buffer_length--) {} /* IMPL_NOTE: decide what to do with possible internal zeroes. * Now we remove all trailing zeroes, but if some garbage text follows * the eol terminator in the buffer, we will append all that stuff. * On the other hand, we can just say DON'T DO THAT (universal advice), * that is, do not include garbage into the string length */ /* We are going to append one terminating zero. */ new_buffer_length++; new_buffer = pcsl_mem_malloc(sizeof(jchar) * new_buffer_length); if (new_buffer == NULL) { return PCSL_STRING_ENOMEM; } (void)memcpy(new_buffer, buffer, sizeof(jchar) * (new_buffer_length - 1)); /* Append the terminating zero. */ new_buffer[new_buffer_length - 1] = 0; string->data = new_buffer; string->length = new_buffer_length; string->flags = PCSL_STRING_IN_HEAP; return PCSL_STRING_OK; }}/** * Creates a new string from the specified array of UTF-8 characters * and saves a pointer to that string into the specified storage 'string'. * Fails if either 'buffer' or 'string' is NULL. * If the last character in the specified array is not zero, * a zero character is appended at the end of string. * * @param buffer array of UTF-8 characters * @param buffer_length number of bytes in the array * @param string storage for the created string * @return status of the operation */pcsl_string_status pcsl_string_convert_from_utf8(const jbyte * buffer, jsize buffer_length, pcsl_string * string) { jchar * utf16_buffer = NULL; const jsize max_utf16_length = buffer_length * 2 + 1; if (buffer == NULL || string == NULL) { return PCSL_STRING_EINVAL; } if (buffer_length < 0) { * string = PCSL_STRING_NULL; return PCSL_STRING_EINVAL; } utf16_buffer = pcsl_mem_malloc(sizeof(jchar) * max_utf16_length); if (utf16_buffer == NULL) { * string = PCSL_STRING_NULL; return PCSL_STRING_ENOMEM; } /* Strip trailing zero characters. */ for ( ; buffer_length > 0 && buffer[buffer_length - 1] == 0; buffer_length--) {} { jsize utf16_length = 0; /* we specify max_utf16_length - 1 to leave room for a terminating zero */ pcsl_string_status status = pcsl_utf8_convert_to_utf16(buffer, buffer_length, utf16_buffer, max_utf16_length - 1, &utf16_length); if (status != PCSL_STRING_OK) { pcsl_mem_free(utf16_buffer); * string = PCSL_STRING_NULL; return status; } else { /* Append terminating zero character. */ utf16_buffer[utf16_length] = 0; utf16_length++; /* Resize the buffer down to the actual string length. */ utf16_buffer = pcsl_mem_realloc(utf16_buffer, utf16_length * sizeof(jchar)); if (utf16_buffer == NULL) { * string = PCSL_STRING_NULL; return PCSL_STRING_ENOMEM; } string->data = utf16_buffer; string->length = utf16_length; string->flags = PCSL_STRING_IN_HEAP; return PCSL_STRING_OK; } }}/** * Tests if two strings are equal. * <p> * Returns PCSL_FALSE if either of the two strings is NULL. * * @param str1 first string to compare * @param str2 second string to compare * @return PCSL_TRUE if both strings are not NULL and are equal, * PCSL_FALSE otherwise */jboolean pcsl_string_equals(const pcsl_string * str1, const pcsl_string * str2) { if (str1 == str2) { /* include NULL = NULL */ return PCSL_TRUE; } if (str1 == NULL || str2 == NULL) { return PCSL_FALSE; } /* Check that input structures are equals */ if (memcmp(str1, str2, sizeof(pcsl_string)) == 0) { return PCSL_TRUE; } if (str1->data == NULL || str2->data == NULL) { return PCSL_FALSE; } if (str1->length != str2->length) { return PCSL_FALSE; } if (str1->data == str2->data) { return PCSL_TRUE; } return memcmp(str1->data, str2->data, str1->length * sizeof(jchar)) == 0 ? PCSL_TRUE : PCSL_FALSE;}/** * Compares two strings. The result of comparison is an integer less than, * equal to, or greater than zero if str1 is found, respectively, to be * less than, to match, or be greater than str2. * * @param str1 first string to compare * @param str2 second string to compare * @param comparison storage for the result of comparison * @return status of operation comparison */pcsl_string_status pcsl_string_compare(const pcsl_string * str1, const pcsl_string * str2, jint * comparison) { if (comparison == NULL) { return PCSL_STRING_EINVAL; } if (str1 == str2) { /* include NULL = NULL */ *comparison = 0; return PCSL_STRING_OK; } if (str1 == NULL || str2 == NULL) { return PCSL_STRING_EINVAL; } /* Check that input structures are equals */ if (memcmp(str1, str2, sizeof(pcsl_string)) == 0) { *comparison = 0; return PCSL_STRING_OK; } /* Damaged strings */ if ((str1->data == NULL && str1->length > 0) || (str2->data == NULL && str2->length > 0)) { return PCSL_STRING_EINVAL; } { const jsize min_length = str1->length < str2->length ? str1->length : str2->length; jint cmp = 0; if (min_length > 1) { /* length = 1 in case of empty string */ cmp = memcmp(str1->data, str2->data, sizeof(jchar) * min_length); } if (cmp == 0) { cmp = str1->length - str2->length; } * comparison = cmp; return PCSL_STRING_OK; }}/** * Creates a new string that is a concatenation of the two specified strings. * NULL string is interpreted as empty string * * @param str1 first string to concatenate * @param str2 second string to concatenate * @param dst storage for the created concatenation * @return status of the operation */pcsl_string_status pcsl_string_cat(const pcsl_string * str1, const pcsl_string * str2, pcsl_string * str) { pcsl_string *src1; pcsl_string *src2; if (str == NULL) { return PCSL_STRING_EINVAL; } if (str1 == NULL) { src1 = (pcsl_string *)&PCSL_STRING_EMPTY; } else { src1 = (pcsl_string *)str1; if (src1->length > 0 && src1->data == NULL) { return PCSL_STRING_EINVAL; } } if (str2 == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -