GophHub - kevinboone/epub2txt2/src/custom_string.c


Raw File

    1	/*============================================================================
    2	  epub2txt v2 
    3	  string.c
    4	  Copyright (c)2020 Kevin Boone, GPL v3.0
    5	============================================================================*/
    6	
    7	#define _GNU_SOURCE
    8	#include <stdio.h>
    9	#include <stdlib.h>
   10	#include <memory.h>
   11	
   12	#if !defined(__MACH__)
   13	#include <malloc.h>
   14	#endif
   15	
   16	#include <pthread.h>
   17	#include <stdint.h>
   18	#include <stdarg.h>
   19	#include <errno.h>
   20	#include <sys/types.h>
   21	#include <sys/stat.h>
   22	#include <fcntl.h>
   23	#include <unistd.h>
   24	#include <ctype.h>
   25	#include "custom_string.h" 
   26	#include "defs.h" 
   27	#include "log.h" 
   28	
   29	struct _String
   30	  {
   31	  char *str;
   32	  }; 
   33	
   34	
   35	/*==========================================================================
   36	string_create_empty 
   37	*==========================================================================*/
   38	String *string_create_empty (void)
   39	  {
   40	  return string_create ("");
   41	  }
   42	
   43	
   44	/*==========================================================================
   45	string_create
   46	*==========================================================================*/
   47	String *string_create (const char *s)
   48	  {
   49	  String *self = malloc (sizeof (String));
   50	  self->str = strdup (s);
   51	  return self;
   52	  }
   53	
   54	
   55	/*==========================================================================
   56	string_destroy
   57	*==========================================================================*/
   58	void string_destroy (String *self)
   59	  {
   60	  if (self)
   61	    {
   62	    if (self->str) free (self->str);
   63	    free (self);
   64	    }
   65	  }
   66	
   67	
   68	/*==========================================================================
   69	string_cstr
   70	*==========================================================================*/
   71	const char *string_cstr (const String *self)
   72	  {
   73	  return self->str;
   74	  }
   75	
   76	
   77	/*==========================================================================
   78	string_cstr_safe
   79	*==========================================================================*/
   80	const char *string_cstr_safe (const String *self)
   81	  {
   82	  if (self)
   83	    {
   84	    if (self->str) 
   85	      return self->str;
   86	    else
   87	      return "";
   88	    }
   89	  else
   90	    return "";
   91	  }
   92	
   93	
   94	/*==========================================================================
   95	string_append
   96	*==========================================================================*/
   97	void string_append (String *self, const char *s) 
   98	  {
   99	  if (!s) return;
  100	  if (self->str == NULL) self->str = strdup ("");
  101	  int newlen = strlen (self->str) + strlen (s) + 2;
  102	  self->str = realloc (self->str, newlen);
  103	  strcat (self->str, s);
  104	  }
  105	
  106	
  107	/*==========================================================================
  108	string_prepend
  109	*==========================================================================*/
  110	void string_prepend (String *self, const char *s) 
  111	  {
  112	  if (!s) return;
  113	  if (self->str == NULL) self->str = strdup ("");
  114	  int newlen = strlen (self->str) + strlen (s) + 2;
  115	  char *temp = strdup (self->str); 
  116	  free (self->str);
  117	  self->str = malloc (newlen);
  118	  strcpy (self->str, s);
  119	  strcat (self->str, temp);
  120	  free (temp);
  121	  }
  122	
  123	
  124	/*==========================================================================
  125	string_append_printf
  126	*==========================================================================*/
  127	void string_append_printf (String *self, const char *fmt,...) 
  128	  {
  129	  if (self->str == NULL) self->str = strdup ("");
  130	  va_list ap;
  131	  va_start (ap, fmt);
  132	  char *s;
  133	  vasprintf (&s, fmt, ap);
  134	  string_append (self, s);
  135	  free (s);
  136	  va_end (ap);
  137	  }
  138	
  139	
  140	/*==========================================================================
  141	string_length
  142	*==========================================================================*/
  143	int string_length (const String *self)
  144	  {
  145	  if (self == NULL) return 0;
  146	  if (self->str == NULL) return 0;
  147	  return strlen (self->str);
  148	  }
  149	
  150	
  151	/*==========================================================================
  152	string_clone
  153	*==========================================================================*/
  154	String *string_clone (const String *self)
  155	  {
  156	  if (!self) return NULL;
  157	  if (!self->str) return string_create_empty();
  158	  return string_create (string_cstr (self));
  159	  }
  160	
  161	
  162	/*==========================================================================
  163	string_find
  164	*==========================================================================*/
  165	int string_find (const String *self, const char *search)
  166	  {
  167	  if (!self) return -1;
  168	  if (!self->str) return -1;
  169	  const char *p = strstr (self->str, search);
  170	  if (p)
  171	    return p - self->str;
  172	  else
  173	    return -1;
  174	  }
  175	
  176	
  177	/*==========================================================================
  178	string_delete
  179	*==========================================================================*/
  180	void string_delete (String *self, const int pos, const int len)
  181	  {
  182	  char *str = self->str;
  183	  if (pos + len > strlen (str))
  184	    string_delete (self, pos, strlen(str) - len);
  185	  else
  186	    {
  187	    char *buff = malloc (strlen (str) - len + 2);
  188	    strncpy (buff, str, pos); 
  189	    strcpy (buff + pos, str + pos + len);
  190	    free (self->str);
  191	    self->str = buff;
  192	    }
  193	  }
  194	
  195	
  196	/*==========================================================================
  197	string_insert
  198	*==========================================================================*/
  199	void string_insert (String *self, const int pos, 
  200	    const char *replace)
  201	  {
  202	  char *buff = malloc (strlen (self->str) + strlen (replace) + 2);
  203	  char *str = self->str;
  204	  strncpy (buff, str, pos);
  205	  buff[pos] = 0;
  206	  strcat (buff, replace);
  207	  strcat (buff, str + pos); 
  208	  free (self->str);
  209	  self->str = buff;
  210	  }
  211	
  212	
  213	
  214	/*==========================================================================
  215	string_substitute_all
  216	*==========================================================================*/
  217	String *string_substitute_all (const String *self, 
  218	    const char *search, const char *replace)
  219	  {
  220	  String *working = string_clone (self);
  221	  BOOL cont = TRUE;
  222	  while (cont)
  223	    {
  224	    int i = string_find (working, search);
  225	    if (i >= 0)
  226	      {
  227	      string_delete (working, i, strlen (search));
  228	      string_insert (working, i, replace);
  229	      }
  230	    else
  231	      cont = FALSE;
  232	    }
  233	  return working;
  234	  }
  235	
  236	
  237	/*==========================================================================
  238	  string_create_from_utf8_file 
  239	*==========================================================================*/
  240	BOOL string_create_from_utf8_file (const char *filename, 
  241	    String **result, char **error)
  242	  {
  243	  String *self = NULL;
  244	  BOOL ok = FALSE; 
  245	  int f = open (filename, O_RDONLY);
  246	  if (f > 0)
  247	    {
  248	    self = malloc (sizeof (String));
  249	    struct stat sb;
  250	    fstat (f, &sb);
  251	    int64_t size = sb.st_size;
  252	    char *buff = malloc (size + 2);
  253	    self->str = buff; 
  254	
  255	    // Read the first three characters, to check for a UTF-8 byte-order-mark
  256	    read (f, buff, 3);
  257	    if (buff[0] == (char)0xEF && buff[1] == (char)0xBB && buff[2] == (char)0xBF)
  258	      {
  259	      read (f, buff, size - 3);
  260	      self->str[size - 3] = 0;
  261	      }
  262	    else
  263	      {
  264	      read (f, buff + 3, size - 3);
  265	      self->str[size] = 0;
  266	      }
  267	
  268	    *result = self;
  269	    ok = TRUE;
  270	    }
  271	  else
  272	    {
  273	    asprintf (error, "Can't open file '%s' for reading: %s", 
  274	      filename, strerror (errno));
  275	    ok = FALSE;
  276	    }
  277	
  278	  return ok;
  279	  }
  280	
  281	
  282	/*==========================================================================
  283	  string_encode_url
  284	*==========================================================================*/
  285	static char to_hex(char code)
  286	  {
  287	  static char hex[] = "0123456789abcdef";
  288	  return hex[code & 15];
  289	  }
  290	
  291	
  292	String *string_encode_url (const char *str)
  293	  {
  294	  if (!str) return string_create_empty();;
  295	  const char *pstr = str; 
  296	  char *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
  297	  while (*pstr)
  298	    {
  299	    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_'
  300	      || *pstr == '.' || *pstr == '~')
  301	      *pbuf++ = *pstr;
  302	    else if (*pstr == ' ')
  303	      *pbuf++ = '+';
  304	    else
  305	      *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4),
  306	         *pbuf++ = to_hex(*pstr & 15);
  307	    pstr++;
  308	    }
  309	  *pbuf = '\0';
  310	  String *result = string_create (buf);
  311	  free (buf);
  312	  return (result);
  313	  }
  314	
  315	
  316	/*==========================================================================
  317	  string_append_byte
  318	*==========================================================================*/
  319	void string_append_byte (String *self, const BYTE byte)
  320	  {
  321	  char buff[2];
  322	  buff[0] = byte;
  323	  buff[1] = 0;
  324	  string_append (self, buff);
  325	  }
  326	
  327	
  328	/*==========================================================================
  329	  string_append_c
  330	*==========================================================================*/
  331	void string_append_c (String *self, const uint32_t ch)
  332	  {
  333	  if (ch < 0x80) 
  334	    {
  335	    string_append_byte (self, (BYTE)ch);
  336	    }
  337	  else if (ch < 0x0800) 
  338	    {
  339	    string_append_byte (self, (BYTE)((ch >> 6) | 0xC0));
  340	    string_append_byte (self, (BYTE)((ch & 0x3F) | 0x80));
  341	    }
  342	  else if (ch < 0x10000) 
  343	    {
  344	    string_append_byte (self, (BYTE)((ch >> 12) | 0xE0));
  345	    string_append_byte (self, (BYTE)((ch >> 6 & 0x3F) | 0x80));
  346	    string_append_byte (self, (BYTE)((ch & 0x3F) | 0x80));
  347	    }
  348	  else 
  349	    {
  350	    string_append_byte (self, (BYTE)((ch >> 18) | 0xF0));
  351	    string_append_byte (self, (BYTE)(((ch >> 12) & 0x3F) | 0x80));
  352	    string_append_byte (self, (BYTE)(((ch >> 6) & 0x3F) | 0x80));
  353	    string_append_byte (self, (BYTE)((ch & 0x3F) | 0x80));
  354	    }
  355	  }
  356	
  357	
  358	
  359	
  360	

Generated by GNU Enscript 1.6.6, and GophHub 1.3.