kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

dist_parse.h (2606B)


      1 #ifndef KIT_DIST_DIST_PARSE_H
      2 #define KIT_DIST_DIST_PARSE_H
      3 
      4 #include <kit/core.h>
      5 #include <stddef.h>
      6 #include <stdint.h>
      7 #include <stdio.h>
      8 #include <string.h>
      9 
     10 #include "dist.h"
     11 
     12 /* Shared `key = value` text-manifest parse/emit helpers used by the tree,
     13  * package-manifest, and kpkg-descriptor codecs. These were once duplicated
     14  * (with drift) across manifest.c/tree.c/kpkg.c; the single copy here
     15  * reconciles them to the strictest/most-informative variant of each. Provided
     16  * as `static inline` so no extra translation unit (and no Makefile
     17  * registration) is required. */
     18 
     19 /* Max length of a single emitted "key = value\n" line. */
     20 #define DIST_KV_LINE_MAX 1024u
     21 
     22 /* Skip leading spaces/tabs, returning a pointer into `s`. */
     23 static inline char* dist_trim_lead(char* s) {
     24   while (*s == ' ' || *s == '\t') ++s;
     25   return s;
     26 }
     27 
     28 /* Strip trailing spaces/tabs/CR/LF in place. */
     29 static inline void dist_trim_trail(char* s) {
     30   size_t n = strlen(s);
     31   while (n && (s[n - 1] == ' ' || s[n - 1] == '\t' || s[n - 1] == '\r' ||
     32                s[n - 1] == '\n'))
     33     s[--n] = '\0';
     34 }
     35 
     36 /* Record `msg` into the caller's error buffer (if any) and return DIST_ERR. */
     37 static inline int dist_set_err(char* err, size_t cap, const char* msg) {
     38   if (err && cap) snprintf(err, cap, "%s", msg);
     39   return DIST_ERR;
     40 }
     41 
     42 /* Copy NUL-terminated `src` into `dst` of capacity `cap`, failing (with an
     43  * error message) if it would not fit. */
     44 static inline int dist_copy_field(char* dst, size_t cap, const char* src,
     45                                   char* err, size_t errcap) {
     46   if (strlen(src) >= cap)
     47     return dist_set_err(err, errcap, "field value too long");
     48   snprintf(dst, cap, "%s", src);
     49   return DIST_OK;
     50 }
     51 
     52 /* Strict base-10 parse of `s` into `*out`: rejects empty input, any non-digit,
     53  * and values that would overflow uint64_t. */
     54 static inline int dist_parse_u64(const char* s, uint64_t* out) {
     55   uint64_t v = 0;
     56   if (!s || !*s || !out) return DIST_ERR;
     57   for (; *s; ++s) {
     58     unsigned d;
     59     if (*s < '0' || *s > '9') return DIST_ERR;
     60     d = (unsigned)(*s - '0');
     61     if (v > (UINT64_MAX - (uint64_t)d) / 10u) return DIST_ERR;
     62     v = v * 10u + (uint64_t)d;
     63   }
     64   *out = v;
     65   return DIST_OK;
     66 }
     67 
     68 /* Emit a single "key = value\n" line to `out`. */
     69 static inline int dist_emit_kv(KitWriter* out, const char* key,
     70                                const char* val) {
     71   char line[DIST_KV_LINE_MAX];
     72   snprintf(line, sizeof line, "%s = %s\n", key, val);
     73   return kit_writer_write(out, line, strlen(line)) == KIT_OK ? DIST_OK
     74                                                              : DIST_ERR;
     75 }
     76 
     77 #endif