📄 gbx_string.c
字号:
/*************************************************************************** String.c The String management routines (c) 2000-2004 Beno� Minisini <gambas@users.sourceforge.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. 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 for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __STRING_C#include "gb_common.h"#include "gb_common_buffer.h"#include "gb_error.h"#include "gbx_value.h"#include "gbx_debug.h"#include "gbx_local.h"#include <ctype.h>#include <iconv.h>#include "gbx_string.h"#if DEBUG_STRING#define DEBUG_ME#endif#define STRING_last_count 32PRIVATE char *STRING_last[STRING_last_count] = { 0 };PRIVATE char _char_string[512] = { 0 };PRIVATE int _index = 0;void STRING_new(char **ptr, const char *src, int len){ STRING *str; if (len <= 0 && src != NULL) len = strlen(src); if (len <= 0) { *ptr = NULL; return; } ALLOC(&str, len + 1 + sizeof(STRING), "STRING_new"); str->len = len; str->ref = 1; if (src != NULL) memcpy(str->data, src, len); str->data[len] = 0; *ptr = str->data; #ifdef DEBUG_ME TRACE_where(); printf("STRING_new %p ( 0 ) \"%.*s\"\n", *ptr, len, src); fflush(NULL); #endif}PRIVATE void post_free(char *ptr){ /*if (NLast >= MAX_LAST_STRING) THROW(E_STRING);*/ #ifdef DEBUG_ME if (STRING_last[_index]) { TRACE_where(); printf("STRING: release temp: %p '%s'\n", STRING_last[_index], STRING_last[_index]); fflush(NULL); } #endif STRING_unref(&STRING_last[_index]); #ifdef DEBUG_ME printf("STRING: post temp: %p '%s'\n", ptr, ptr); fflush(NULL); #endif STRING_last[_index] = ptr; _index++; if (_index >= STRING_last_count) _index = 0;}PUBLIC long STRING_get_free_index(void){ return _index;}void STRING_new_temp(char **ptr, const char *src, int len){ STRING_new(ptr, src, len); if (*ptr) post_free(*ptr);}void STRING_exit(void){ int i; for (i = 0; i < STRING_last_count; i++) { /*if (STRING_last[i]) printf("release temp %p '%s'\n", STRING_last[i], STRING_last[i]);*/ STRING_unref(&STRING_last[i]); STRING_last[i] = NULL; } _index = 0;}void STRING_extend(char **ptr, int new_len){ STRING *str; long len = STRING_length(*ptr); if (new_len == len) return; if (new_len == 0) { STRING_free(ptr); return; } if (len == 0) { ALLOC(&str, new_len + 1 + sizeof(STRING), "STRING_extend"); str->ref = 1; } else { str = STRING_from_ptr(*ptr); REALLOC(&str, new_len + 1 + sizeof(STRING), "STRING_extend"); } str->len = new_len; *ptr = str->data;}void STRING_extend_end(char **ptr){ if (*ptr) { (*ptr)[STRING_length(*ptr)] = 0; post_free(*ptr); }}void STRING_copy_from_value_temp(char **ptr, VALUE *value){ if (value->_string.len == 0) *ptr = NULL; else if (value->type == T_STRING && value->_string.start == 0 && value->_string.len == STRING_length(value->_string.addr)) *ptr = value->_string.addr; else STRING_new_temp(ptr, &value->_string.addr[value->_string.start], value->_string.len);}/* Attention ! Contrairement �STRING_new, STRING_new_temp_value cr� des cha�es temporaires.*/void STRING_new_temp_value(VALUE *value, const char *src, int len){ STRING_new_temp(&(value->_string.addr), src, len); value->_string.len = STRING_length(value->_string.addr); value->_string.start = 0; value->type = T_STRING;}void STRING_new_constant_value(VALUE *value, const char *src, int len){ value->_string.addr = (char *)src; value->_string.len = ((len < 0) ? strlen(src) : len); value->_string.start = 0; value->type = T_CSTRING;}void STRING_void_value(VALUE *value){ value->type = T_CSTRING; value->_string.addr = NULL; value->_string.start = 0; value->_string.len = 0;}void STRING_char_value(VALUE *value, uchar car){ char *addr = &_char_string[(int)car * 2]; value->type = T_CSTRING; value->_string.addr = addr; value->_string.start = 0; value->_string.len = 1; *addr = car;}void STRING_free(char **ptr){ STRING *str; if (*ptr == NULL) return; str = STRING_from_ptr(*ptr); #ifdef DEBUG_ME TRACE_where(); printf("STRING_free %p %p\n", *ptr, ptr); fflush(NULL); #endif str->ref = 1000000000L; FREE(&str, "STRING_free"); *ptr = NULL; #ifdef DEBUG_ME printf("OK\n"); #endif}int STRING_comp_value(VALUE *str1, VALUE *str2){ long i; long len = Min(str1->_string.len, str2->_string.len); long diff = str1->_string.len - str2->_string.len; const char *s1; const char *s2; s1 = str1->_string.addr + str1->_string.start; s2 = str2->_string.addr + str2->_string.start; for (i = 0; i < len; i++) { if (*s1 > *s2) return 1; if (*s1 < *s2) return -1; s1++; s2++; } return (diff < 0) ? (-1) : (diff > 0) ? 1 : 0;}void STRING_ref(char *ptr){ STRING *str; if (ptr == NULL) return; str = STRING_from_ptr(ptr); #ifdef DEBUG_ME TRACE_where(); printf("STRING_ref %p ( %ld -> %ld )\n", ptr, str->ref, str->ref + 1); if (str->ref < 0 || str->ref > 10000) printf("*** BAD\n"); fflush(NULL); #endif str->ref++;}void STRING_unref(char **ptr){ STRING *str; if (*ptr == NULL) return; str = STRING_from_ptr(*ptr); #ifdef DEBUG_ME TRACE_where(); printf("STRING_unref %p ( %ld -> %ld )\n", *ptr, str->ref, str->ref - 1); if (str->ref < 1 || str->ref > 10000) printf("*** BAD\n"); fflush(NULL); #endif if ((--str->ref) <= 0) STRING_free(ptr);}void STRING_unref_keep(char **ptr){ STRING *str; if (*ptr == NULL) return; str = STRING_from_ptr(*ptr); if (str->ref > 1) str->ref--; else post_free(*ptr);}PUBLIC char *STRING_subst(const char *string, long len, SUBST_FUNC get_param){ const char *add; long len_add; unsigned char c; int np; char *par; long len_par; unsigned char next_char(void) { len--; return (unsigned char)*string++; } if (!string) return NULL; SUBST_init(); if (len <= 0) len = strlen(string); if (len > 0) { add = string; len_add = 0; for(;;) { if (len == 0) { SUBST_add(add, len_add); break; } c = next_char(); if (c != '&') { len_add++; continue; } SUBST_add(add, len_add); add = string; len_add = 0; c = next_char(); if (!isdigit(c)) { if (c == '&') { add++; len_add++; } else len_add += 2; continue; } np = (c - '0'); c = *string; if (isdigit(c)) { np = np * 10 + c - '0'; next_char(); } par = NULL; len_par = 0; (*get_param)(np, &par, &len_par); if (par) SUBST_add(par, len_par); add = string; } } /* Avant, les release de SUBR_subst s'effectuaient ici... */ SUBST_exit(); return SUBST_buffer();}PUBLIC void STRING_add(char **ptr, const char *src, int len){ int old_len; if (len <= 0 && src != NULL) len = strlen(src); if (len <= 0) return; old_len = STRING_length(*ptr); STRING_extend(ptr, old_len + len); memcpy(&((*ptr)[old_len]), src, len); (*ptr)[old_len + len] = 0;}PUBLIC void STRING_conv(char **result, const char *str, long len, const char *src, const char *dst){ iconv_t handle; bool err; const char *in; char *out; size_t in_len; size_t out_len; int ret; *result = NULL; in = str; in_len = len; if (len == 0) return; if (!dst || *dst == 0) dst = "ASCII"; if (!src || *src == 0) src = "ASCII"; handle = iconv_open(dst, src); if (handle == (iconv_t)(-1)) { if (errno == EINVAL) THROW(E_UCONV); else THROW(E_CONV); } err = FALSE; for(;;) { out = COMMON_buffer; out_len = COMMON_BUF_MAX; #ifdef __sun__ ret = iconv(handle, &in, &in_len, &out, &out_len); #else ret = iconv(handle, (char **)&in, &in_len, &out, &out_len); #endif if (ret != (size_t)(-1 ) || errno == E2BIG) STRING_add(result, COMMON_buffer, COMMON_BUF_MAX - out_len); if (ret != (size_t)(-1)) break; if (errno != E2BIG) { err = TRUE; break; } } iconv_close(handle); STRING_extend_end(result); if (err) THROW(E_CONV);}PUBLIC char *STRING_conv_file_name(const char *name, long len){ char *result = NULL; if (!name) return ""; if (len <= 0) len = strlen(name); if (LOCAL_is_UTF8) STRING_new_temp(&result, name, len); else STRING_conv(&result, name, len, "UTF-8", LOCAL_encoding); if (result) return result; else return "";}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -