diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-01-03 12:23:44 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-01-03 12:23:52 +0200 |
commit | 80ed5e611de0e31eed65ee207f1fd64ad097e6d1 (patch) | |
tree | 40979fe5ecadaa3d1351c645ff7988a87218e142 /mimetypes/prloc.c | |
parent | a4edd153e4cdf703c98008313743b112274e760f (diff) | |
download | fileserv-80ed5e611de0e31eed65ee207f1fd64ad097e6d1.tar.gz fileserv-80ed5e611de0e31eed65ee207f1fd64ad097e6d1.tar.bz2 |
Add mimetypes library.
Ported from GNU Mailutils.
Diffstat (limited to 'mimetypes/prloc.c')
-rw-r--r-- | mimetypes/prloc.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/mimetypes/prloc.c b/mimetypes/prloc.c new file mode 100644 index 0000000..d53883c --- /dev/null +++ b/mimetypes/prloc.c @@ -0,0 +1,172 @@ +#include <stdlib.h> +#include <errno.h> +#include "locus.h" + +size_t +nprlen (unsigned x) +{ + size_t len = 1; + while (x /= 10) + len++; + return len; +} + +size_t +lpprlen (struct locus_point const *lp) +{ + size_t len = 0; + + if (lp->file) + { + len = strlen (lp->file) + 1 + nprlen (lp->line); + if (lp->col) + len += 1 + nprlen (lp->col); + } + return len; +} + +size_t +lrprlen (struct locus_range const *lr) +{ + size_t len; + + len = lpprlen (&lr->end); + if (len) + len++; + len += lpprlen (&lr->beg); + return len; +} + +enum + { + PR_NON = 0x00, + PR_FIL = 0x01, + PR_LIN = 0x02, + PR_COL = 0x04, + PR_ALL = PR_FIL|PR_LIN|PR_COL + }; + +static ssize_t +_numprint (char *p, unsigned num) +{ + size_t len = 0; + char *q; + do + { + p[len++] = (num % 10) + '0'; + } + while (num /= 10); + for (q = p + len - 1; q > p; p++, q--) + { + char t = *p; + *p = *q; + *q = t; + } + return len; +} + +ssize_t +_lpprint (char *buf, struct locus_point const *lp, int pr) +{ + size_t n = 0; + + if (!lp->file) + pr &= ~PR_FIL; + if (!lp->col) + pr &= ~PR_COL; + + if (pr & PR_FIL) + { + n = strlen (lp->file); + memcpy (buf, lp->file, n); + } + if (pr & PR_LIN) + { + if (pr & PR_FIL) + buf[n++] = ':'; + n += _numprint (buf + n, lp->line); + } + if (pr & PR_COL) + { + if (pr & PR_LIN) + buf[n++] = '.'; + n += _numprint (buf + n, lp->col); + } + return n; +} + +ssize_t +locus_point_format (char **pbuf, size_t *psize, struct locus_point const *lp) +{ + char *buf; + size_t size; + size_t prlen; + + if (!pbuf || !psize || !lp) + { + errno = EINVAL; + return -1; + } + buf = *pbuf; + size = *psize; + + prlen = lpprlen (lp); + if (prlen + 1 > size) + { + size = prlen + 1; + buf = realloc (buf, size); + if (!buf) + return -1; + *pbuf = buf; + *psize = size; + } + return _lpprint (buf, lp, PR_ALL); +} + +ssize_t +locus_range_format (char **pbuf, size_t *psize, struct locus_range const *lr) +{ + char *buf; + size_t size; + size_t prlen; + size_t n; + + if (!pbuf || !psize || !lr) + { + errno = EINVAL; + return -1; + } + buf = *pbuf; + size = *psize; + + prlen = lrprlen (lr); + if (prlen + 1 > size) + { + size = prlen + 1; + buf = realloc (buf, size); + if (!buf) + return -1; + *pbuf = buf; + *psize = size; + } + n = _lpprint (buf, &lr->beg, PR_ALL); + buf += n; + if (lr->end.file) + { + int flag = PR_NON; + + if (!locus_point_same_file (&lr->beg, &lr->end)) + flag = PR_ALL; + else if (lr->beg.line != lr->end.line) + flag = PR_LIN|PR_COL; + else if (lr->beg.col && lr->beg.col != lr->end.col) + flag = PR_COL; + + if (flag != PR_NON) + { + buf[n++] = '-'; + n += _lpprint (buf + n, &lr->end, flag); + } + } + return n; +} |