Cthulhu  0.2.10
Cthulhu compiler collection
text.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 
3 #include "cthulhu/util/text.h"
4 
5 #include "base/panic.h"
6 #include "base/util.h"
8 #include "arena/arena.h"
9 #include "std/typed/vector.h"
10 
11 #include "notify/notify.h"
12 
13 typedef struct escape_t
14 {
15  size_t length;
16  char code;
17 } escape_t;
18 
19 static escape_t escape_new(size_t length, char code)
20 {
21  escape_t escape = {
22  .length = length,
23  .code = code
24  };
25 
26  return escape;
27 }
28 
29 static escape_t consume_escape(logger_t *reports, const node_t *node, const char *text)
30 {
31  switch (*text)
32  {
33  case 'n': return escape_new(2, '\n');
34  case 't': return escape_new(2, '\t');
35  case 'r': return escape_new(2, '\r');
36  case '0': return escape_new(2, '\0');
37  case '\\': return escape_new(2, '\\');
38  case '"': return escape_new(2, '"');
39  case '\'': return escape_new(2, '\'');
40 
41  default:
42  msg_notify(reports, &kEvent_InvalidStringEscape, node, "unknown escape sequence '\\%c'", *text);
43  return escape_new(1, *text);
44  }
45 }
46 
47 static escape_t consume_text(logger_t *reports, const node_t *node, const char *text)
48 {
49  switch (*text)
50  {
51  case '\\': return consume_escape(reports, node, text + 1);
52  default: return escape_new(1, *text);
53  }
54 }
55 
57 text_t util_text_escape(logger_t *reports, const node_t *node, const char *text, size_t length, arena_t *arena)
58 {
59  CTASSERT(reports != NULL);
60  CTASSERT(node != NULL);
61  CTASSERT(text != NULL);
62  CTASSERT(arena != NULL);
63 
64  typevec_t vec = typevec_make(sizeof(char), length, arena);
65  ARENA_IDENTIFY(typevec_data(&vec), "text", reports, arena);
66 
67  for (size_t i = 0; i < length;)
68  {
69  escape_t escape = consume_text(reports, node, text + i);
70  typevec_push(&vec, &escape.code);
71  i += escape.length;
72  }
73 
74  char zero = '\0';
75  typevec_push(&vec, &zero);
76 
77  return text_make(typevec_data(&vec), typevec_len(&vec));
78 }
79 
81 bool util_text_has_escapes(const char *text, size_t length)
82 {
83  CTASSERT(text != NULL);
84 
85  for (size_t i = 0; i < length; i++)
86  {
87  if (text[i] == '\\')
88  {
89  return true;
90  }
91  }
92 
93  return false;
94 }
#define STA_DECL
sal2 annotation on function implementations to copy annotations from the declaration
CT_CONSTFN CT_BASE_API text_t text_make(STA_READS(length) char *text, size_t length)
create a new owning text array text must be a valid string at least length bytes long
#define ARENA_IDENTIFY(ptr, name, parent, arena)
rename and reparent a pointer in a custom allocator
Definition: arena.h:409
CT_NOTIFY_API event_builder_t msg_notify(INOUT_NOTNULL logger_t *logs, const diagnostic_t *diagnostic, const node_t *node, STA_FORMAT_STRING const char *fmt,...)
notify the logger of a new message
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
CT_STD_API typevec_t typevec_make(size_t width, size_t len, arena_t *arena)
create a new typed vector on the stack
Definition: vector.c:69
CT_STD_API void * typevec_push(typevec_t *vec, const void *src)
push a value onto the vector
Definition: vector.c:156
CT_NODISCARD CT_PUREFN CT_STD_API size_t typevec_len(const typevec_t *vec)
get the length of a vector
Definition: vector.c:120
CT_NODISCARD CT_PUREFN CT_STD_API void * typevec_data(const typevec_t *vec)
get a pointer to the underlying data
Definition: vector.c:199
an allocator object
Definition: arena.h:86
Definition: text.c:14
char code
Definition: text.c:16
size_t length
Definition: text.c:15
a logging sink
Definition: notify.c:14
a position in a source file
Definition: node.h:23
a range of text
Definition: text.h:14
A vector with a fixed type size.
Definition: vector.h:24
STA_DECL bool util_text_has_escapes(const char *text, size_t length)
Definition: text.c:81
STA_DECL text_t util_text_escape(logger_t *reports, const node_t *node, const char *text, size_t length, arena_t *arena)
Definition: text.c:57