📄 string.c
字号:
/* Copyright (C) (2007) (Benoit Favre) <favre@icsi.berkeley.edu>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 2 of the License, 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "string.h"#include "utils/hashtable.h"#include <math.h>string_t* string_resize(string_t* input,size_t newSize){ if(newSize==input->size)return input; input->data=REALLOC(input->data,newSize); input->size=newSize; return input;}string_t* string_new(const char* string){ size_t length=strlen(string); string_t* output=(string_t*)MALLOC(sizeof(string_t));#ifdef USE_GC output->data=GC_MALLOC_ATOMIC(length+1);#else output->data=MALLOC(length+1);#endif output->length=length; output->size=length+1; memcpy(output->data,string,length+1); return output;}string_t* string_new_empty(){ size_t length=0; string_t* output=(string_t*)MALLOC(sizeof(string_t));#ifdef USE_GC output->data=GC_MALLOC_ATOMIC(length+1);#else output->data=MALLOC(length+1);#endif output->length=length; output->size=length+1; *output->data='\0'; return output;}string_t* string_new_from_to(const char* string,size_t from, size_t to){ size_t length=to-from; if(length<0) { length=0; } string_t* output=(string_t*)MALLOC(sizeof(string_t));#ifdef USE_GC output->data=GC_MALLOC_ATOMIC(length+1);#else output->data=MALLOC(length+1);#endif output->length=length; output->size=length+1; memcpy(output->data,string+from,length); *(output->data+length)='\0'; return output;}string_t* string_copy(string_t* input){ string_t* output=string_new(input->data); return output;}string_t* string_append_cstr(string_t* input, const char* peer){ size_t length=strlen(peer); string_resize(input,input->length+length+1); memcpy(input->data+input->length,peer,length+1); input->length+=length; return input;}string_t* string_prepend_cstr(string_t* input, const char* peer){ size_t length=strlen(peer); string_resize(input,input->length+length+1); memmove(input->data+length,input->data,input->length+1); memcpy(input->data,peer,length); input->length+=length; return input;}string_t* string_append(string_t* input, string_t* peer){ string_resize(input,input->length+peer->length+1); memcpy(input->data+input->length,peer->data,peer->length+1); input->length+=peer->length; return input;}string_t* string_prepend(string_t* input, string_t* peer){ string_resize(input,input->length+peer->length+1); memmove(input->data+peer->length,input->data,input->length+1); memcpy(input->data,peer->data,peer->length); input->length+=peer->length; return input;}void string_free(string_t* input){ FREE(input->data); FREE(input);}string_t* string_substr(string_t* input,size_t from,size_t to){ if(to<from || from<0 || to>input->length)return NULL; string_t* output=(string_t*)MALLOC(sizeof(string_t));#ifdef USE_GC output->data=GC_MALLOC_ATOMIC(to-from+1);#else output->data=MALLOC(to-from+1);#endif output->length=to-from; output->size=to-from+1; memcpy(output->data,input->data+from,to-from); *(output->data+output->length)='\0'; return output;}string_t* string_reverse(string_t* input){ size_t i=0; size_t j=input->length-1; for(;i<input->length/2;i++) { char tmp=input->data[i]; input->data[i]=input->data[j]; input->data[j]=tmp; j--; } return input;}string_t* string_chomp(string_t* input){ size_t i=input->length; while(i>0 && (input->data[i-1]=='\n' || input->data[i-1]=='\r'))i--; if(i>0 && i<input->length)input->data[i]='\0'; input->length=i; return input;}array_t* string_array_chomp(array_t* input){ int i=0; for(i=0; i<input->length; i++) string_chomp((string_t*)array_get(input, i)); return input;}string_t* string_join(string_t* separator, array_t* parts){ if(parts->first==NULL)return string_new(""); arrayelement_t* current=parts->first; // compute length size_t length=((string_t*)current->data)->length; current=current->next; do { length+=separator->length; length+=((string_t*)current->data)->length; current=current->next; } while(current); current=parts->first; string_t* output=string_copy((string_t*)current->data); string_resize(output,length+1); char* output_cstr=output->data+output->length; current=current->next; while(current) { memcpy(output_cstr,separator->data,separator->length); output_cstr+=separator->length; string_t* current_string=(string_t*)current->data; memcpy(output_cstr,current_string->data,current_string->length); output_cstr+=current_string->length; current=current->next; } *output_cstr='\0'; output->length=length; return output;}string_t* string_join_cstr(const char* separator, array_t* parts){ string_t* separator_string=string_new(separator); string_t* output=string_join(separator_string,parts); string_free(separator_string); return output;}typedef struct regexstatus { regex_t expression; //vector_t* groups; size_t start; size_t end; int flags; const char* replacement; vector_t* between_replacements; vector_t* replacement_mapping;} regexstatus_t;#define REGEX_FLAG_NONE 0#define REGEX_FLAG_GLOBAL (1<<0)#define REGEX_FLAG_CONTINUE (1<<1)#define REGEX_FLAG_CASE_INSENSITIVE (1<<2)#define REGEX_FLAG_MULTILINE (1<<3)#define REGEX_FLAG_ONCE (1<<4)#define REGEX_FLAG_NOSUB (1<<5)#define REGEX_FLAG_REVERSE (1<<6)void _regexstatus_free(regexstatus_t* status){ if(status->replacement_mapping!=NULL)vector_free(status->replacement_mapping); if(status->between_replacements!=NULL)string_vector_free(status->between_replacements); regfree(&status->expression); FREE(status);}#ifdef STRING_REGEX_USE_CACHEhashtable_t* _regex_cache=NULL;#endifregexstatus_t* _regexstatus_new(const char* pattern, const char* replacement, const char* flags_string){ regexstatus_t* status=NULL; int flags=REGEX_FLAG_NONE; if(flags_string!=NULL) { const char* current_flag=flags_string; while(current_flag && *current_flag!='\0') { switch(*current_flag) { case 'g': flags|=REGEX_FLAG_GLOBAL;break; case 'c': flags|=REGEX_FLAG_CONTINUE;break; case 'i': flags|=REGEX_FLAG_CASE_INSENSITIVE;break; case 'm': flags|=REGEX_FLAG_MULTILINE;break; case 'o': flags|=REGEX_FLAG_ONCE;break; case 'n': flags|=REGEX_FLAG_NOSUB;break; case '!': flags|=REGEX_FLAG_REVERSE;break; default: if(replacement==NULL) { die("invlid flag \"%c\", in m/%s/%s",*current_flag, pattern, flags_string); } else { die("invlid flag \"%c\", in s/%s/%s/%s",*current_flag, pattern, replacement, flags_string); } break; } current_flag++; } }#ifdef STRING_REGEX_USE_CACHE if((flags & REGEX_FLAG_ONCE) == 0) { if(_regex_cache==NULL) { _regex_cache=hashtable_new(); } else { status=hashtable_get(_regex_cache, pattern, strlen(pattern)); } }#endif if(status==NULL || ((status->flags & (REGEX_FLAG_CASE_INSENSITIVE|REGEX_FLAG_MULTILINE|REGEX_FLAG_NOSUB)) != (flags & (REGEX_FLAG_CASE_INSENSITIVE|REGEX_FLAG_MULTILINE|REGEX_FLAG_NOSUB)))) { if(status==NULL) { status=MALLOC(sizeof(regexstatus_t)); memset(status,0,sizeof(regexstatus_t));#ifdef STRING_REGEX_USE_CACHE if((flags & REGEX_FLAG_ONCE) == 0)hashtable_set(_regex_cache, pattern, strlen(pattern), status);#endif } else { regfree(&status->expression); } status->flags=flags; int regcomp_result=regcomp(&status->expression, pattern, (flags & REGEX_FLAG_CASE_INSENSITIVE ? REG_ICASE : 0) | (flags & REGEX_FLAG_MULTILINE ? REG_NEWLINE : 0) | (flags & REGEX_FLAG_NOSUB ? REG_NOSUB : 0) | REG_EXTENDED); if(regcomp_result!=0) { char buffer[1024]; regerror(regcomp_result, &status->expression, buffer, 1024); if(replacement==NULL) { die("compiling regex m/%s/%s, %s", pattern, flags_string, buffer); } else { die("compiling regex s/%s/%s/%s, %s", pattern, replacement, flags_string, buffer); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -