summaryrefslogtreecommitdiff
path: root/cbits/escapexml.c
blob: 6eb366d51332965e80c74c4baccf3dc865c19ba7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <string.h>
#include <stdint.h>

// https://hackage-content.haskell.org/package/mustache-2.4.3.1/src/src/Text/Mustache/Internal.hs
//
// escapeXML :: String -> String
// escapeXML = concatMap $ \x -> IntMap.findWithDefault [x] (ord x) mp
//     where mp = IntMap.fromList [(ord b, "&"++a++";") | (a,[b]) <- xmlEntities]
//
// xmlEntities :: [(String, String)]
// xmlEntities =
//   [ ("quot", "\"")
//   , ("#39", "'")
//   , ("amp" , "&")
//   , ("lt"  , "<")
//   , ("gt"  , ">")
//   ]

#define ENTITIES_XLIST \
  X('"', 6, "&quot;") \
  X('\'', 5, "&#39;") \
  X('&', 5, "&amp;") \
  X('<', 4, "&lt;") \
  X('>', 4, "&gt;")

size_t tirclogv_escapexml_len(const uint8_t *src, size_t src_off, size_t src_len) {
  size_t reslen = 0;
  for (size_t i = 0; i < src_len; i++) {
    switch (src[src_off + i]) {
#define X(ch, len, _str) case ch: reslen += len; break;
      ENTITIES_XLIST
#undef X
      default: reslen += 1; break;
    }
  }
  return reslen;
}

void tirclogv_escapexml(uint8_t *dst, const uint8_t *src, size_t src_off, size_t src_len) {
  for (size_t i = 0, j = 0; i < src_len; i++) {
    const uint8_t c = src[src_off + i];
    switch (c) {
#define X(ch, len, str) case ch: memcpy(&dst[j], str, len); j += len; break;
      ENTITIES_XLIST
#undef X
      default: dst[j++] = c; break;
    }
  }
}