Subversion Repositories Kolibri OS

Rev

Rev 1905 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.         stringbuf: mimicking a bit of C++ to more safely handle strings
  3.  
  4.         copyright 2006-10 by the mpg123 project - free software under the terms of the LGPL 2.1
  5.         see COPYING and AUTHORS files in distribution or http://mpg123.org
  6.         initially written by Thomas Orgis
  7. */
  8.  
  9. #include "mpg123lib_intern.h"
  10. #include "config.h"
  11. #include "mpg123.h"
  12. #include "compat.h"
  13. #include <string.h>
  14. #include "debug.h"
  15.  
  16. void attribute_align_arg mpg123_init_string(mpg123_string* sb)
  17. {
  18.         sb->p = NULL;
  19.         sb->size = 0;
  20.         sb->fill = 0;
  21. }
  22.  
  23. void attribute_align_arg mpg123_free_string(mpg123_string* sb)
  24. {
  25.         if(sb->p != NULL) free(sb->p);
  26.         mpg123_init_string(sb);
  27. }
  28.  
  29. int attribute_align_arg mpg123_grow_string(mpg123_string* sb, size_t new)
  30. {
  31.         if(sb->size < new) return mpg123_resize_string(sb, new);
  32.         else return 1;
  33. }
  34.  
  35. int attribute_align_arg mpg123_resize_string(mpg123_string* sb, size_t new)
  36. {
  37.         debug3("resizing string pointer %p from %lu to %lu", (void*) sb->p, (unsigned long)sb->size, (unsigned long)new);
  38.         if(new == 0)
  39.         {
  40.                 if(sb->size && sb->p != NULL) free(sb->p);
  41.                 mpg123_init_string(sb);
  42.                 return 1;
  43.         }
  44.         if(sb->size != new)
  45.         {
  46.                 char* t;
  47.                 debug("really!");
  48.                 t = (char*) safe_realloc(sb->p, new*sizeof(char));
  49.                 debug1("safe_realloc returned %p", (void*) t);
  50.                 if(t != NULL)
  51.                 {
  52.                         sb->p = t;
  53.                         sb->size = new;
  54.                         return 1;
  55.                 }
  56.                 else return 0;
  57.         }
  58.         else return 1; /* success */
  59. }
  60.  
  61. int attribute_align_arg mpg123_copy_string(mpg123_string* from, mpg123_string* to)
  62. {
  63.         size_t fill;
  64.         char  *text;
  65.         if(to == NULL) return -1;
  66.  
  67.         debug2("called copy_string with %p -> %p", (void*)from, (void*)to);
  68.         if(from == NULL)
  69.         {
  70.                 fill = 0;
  71.                 text = NULL;
  72.         }
  73.         else
  74.         {
  75.                 fill = from->fill;
  76.                 text = from->p;
  77.         }
  78.  
  79.         if(mpg123_resize_string(to, fill))
  80.         {
  81.                 memcpy(to->p, text, fill);
  82.                 to->fill = fill;
  83.                 return 1;
  84.         }
  85.         else return 0;
  86. }
  87.  
  88. int attribute_align_arg mpg123_add_string(mpg123_string* sb, const char* stuff)
  89. {
  90.         debug1("adding %s", stuff);
  91.         return mpg123_add_substring(sb, stuff, 0, strlen(stuff));
  92. }
  93.  
  94. int attribute_align_arg mpg123_add_substring(mpg123_string *sb, const char *stuff, size_t from, size_t count)
  95. {
  96.         debug("adding a substring");
  97.         if(sb->fill) /* includes zero byte... */
  98.         {
  99.                 if( (SIZE_MAX - sb->fill >= count) /* Avoid overflow. */
  100.                     && (sb->size >= sb->fill+count || mpg123_grow_string(sb, sb->fill+count)) )
  101.                 {
  102.                         memcpy(sb->p+sb->fill-1, stuff+from, count);
  103.                         sb->fill += count;
  104.                         sb->p[sb->fill-1] = 0; /* Terminate! */
  105.                 }
  106.                 else return 0;
  107.         }
  108.         else
  109.         {
  110.                 if( count < SIZE_MAX && mpg123_grow_string(sb, count+1) )
  111.                 {
  112.                         memcpy(sb->p, stuff+from, count);
  113.                         sb->fill = count+1;
  114.                         sb->p[sb->fill-1] = 0; /* Terminate! */
  115.                 }
  116.                 else return 0;
  117.         }
  118.         return 1;
  119. }
  120.  
  121. int attribute_align_arg mpg123_set_substring(mpg123_string* sb, const char* stuff, size_t from, size_t count)
  122. {
  123.         sb->fill = 0;
  124.         return mpg123_add_substring(sb, stuff, from, count);
  125. }
  126.  
  127. int attribute_align_arg mpg123_set_string(mpg123_string* sb, const char* stuff)
  128. {
  129.         sb->fill = 0;
  130.         return mpg123_add_string(sb, stuff);
  131. }
  132.  
  133. size_t attribute_align_arg mpg123_strlen(mpg123_string *sb, int utf8)
  134. {
  135.         size_t i;
  136.         size_t bytelen;
  137.  
  138.         /* Notions of empty string. If there's only a single character, it has to be the trailing zero, and if the first is the trailing zero anyway, we got empty. */
  139.         if(sb->fill < 2 || sb->p[0] == 0) return 0;
  140.  
  141.         /* Find the first non-null character from the back.
  142.            We already established that the first character is non-null
  143.            That at fill-2 has to be null, though. */
  144.         for(i=sb->fill-2; i>0; --i)
  145.         if(sb->p[i] != 0) break;
  146.  
  147.         /* For simple byte strings, we are done now. */
  148.         bytelen = i+1;
  149.  
  150.         if(!utf8) return bytelen;
  151.         else
  152.         {
  153.                 /* Work out the actual count of UTF8 bytes.
  154.                    This employs no particular encoding error checking. */
  155.                 size_t len = 0;
  156.                 for(i=0; i<bytelen; ++i)
  157.                 {
  158.                         /* Every byte that is not a continuation byte ( 0xc0 == 10xx xxxx ) stands for a character. */
  159.                         if((sb->p[i] & 0xc0) != 0x80) len++;
  160.                 }
  161.                 return len;
  162.         }
  163. }
  164.  
  165. int attribute_align_arg mpg123_chomp_string(mpg123_string *sb)
  166. {
  167.         ssize_t i;
  168.         if(!sb || !sb->fill) return 0;
  169.  
  170.         /* Ensure that it is zero-terminated. */
  171.         sb->p[sb->fill-1] = 0;
  172.         for(i=sb->fill-2; i>=0; --i)
  173.         {
  174.                 char *c = sb->p+i;
  175.                 /* Stop at the first proper character. */
  176.                 if(*c && *c != '\r' && *c != '\n') break;
  177.                 else *c = 0;
  178.         }
  179.         /* initial fill at least 1, so i at least -1,
  180.            +2 means nothing happened for fill=1 .
  181.            With i=0, we got one non-null character, fill shall be 2
  182.            to accomodate the trailing zero. */
  183.         sb->fill = (size_t)i+2;
  184.  
  185.         return 1;
  186. }
  187.