/* This file is part of fileserv. Copyright (C) 2017-2023 Sergey Poznyakoff Fileserv is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Fileserv is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with fileserv. If not, see . */ #include #include #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); 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); } } buf[n] = 0; return n; }