LCOV - code coverage report
Current view: top level - libsd - util.c (source / functions) Hit Total Coverage
Test: app.info Lines: 115 123 93.5 %
Date: 2015-08-29 Functions: 9 9 100.0 %

          Line data    Source code
       1             : // Copyright 2014 Bobby Powers. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style
       3             : // license that can be found in the LICENSE file.
       4             : 
       5             : #include <stdio.h>
       6             : #include <stdlib.h>
       7             : #include <string.h>
       8             : #include <stdbool.h>
       9             : #include <sys/types.h>
      10             : #include <sys/stat.h>
      11             : #include <fcntl.h>
      12             : #include <ctype.h>
      13             : 
      14             : #include "utf.h"
      15             : #include "sd.h"
      16             : #include "sd_internal.h"
      17             : 
      18             : 
      19        2951 : int slice_make(Slice *s, size_t len, size_t cap)
      20             : {
      21        2951 :         if (!s)
      22           1 :                 return SD_ERR_UNSPECIFIED;
      23             : 
      24        2950 :         if (cap) {
      25          18 :                 s->elems = calloc(cap, sizeof(*s->elems));
      26          18 :                 if (!s->elems)
      27           0 :                         return SD_ERR_NOMEM;
      28             :         } else {
      29        2932 :                 s->elems = NULL;
      30             :         }
      31        2950 :         s->len = len;
      32        2950 :         s->cap = cap;
      33        2950 :         return SD_ERR_NO_ERROR;
      34             : }
      35             : 
      36        4734 : int slice_append(Slice *s, void *e)
      37             : {
      38             :         size_t new_cap;
      39             : 
      40        4734 :         if (!s)
      41           1 :                 return SD_ERR_UNSPECIFIED;
      42             : 
      43        4733 :         if (s->cap == 0) {
      44        1514 :                 new_cap = 2;
      45        1514 :                 s->elems = calloc(new_cap, sizeof(*s->elems));
      46        1514 :                 if (!s->elems)
      47           0 :                         return SD_ERR_NOMEM;
      48        1514 :                 s->cap = new_cap;
      49             :         }
      50        3219 :         else if (s->len == s->cap) {
      51         972 :                 new_cap = s->cap*2;
      52         972 :                 s->elems = realloc(s->elems, new_cap*sizeof(*s->elems));
      53         972 :                 if (!s->elems) {
      54           0 :                         s->len = 0;
      55           0 :                         s->cap = 0;
      56           0 :                         return SD_ERR_NOMEM;
      57             :                 }
      58        4004 :                 for (size_t i = s->len; i < new_cap; ++i)
      59        3032 :                         s->elems[i] = NULL;
      60         972 :                 s->cap = new_cap;
      61             :         }
      62        4733 :         s->elems[s->len++] = e;
      63        4733 :         return SD_ERR_NO_ERROR;
      64             : }
      65             : 
      66           3 : int slice_extend(Slice *s, Slice *other)
      67             : {
      68           3 :         if (!s || !other)
      69           1 :                 return SD_ERR_UNSPECIFIED;
      70             : 
      71             :         // XXX: could be more efficient
      72           6 :         for (size_t i = 0; i < other->len; i++)
      73           4 :                 slice_append(s, other->elems[i]);
      74             : 
      75           2 :         return SD_ERR_NO_ERROR;
      76             : }
      77             : 
      78             : int
      79        1594 : strrepl(char *s, const char *orig, const char *new)
      80             : {
      81             :         char *found;
      82        1594 :         int replacements = 0;
      83        1594 :         size_t olen = strlen(orig);
      84        1594 :         size_t nlen = strlen(new);
      85        1594 :         int diff = strlen(orig) - strlen(new);
      86             : 
      87             :         // we will not allocate - exit early if we're being asked to
      88             :         // do so.
      89        1594 :         if (diff < 0)
      90           1 :                 return 0;
      91             : 
      92        3230 :         while ((found = strstr(s, orig))) {
      93          44 :                 replacements++;
      94          44 :                 memcpy(found, new, strlen(new));
      95             :                 // +1 is to copy trailing null
      96          44 :                 if (diff)
      97          29 :                         memmove(found + nlen, found + olen, strlen(found + olen)+1);
      98          44 :                 s = found + nlen;
      99             :         }
     100        1593 :         return replacements;
     101             : }
     102             : 
     103             : int
     104        4952 : strtrim(const char **s, int len)
     105             : {
     106             :         int n;
     107             :         Rune r;
     108       36831 :         for (; (n = charntorune(&r, *s, len)); *s += n, len -= n) {
     109       32760 :                 if (!r || !isspace(r))
     110             :                         break;
     111             :         }
     112        5005 :         for (int i = 1; len > 0 && (n = charntorune(&r, &(*s)[len-i], i)); i++) {
     113         928 :                 if (r == Runeerror)
     114           0 :                         continue;
     115         928 :                 if (!isspace(r))
     116         875 :                         break;
     117          53 :                 len -= i;
     118          53 :                 i = 0;
     119             :         }
     120        4952 :         return len;
     121             : }
     122             : 
     123             : int
     124         413 : utf8_tolower(char **s)
     125             : {
     126             :         int n;
     127             :         Rune u;
     128         413 :         const size_t slen = strlen(*s);
     129         413 :         size_t dlen = 0;
     130             :         char *src, **ss;
     131         413 :         bool needs_realloc = false;
     132             : 
     133         413 :         src = *s;
     134         413 :         ss = &src;
     135             : 
     136        5052 :         for (size_t len = slen; (n = charntorune(&u, *ss, len)); *ss += n, len -= n) {
     137        4639 :                 const Rune l = tolowerrune(u);
     138        4639 :                 needs_realloc |= runelen(l) > n;
     139        4639 :                 dlen += runelen(l);
     140             :         }
     141         413 :         char *d = needs_realloc ? realloc(*s, dlen) : *s;
     142         413 :         if (!d)
     143           0 :                 return SD_ERR_NOMEM;
     144             : 
     145             : 
     146         413 :         src = *s;
     147         413 :         size_t doff = 0;
     148        5052 :         for (size_t len = slen; (n = charntorune(&u, *ss, len)); *ss += n, len -= n) {
     149        4639 :                 Rune l = tolowerrune(u);
     150        4639 :                 const int ln = runetochar(&d[doff], &l);
     151        4639 :                 doff += ln;
     152             :         }
     153             : 
     154         413 :         *s = d;
     155             : 
     156         413 :         return SD_ERR_NO_ERROR;
     157             : }
     158             : 
     159             : size_t
     160          36 : round_up(size_t i, size_t n)
     161             : {
     162          36 :         return n*((i - 1)/n + 1);
     163             : }
     164             : 
     165             : double
     166        1737 : lookup(Table *t, double index)
     167             : {
     168        1737 :         size_t len = t->len;
     169        1737 :         if (unlikely(t->len == 0))
     170           1 :                 return 0;
     171             : 
     172        1736 :         double *x = t->x;
     173        1736 :         double *y = t->y;
     174             : 
     175             :         // if the request is outside the min or max, then we return
     176             :         // the nearest element of the array
     177        1736 :         if (unlikely(index < x[0]))
     178           2 :                 return y[0];
     179        1734 :         else if (unlikely(index > x[len-1]))
     180          15 :                 return y[len-1];
     181             : 
     182             :         // binary search makes more sense here
     183        1719 :         size_t low = 0;
     184        1719 :         size_t high = len;
     185             :         size_t mid;
     186        9724 :         while (low < high) {
     187        6286 :                 mid = low + ((high-low)/2);
     188        6286 :                 if (x[mid] < index)
     189        2321 :                         low = mid + 1;
     190             :                 else
     191        3965 :                         high = mid;
     192             :         }
     193             : 
     194             :         // at this point low == high, so using 'i' seems more readable.
     195        1719 :         size_t i = low;
     196        1719 :         if (unlikely(x[i] == index)) {
     197        1467 :                 return y[i];
     198             :         } else {
     199             :                 // slope = deltaY/deltaX
     200         252 :                 double slope = (y[i] - y[i-1]) / (x[i] - x[i-1]);
     201         252 :                 return (index-x[i-1])*slope + y[i-1];
     202             :         }
     203             : 
     204             :         return 0;
     205             : }
     206             : 
     207             : char *
     208         265 : normalize_name(const char *n)
     209             : {
     210             :         char *result;
     211         265 :         size_t len = strlen(n);
     212         265 :         bool quoted = len > 0 && n[0] == '"' && n[len-1] == '"';
     213         265 :         int off = quoted ? 1 : 0;
     214             : 
     215         265 :         result = strndup(n+off, len - 2*off);
     216         265 :         if (!result)
     217           0 :                 return NULL;
     218         265 :         utf8_tolower(&result);
     219             :         // FIXME: be more efficient
     220         265 :         strrepl(result, "\\\\", "\\");
     221         265 :         strrepl(result, "\\n", "_");
     222         265 :         strrepl(result, "\\r", "_");
     223         265 :         strrepl(result, "\n", "_");
     224         265 :         strrepl(result, "\r", "_");
     225         265 :         strrepl(result, " ", "_");
     226             :         // FIXME: nbsp - 00A0 / C2A0
     227         265 :         return result;
     228             : }

Generated by: LCOV version 1.10