dynamic strings

This commit is contained in:
Ian Jauslin 2023-11-03 12:25:02 -04:00
parent 3d94694017
commit dd9bd74c83
2 changed files with 319 additions and 0 deletions

243
src/dstring.c Normal file
View File

@ -0,0 +1,243 @@
/*
Copyright 2017-2023 Ian Jauslin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "dstring.h"
#include <stdarg.h>
#include <stdlib.h>
// init
int dstring_init (dstring* str, unsigned int memory){
str->string=calloc(memory,sizeof(char));
str->memory=memory;
str->length=0;
return(0);
}
int dstring_free (dstring str){
free(str.string);
return(0);
}
// resize memory
int dstring_resize (dstring* str, unsigned int newsize){
unsigned int i;
dstring new_str;
dstring_init (&new_str, newsize);
for(i=0;i<str->length;i++){
new_str.string[i]=str->string[i];
}
new_str.length=str->length;
free(str->string);
*str=new_str;
return(0);
}
// add a character
int dstring_append (char val, dstring* output){
if(output->length >= output->memory){
dstring_resize (output,2*output->memory+1);
}
output->string[output->length]=val;
output->length++;
return(0);
}
// copy
int dstring_cpy (dstring input, dstring* output){
dstring_init (output, input.length);
dstring_cpy_noinit (input, output);
return(0);
}
// do not init output str
int dstring_cpy_noinit (dstring input, dstring* output){
unsigned int i;
if(output->memory<input.length){
fprintf(stderr,"error: cannot copy a dstring of length %u to a dstring with memory %u\n",input.length,output->memory);
return(-1);
}
for(i=0;i<input.length;i++){
output->string[i]=input.string[i];
}
output->length=input.length;
return(0);
}
// concatenate
int dstring_concat (dstring input, dstring* output){
unsigned int i;
for(i=0;i<input.length;i++){
dstring_append (input.string[i], output);
}
return(0);
}
// sub-str
int dstring_substr (dstring str, unsigned int begin, unsigned int end, dstring* substr){
unsigned int i;
if(begin>end || end>=str.length){
fprintf(stderr,"error: cannot take substring [%u,%u] of dstring of lengdth %u\n",begin,end,str.length);
return(-1);
}
dstring_init (substr,end-begin);
for(i=begin;i<=end;i++){
dstring_append (str.string[i], substr);
}
return(0);
}
// find
int dstring_find (char val, dstring str){
unsigned int i;
for(i=0;i<str.length;i++){
if(str.string[i]==val){
return(i);
}
}
return(-1);
}
// compare strings
int dstring_cmp (dstring str1, dstring str2){
unsigned int i;
// compare lengths
if(str1.length<str2.length){
return(-1);
}
if(str1.length>str2.length){
return(1);
}
// compare terms
for(i=0;i<str1.length;i++){
if(str1.string[i]<str2.string[i]){
return(-1);
}
if(str1.string[i]<str2.string[i]){
return(1);
}
}
// if equal
return(0);
}
// print str
int dstring_print (dstring str, FILE* file){
unsigned int i;
for(i=0;i<str.length;i++){
fprintf(file, "%s",str.string);
}
return(0);
}
// append a char*
int dstring_append_str(char* str, dstring* output){
char* ptr;
for (ptr=str;*ptr!='\0';ptr++){
dstring_append(*ptr, output);
}
return(0);
}
// convert to char*
int dstring_to_str(dstring input, char** output){
unsigned int i;
(*output)=calloc(input.length+1,sizeof(char));
for(i=0;i<input.length;i++){
(*output)[i]=input.string[i];
}
if((*output)[input.length-1]!='\0'){
(*output)[input.length]='\0';
}
return(0);
}
// noinit (changes the size of input if needed)
char* dstring_to_str_noinit(dstring* input){
if(input->string[input->length-1]!='\0'){
if(input->length==input->memory){
dstring_resize(input,input->length+1);
}
// add final '\0'
input->string[input->length]='\0';
}
return(input->string);
}
// convert from char*
int str_to_dstring(char* str, dstring* output){
char* ptr;
unsigned int str_len=0;
for(ptr=str;*ptr!='\0';ptr++){
str_len++;
}
dstring_init(output, str_len);
for(ptr=str;*ptr!='\0';ptr++){
dstring_append(*ptr,output);
}
return(0);
}
// compare a dstring and a char*
int dstring_cmp_str(dstring dstring, char* str){
unsigned int j;
for(j=0;j<dstring.length && str[j]!='\0';j++){
if(dstring.string[j]!=str[j]){
return(0);
}
}
if(j==dstring.length && str[j]=='\0'){
return(1);
}
return(0);
}
// format strings
int dstring_snprintf(dstring* output, char* fmt, ...){
size_t size=100;
unsigned int extra_size;
char* out_str=calloc(size,sizeof(char));
char* ptr;
va_list vaptr;
// initialize argument list starting after fmt
va_start(vaptr, fmt);
// print format
extra_size=vsnprintf(out_str, size, fmt, vaptr);
va_end(vaptr);
// if too large
if(extra_size>size){
// resize
free(out_str);
// +1 for '\0'
size=extra_size+1;
out_str=calloc(size,sizeof(char));
// read format again
va_start(vaptr, fmt);
vsnprintf(out_str,size,fmt,vaptr);
va_end(vaptr);
}
// write to char array
for(ptr=out_str;*ptr!='\0';ptr++){
dstring_append(*ptr, output);
}
free(out_str);
return(0);
}

76
src/dstring.h Normal file
View File

@ -0,0 +1,76 @@
/*
Copyright 2017-2023 Ian Jauslin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef DSTRING_H
#define DSTRING_H
#include <stdio.h>
typedef struct dstring {
char* string;
unsigned int length;
unsigned int memory;
} dstring;
// init
int dstring_init (dstring* str, unsigned int memory);
int dstring_free (dstring str);
// resize memory
int dstring_resize (dstring* str, unsigned int newsize);
// add a character
int dstring_append (char val, dstring* output);
// copy
int dstring_cpy (dstring input, dstring* output);
// do not init output str
int dstring_cpy_noinit (dstring input, dstring* output);
// concatenate
int dstring_concat (dstring input, dstring* output);
// sub-str
int dstring_substr (dstring str, unsigned int begin, unsigned int end, dstring* substr);
// find
int dstring_find (char val, dstring str);
// compare strings
int dstring_cmp (dstring str1, dstring str2);
// print str
int dstring_print (dstring str, FILE* file);
// append a char*
int dstring_append_str(char* str, dstring* output);
// convert to char*
int dstring_to_str(dstring input, char** output);
// noinit (changes the size of input if needed)
char* dstring_to_str_noinit(dstring* input);
// convert from char*
int str_to_dstring(char* str, dstring* output);
// compare a dstring and a char*
int dstring_cmp_str(dstring dstring, char* str);
// format strings
int dstring_snprintf(dstring* output, char* fmt, ...);
#endif