Coverage Report

Created: 2026-09-13 06:50

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
904
struct locfile* locfile_init(jq_state *jq, const char *fname, const char* data, int length) {
13
904
  struct locfile* l = jv_mem_alloc(sizeof(struct locfile));
14
904
  l->jq = jq;
15
904
  l->fname = jv_string(fname);
16
904
  l->data = jv_mem_alloc(length);
17
904
  memcpy((char*)l->data,data,length);
18
904
  l->length = length;
19
904
  l->nlines = 1;
20
904
  l->refct = 1;
21
45.1M
  for (int i=0; i<length; i++) {
22
45.1M
    if (data[i] == '\n') l->nlines++;
23
45.1M
  }
24
904
  l->linemap = jv_mem_calloc(l->nlines + 1, sizeof(int));
25
904
  l->linemap[0] = 0;
26
904
  int line = 1;
27
45.1M
  for (int i=0; i<length; i++) {
28
45.1M
    if (data[i] == '\n') {
29
6.52M
      l->linemap[line] = i+1;   // at start of line, not of \n
30
6.52M
      line++;
31
6.52M
    }
32
45.1M
  }
33
904
  l->linemap[l->nlines] = length+1;   // virtual last \n
34
904
  return l;
35
904
}
36
37
372k
struct locfile* locfile_retain(struct locfile* l) {
38
372k
  l->refct++;
39
372k
  return l;
40
372k
}
41
373k
void locfile_free(struct locfile* l) {
42
373k
  if (--(l->refct) == 0) {
43
904
    jv_free(l->fname);
44
904
    jv_mem_free(l->linemap);
45
904
    jv_mem_free((char*)l->data);
46
904
    jv_mem_free(l);
47
904
  }
48
373k
}
49
50
279k
int locfile_get_line(struct locfile* l, int pos) {
51
279k
  assert(pos < l->length);
52
279k
  int line = 1;
53
4.03G
  while (l->linemap[line] <= pos) line++;   // == if pos at start (before, never ==, because pos never on \n)
54
279k
  assert(line-1 < l->nlines);
55
279k
  return line-1;
56
279k
}
57
58
279k
static int locfile_line_length(struct locfile* l, int line) {
59
279k
  assert(line < l->nlines);
60
279k
  return l->linemap[line+1] - l->linemap[line] -1;   // -1 to omit \n
61
279k
}
62
63
279k
void locfile_locate(struct locfile* l, location loc, const char* fmt, ...) {
64
279k
  va_list fmtargs;
65
279k
  va_start(fmtargs, fmt);
66
67
279k
  jv m1 = jv_string_vfmt(fmt, fmtargs);
68
279k
  va_end(fmtargs);
69
279k
  if (!jv_is_valid(m1)) {
70
0
    jq_report_error(l->jq, m1);
71
0
    return;
72
0
  }
73
279k
  if (loc.start == -1) {
74
5
    jq_report_error(l->jq, jv_string_fmt("jq: error: %s", jv_string_value(m1)));
75
5
    jv_free(m1);
76
5
    return;
77
5
  }
78
79
279k
  int startline = locfile_get_line(l, loc.start);
80
279k
  int offset = l->linemap[startline];
81
279k
  int end = MIN(loc.end, MAX(l->linemap[startline+1] - 1, loc.start + 1));
82
279k
  jv underline = jv_string_repeat(jv_string("^"), end - loc.start);
83
279k
  jv m2 = jv_string_fmt("%s at %s, line %d, column %d:\n    %.*s\n    %*s",
84
279k
                        jv_string_value(m1), jv_string_value(l->fname),
85
279k
                        startline + 1, loc.start - offset + 1,
86
279k
                        locfile_line_length(l, startline), l->data + offset,
87
279k
                        end - offset, jv_string_value(underline));
88
279k
  jv_free(m1);
89
279k
  jv_free(underline);
90
279k
  jq_report_error(l->jq, m2);
91
279k
  return;
92
279k
}