tal: document tal_steal(ctx, NULL) as OK.
[ccan] / ccan / charset / _info
1 #include "config.h"
2 #include <stdio.h>
3 #include <string.h>
4
5 /**
6  * charset - character set conversion and validation routines
7  *
8  * This module provides a collection of well-tested routines
9  * for dealing with character set nonsense.
10  *
11  * Example:
12  *      #include <err.h>
13  *      #include <stdio.h>
14  *      #include <stdlib.h>
15  *      #include <string.h>
16  *      #include <ccan/charset/charset.h>
17  *      #include <ccan/tal/grab_file/grab_file.h>
18  *      #include <ccan/tal/tal.h>
19  *      
20  *      static void print_json_string(const char *s);
21  *      static bool parse_hex16(const char **sp, unsigned int *out);
22  *      
23  *      // Take a JSON-encoded string on input and print its literal value.
24  *      int main(void)
25  *      {
26  *              char *input;
27  *      
28  *              input = grab_file(NULL, NULL);
29  *              if (!input)
30  *                      err(1, "Error reading input");
31  *              if (!utf8_validate(input, tal_count(input)-1)) {
32  *                      fprintf(stderr, "Input contains invalid UTF-8\n");
33  *                      return 1;
34  *              }
35  *              if (strlen(input) != tal_count(input)-1) {
36  *                      fprintf(stderr, "Input contains null characters\n");
37  *                      return 1;
38  *              }
39  *              
40  *              print_json_string(input);
41  *              
42  *              tal_free(input);
43  *              return 0;
44  *      }
45  *      
46  *      static void print_json_string(const char *s)
47  *      {
48  *              char output_buffer[4];
49  *              
50  *              // Skip leading whitespace
51  *              while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
52  *                      s++;
53  *              
54  *              if (*s++ != '"') {
55  *                      fprintf(stderr, "Expected JSON string literal surrounded by double quotes.\n");
56  *                      exit(EXIT_FAILURE);
57  *              }
58  *              
59  *              while (*s != '"') {
60  *                      unsigned char c = *s++;
61  *                      char *b = output_buffer;
62  *                      
63  *                      if (c == '\\') {
64  *                              c = *s++;
65  *                              switch (c) {
66  *                                      case '"':
67  *                                      case '\\':
68  *                                      case '/':
69  *                                              *b++ = c;
70  *                                              break;
71  *                                      case 'b': *b++ = '\b'; break;
72  *                                      case 'f': *b++ = '\f'; break;
73  *                                      case 'n': *b++ = '\n'; break;
74  *                                      case 'r': *b++ = '\r'; break;
75  *                                      case 't': *b++ = '\t'; break;
76  *                                      case 'u': {
77  *                                              unsigned int uc, lc;
78  *                                              
79  *                                              if (!parse_hex16(&s, &uc))
80  *                                                      goto syntax_error;
81  *                                              
82  *                                              if (uc >= 0xD800 && uc <= 0xDFFF) {
83  *                                                      // Handle UTF-16 surrogate pair (e.g. "\uD834\uDD1E").
84  *                                                      uchar_t unicode;
85  *                                                      
86  *                                                      if (*s++ != '\\' || *s++ != 'u' || !parse_hex16(&s, &lc))
87  *                                                              goto syntax_error;
88  *                                                      
89  *                                                      unicode = from_surrogate_pair(uc, lc);
90  *                                                      if (unicode == REPLACEMENT_CHARACTER) {
91  *                                                              fprintf(stderr, "Invalid surrogate pair.\n");
92  *                                                              exit(EXIT_FAILURE);
93  *                                                      }
94  *                                                      
95  *                                                      b += utf8_write_char(unicode, b);
96  *                                              } else {
97  *                                                      // Handle ordinary Unicode escape (e.g. "\u266B").
98  *                                                      b += utf8_write_char(uc, b);
99  *                                              }
100  *                                              
101  *                                              break;
102  *                                      }
103  *                                      default:
104  *                                              goto syntax_error;
105  *                              }
106  *                      } else if (c <= 0x1F) {
107  *                              // Control characters are not allowed in string literals.
108  *                              goto syntax_error;
109  *                      } else {
110  *                              *b++ = c;
111  *                      }
112  *                      
113  *                      fwrite(output_buffer, 1, b - output_buffer, stdout);
114  *              }
115  *              
116  *              putchar('\n');
117  *              return;
118  *              
119  *      syntax_error:
120  *              fprintf(stderr, "Syntax error in JSON string literal.\n");
121  *              exit(EXIT_FAILURE);
122  *      }
123  *      
124  *      static bool parse_hex16(const char **sp, unsigned int *out)
125  *      {
126  *              const char *s = *sp;
127  *              unsigned int ret = 0;
128  *              unsigned int i;
129  *              unsigned int tmp;
130  *              char            c;
131  *      
132  *              for (i = 0; i < 4; i++)
133  *              {
134  *                      c = *s++;
135  *                      if (c >= '0' && c <= '9')
136  *                              tmp = c - '0';
137  *                      else if (c >= 'A' && c <= 'F')
138  *                              tmp = c - 'A' + 10;
139  *                      else if (c >= 'a' && c <= 'f')
140  *                              tmp = c - 'a' + 10;
141  *                      else
142  *                              return false;
143  *      
144  *                      ret <<= 4;
145  *                      ret += tmp;
146  *              }
147  *              
148  *              *out = ret;
149  *              *sp = s;
150  *              return true;
151  *      }
152  *
153  * Author: Joey Adams <joeyadams3.14159@gmail.com>
154  * License: MIT
155  * Version: 0.3
156  */
157 int main(int argc, char *argv[])
158 {
159         /* Expect exactly one argument */
160         if (argc != 2)
161                 return 1;
162
163         if (strcmp(argv[1], "depends") == 0) {
164                 /* Nothing */
165                 return 0;
166         }
167         
168         if (strcmp(argv[1], "libs") == 0) {
169                 printf("m\n"); /* Needed for the pow() invocation in run.c */
170                 return 0;
171         }
172
173         return 1;
174 }