Coverage Report

Created: 2026-02-27 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jq/src/locfile.c
Line
Count
Source
1
#include <assert.h>
2
#include <errno.h>
3
#include <stdarg.h>
4
#include <stdlib.h>
5
#include <stdio.h>
6
#include <string.h>
7
#include "jq.h"
8
#include "jv_alloc.h"
9
#include "locfile.h"
10
#include "util.h"
11
12
9.98k
struct locfile* locfile_init(jq_state *jq, const char *fname, const char* data, int length) {
13
9.98k
  struct locfile* l = jv_mem_alloc(sizeof(struct locfile));
14
9.98k
  l->jq = jq;
15
9.98k
  l->fname = jv_string(fname);
16
9.98k
  l->data = jv_mem_alloc(length);
17
9.98k
  memcpy((char*)l->data,data,length);
18
9.98k
  l->length = length;
19
9.98k
  l->nlines = 1;
20
9.98k
  l->refct = 1;
21
58.9M
  for (int i=0; i<length; i++) {
22
58.9M
    if (data[i] == '\n') l->nlines++;
23
58.9M
  }
24
9.98k
  l->linemap = jv_mem_calloc(l->nlines + 1, sizeof(int));
25
9.98k
  l->linemap[0] = 0;
26
9.98k
  int line = 1;
27
58.9M
  for (int i=0; i<length; i++) {
28
58.9M
    if (data[i] == '\n') {
29
2.34M
      l->linemap[line] = i+1;   // at start of line, not of \n
30
2.34M
      line++;
31
2.34M
    }
32
58.9M
  }
33
9.98k
  l->linemap[l->nlines] = length+1;   // virtual last \n
34
9.98k
  return l;
35
9.98k
}
36
37
2.59M
struct locfile* locfile_retain(struct locfile* l) {
38
2.59M
  l->refct++;
39
2.59M
  return l;
40
2.59M
}
41
2.60M
void locfile_free(struct locfile* l) {
42
2.60M
  if (--(l->refct) == 0) {
43
9.98k
    jv_free(l->fname);
44
9.98k
    jv_mem_free(l->linemap);
45
9.98k
    jv_mem_free((char*)l->data);
46
9.98k
    jv_mem_free(l);
47
9.98k
  }
48
2.60M
}
49
50
98.7k
int locfile_get_line(struct locfile* l, int pos) {
51
98.7k
  assert(pos < l->length);
52
98.7k
  int line = 1;
53
52.5M
  while (l->linemap[line] <= pos) line++;   // == if pos at start (before, never ==, because pos never on \n)
54
98.7k
  assert(line-1 < l->nlines);
55
98.7k
  return line-1;
56
98.7k
}
57
58
98.7k
static int locfile_line_length(struct locfile* l, int line) {
59
98.7k
  assert(line < l->nlines);
60
98.7k
  return l->linemap[line+1] - l->linemap[line] -1;   // -1 to omit \n
61
98.7k
}
62
63
98.7k
void locfile_locate(struct locfile* l, location loc, const char* fmt, ...) {
64
98.7k
  va_list fmtargs;
65
98.7k
  va_start(fmtargs, fmt);
66
67
98.7k
  jv m1 = jv_string_vfmt(fmt, fmtargs);
68
98.7k
  va_end(fmtargs);
69
98.7k
  if (!jv_is_valid(m1)) {
70
0
    jq_report_error(l->jq, m1);
71
0
    return;
72
0
  }
73
98.7k
  if (loc.start == -1) {
74
1
    jq_report_error(l->jq, jv_string_fmt("jq: error: %s", jv_string_value(m1)));
75
1
    jv_free(m1);
76
1
    return;
77
1
  }
78
79
98.7k
  int startline = locfile_get_line(l, loc.start);
80
98.7k
  int offset = l->linemap[startline];
81
98.7k
  int end = MIN(loc.end, MAX(l->linemap[startline+1] - 1, loc.start + 1));
82
98.7k
  jv underline = jv_string_repeat(jv_string("^"), end - loc.start);
83
98.7k
  jv m2 = jv_string_fmt("%s at %s, line %d, column %d:\n    %.*s\n    %*s",
84
98.7k
                        jv_string_value(m1), jv_string_value(l->fname),
85
98.7k
                        startline + 1, loc.start - offset + 1,
86
98.7k
                        locfile_line_length(l, startline), l->data + offset,
87
98.7k
                        end - offset, jv_string_value(underline));
88
98.7k
  jv_free(m1);
89
98.7k
  jv_free(underline);
90
98.7k
  jq_report_error(l->jq, m2);
91
98.7k
  return;
92
98.7k
}