dynamic strings
This commit is contained in:
		
							
								
								
									
										243
									
								
								src/dstring.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								src/dstring.c
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										76
									
								
								src/dstring.h
									
									
									
									
									
										Normal 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
 | 
			
		||||
		Reference in New Issue
	
	Block a user