LCOV - code coverage report
Current view: top level - src - charbuf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 125 125 100.0 %
Date: 2016-12-21 02:12:01 Functions: 22 22 100.0 %

          Line data    Source code
       1             : /***************************************************************************//**
       2             : 
       3             :   @file         charbuf.c
       4             : 
       5             :   @author       Stephen Brennan
       6             : 
       7             :   @date         Saturday, 23 May 2015
       8             : 
       9             :   @brief        Implementation of "libstephen/cb.h".
      10             : 
      11             :   @copyright    Copyright (c) 2015-2016, Stephen Brennan.  Released under the
      12             :                 Revised BSD License.  See the LICENSE.txt file for details.
      13             : 
      14             : *******************************************************************************/
      15             : 
      16             : #include <stdarg.h>
      17             : #include <wchar.h>
      18             : #include <string.h>
      19             : 
      20             : #include "libstephen/base.h"
      21             : #include "libstephen/cb.h"
      22             : 
      23             : /*******************************************************************************
      24             : 
      25             :                                  cbuf Functions
      26             : 
      27             : *******************************************************************************/
      28             : 
      29          28 : void cb_init(cbuf *obj, int capacity)
      30             : {
      31             :   // Initialization logic
      32          28 :   obj->buf = smb_new(char, capacity);
      33          28 :   obj->buf[0] = '\0';
      34          28 :   obj->capacity = capacity;
      35          28 :   obj->length = 0;
      36          28 : }
      37             : 
      38           8 : cbuf *cb_create(int capacity)
      39             : {
      40           8 :   cbuf *obj = smb_new(cbuf, 1);
      41           8 :   cb_init(obj, capacity);
      42           8 :   return obj;
      43             : }
      44             : 
      45          24 : void cb_destroy(cbuf *obj)
      46             : {
      47          24 :   smb_free(obj->buf);
      48          24 :   obj->buf = NULL;
      49          24 : }
      50             : 
      51           8 : void cb_delete(cbuf *obj) {
      52           8 :   cb_destroy(obj);
      53           8 :   smb_free(obj);
      54           8 : }
      55             : 
      56             : /**
      57             :    @brief Ensure that the cbuf can fit a certain amount of characters.
      58             :    @param obj The cbuf to expand (if necessary).
      59             :    @param minsize The minimum size the cbuf should be able to fit.
      60             : 
      61             :    Note that minsize should include the NUL byte as part of the character count.
      62             :    Therefore, to ensure that the string "four" fits in the buffer, you would
      63             :    want to run `cb_expand_to_fit(obj, 5)` (assuming the buffer was empty).
      64             :  */
      65         170 : static void cb_expand_to_fit(cbuf *obj, int minsize)
      66             : {
      67         170 :   int newcapacity = obj->capacity;
      68         344 :   while (newcapacity < minsize) {
      69           4 :     newcapacity *= 2;
      70             :   }
      71         170 :   if (newcapacity != obj->capacity) {
      72           3 :     obj->buf = smb_renew(char, obj->buf, newcapacity);
      73           3 :     obj->capacity = newcapacity;
      74             :   }
      75         170 : }
      76             : 
      77           7 : void cb_concat(cbuf *obj, char *buf)
      78             : {
      79           7 :   int length = strlen(buf);
      80           7 :   cb_expand_to_fit(obj, obj->length + length + 1);
      81           7 :   strcpy(obj->buf + obj->length, buf);
      82           7 :   obj->length += length;
      83           7 : }
      84             : 
      85         146 : void cb_append(cbuf *obj, char next)
      86             : {
      87         146 :   cb_expand_to_fit(obj, obj->length + 2); // include new character + nul
      88         146 :   obj->buf[obj->length] = next;
      89         146 :   obj->length++;
      90         146 :   obj->buf[obj->length] = '\0';
      91         146 : }
      92             : 
      93           5 : void cb_trim(cbuf *obj)
      94             : {
      95           5 :   obj->buf = smb_renew(char, obj->buf, obj->length + 1);
      96           5 :   obj->capacity = obj->length + 1;
      97           5 : }
      98             : 
      99           1 : void cb_clear(cbuf *obj)
     100             : {
     101           1 :   obj->buf[0] = '\0';
     102           1 :   obj->length = 0;
     103           1 : }
     104             : 
     105          17 : void cb_vprintf(cbuf *obj, char *format, va_list va)
     106             : {
     107             :   va_list v2;
     108             :   int length;
     109          17 :   va_copy(v2, va);
     110             : 
     111             :   // Find the length of the formatted string.
     112          17 :   length = vsnprintf(NULL, 0, format, va);
     113             : 
     114             :   // Make sure we have enough room for everything.
     115          17 :   cb_expand_to_fit(obj, obj->length + length + 1);
     116             : 
     117             :   // Put the formatted string into the buffer.
     118          17 :   vsnprintf(obj->buf + obj->length, length + 1, format, v2);
     119          17 :   va_end(v2);
     120          17 : }
     121             : 
     122           9 : void cb_printf(cbuf *obj, char *format, ...)
     123             : {
     124             :   va_list va;
     125           9 :   va_start(va, format);
     126           9 :   cb_vprintf(obj, format, va);
     127           9 :   va_end(va);  // Have to va_stop() it when you're done using it.
     128           9 : }
     129             : 
     130             : /*******************************************************************************
     131             : 
     132             :                                 wcbuf Functions
     133             : 
     134             : *******************************************************************************/
     135             : 
     136          12 : void wcb_init(wcbuf *obj, int capacity)
     137             : {
     138             :   // Initialization logic
     139          12 :   obj->buf = smb_new(wchar_t, capacity);
     140          12 :   obj->buf[0] = L'\0';
     141          12 :   obj->capacity = capacity;
     142          12 :   obj->length = 0;
     143          12 : }
     144             : 
     145           8 : wcbuf *wcb_create(int capacity)
     146             : {
     147           8 :   wcbuf *obj = smb_new(wcbuf, 1);
     148           8 :   wcb_init(obj, capacity);
     149           8 :   return obj;
     150             : }
     151             : 
     152           8 : void wcb_destroy(wcbuf *obj)
     153             : {
     154             :   // Cleanup logic
     155           8 :   smb_free(obj->buf);
     156           8 :   obj->buf = NULL;
     157           8 : }
     158             : 
     159           8 : void wcb_delete(wcbuf *obj)
     160             : {
     161           8 :   wcb_destroy(obj);
     162           8 :   smb_free(obj);
     163           8 : }
     164             : 
     165             : /**
     166             :    @brief Ensure that the wcbuf can fit a certain amount of characters.
     167             :    @param obj The wcbuf to expand (if necessary).
     168             :    @param minsize The minimum size the wcbuf should be able to fit.
     169             : 
     170             :    Note that minsize should include the NUL character as part of the character
     171             :    count.  Therefore, to ensure that the string L"four" fits in the buffer, you
     172             :    would want to run `cb_expand_to_fit(obj, 5)` (assuming the buffer was empty).
     173             :  */
     174         154 : static void wcb_expand_to_fit(wcbuf *obj, int minsize)
     175             : {
     176         154 :   int newcapacity = obj->capacity;
     177         312 :   while (newcapacity < minsize) {
     178           4 :     newcapacity *= 2;
     179             :   }
     180         154 :   if (newcapacity != obj->capacity) {
     181           3 :     obj->buf = smb_renew(wchar_t, obj->buf, newcapacity);
     182           3 :     obj->capacity = newcapacity;
     183             :   }
     184         154 : }
     185             : 
     186           7 : void wcb_concat(wcbuf *obj, wchar_t *str)
     187             : {
     188           7 :   int length = wcslen(str);
     189           7 :   wcb_expand_to_fit(obj, obj->length + length + 1);
     190           7 :   wcscpy(obj->buf + obj->length, str);
     191           7 :   obj->length += length;
     192           7 : }
     193             : 
     194         146 : void wcb_append(wcbuf *obj, wchar_t next)
     195             : {
     196         146 :   wcb_expand_to_fit(obj, obj->length + 2); // include new character + nul
     197         146 :   obj->buf[obj->length] = next;
     198         146 :   obj->length++;
     199         146 :   obj->buf[obj->length] = L'\0';
     200         146 : }
     201             : 
     202           5 : void wcb_trim(wcbuf *obj)
     203             : {
     204           5 :   obj->buf = smb_renew(wchar_t, obj->buf, obj->length + 1);
     205           5 :   obj->capacity = obj->length + 1;
     206           5 : }
     207             : 
     208           1 : void wcb_clear(wcbuf *obj)
     209             : {
     210           1 :   obj->buf[0] = L'\0';
     211           1 :   obj->length = 0;
     212           1 : }
     213             : 
     214           1 : void wcb_vprintf(wcbuf *obj, wchar_t *format, va_list v1)
     215             : {
     216             :   va_list v2;
     217             :   char *mbformat, *mbout;
     218             :   size_t mbformat_len, mbout_len, wcout_len;
     219             : 
     220             :   // First, convert the wide format string to a multibyte one.
     221           1 :   mbformat_len = wcstombs(NULL, format, 0);
     222           1 :   mbformat = smb_new(char, mbformat_len + 1);
     223           1 :   wcstombs(mbformat, format, mbformat_len+1);
     224             : 
     225             :   // Then, use vsnprintf first to find out how many bytes of output to allocate.
     226           1 :   va_copy(v2, v1);
     227           1 :   mbout_len = vsnprintf(NULL, 0, mbformat, v1);
     228             : 
     229             :   // Now, actually allocate the memory and do the multibyte print.
     230           1 :   mbout = smb_new(char, mbout_len + 1);
     231           1 :   vsnprintf(mbout, mbout_len + 1, mbformat, v2);
     232           1 :   va_end(v2);
     233             : 
     234             :   // And now, get the number of wide characters this is.
     235           1 :   wcout_len = mbstowcs(NULL, mbout, 0);
     236             : 
     237             :   // Make sure we have room for everything.
     238           1 :   wcb_expand_to_fit(obj, obj->length + wcout_len + 1);
     239             : 
     240             :   // And, put the output in the buffer.
     241           1 :   mbstowcs(obj->buf + obj->length, mbout, wcout_len + 1);
     242           1 :   obj->length += wcout_len;
     243             : 
     244             :   // Free up allocated memory, and we're good to go.
     245           1 :   smb_free(mbformat);
     246           1 :   smb_free(mbout);
     247           1 : }
     248             : 
     249           1 : void wcb_printf(wcbuf *obj, wchar_t *format, ...)
     250             : {
     251             :   va_list va;
     252           1 :   va_start(va, format);
     253           1 :   wcb_vprintf(obj, format, va);
     254           1 :   va_end(va);
     255           1 : }

Generated by: LCOV version 1.11