harfbuzzjs 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/.github/workflows/build.yml +45 -0
  2. package/.gitmodules +3 -0
  3. package/LICENSE +0 -1
  4. package/README.md +2 -8
  5. package/build-subset.sh +21 -0
  6. package/build.sh +17 -57
  7. package/{subset/config-override.h → config-override-subset.h} +0 -0
  8. package/config-override.h +4 -3
  9. package/examples/Mada.abjad.otf +0 -0
  10. package/{subset/roboto-black.ttf → examples/Roboto-Black.ttf} +0 -0
  11. package/{subset/test.js → examples/hb-subset.example.node.js} +5 -5
  12. package/examples/hbjs.example.html +0 -1
  13. package/examples/hbjs.example.js +6 -3
  14. package/examples/hbjs.example.node.js +2 -0
  15. package/examples/nohbjs.html +0 -1
  16. package/harfbuzz.ts +46 -1
  17. package/hb-subset.symbols +28 -0
  18. package/hb-subset.wasm +0 -0
  19. package/hb.wasm +0 -0
  20. package/hbjs.cc +256 -0
  21. package/hbjs.js +73 -4
  22. package/hbjs.symbols +41 -0
  23. package/index.js +0 -1
  24. package/package.json +1 -1
  25. package/hbjs.c +0 -284
  26. package/libc/ctype.h +0 -73
  27. package/libc/emmalloc.cpp +0 -1202
  28. package/libc/fprintf.c +0 -65
  29. package/libc/include/assert.h +0 -14
  30. package/libc/include/cassert +0 -1
  31. package/libc/include/cfloat +0 -1
  32. package/libc/include/climits +0 -1
  33. package/libc/include/cmath +0 -1
  34. package/libc/include/cstdarg +0 -1
  35. package/libc/include/cstddef +0 -1
  36. package/libc/include/cstdio +0 -1
  37. package/libc/include/cstdlib +0 -1
  38. package/libc/include/cstring +0 -1
  39. package/libc/include/emscripten.h +0 -0
  40. package/libc/include/float.h +0 -6
  41. package/libc/include/limits.h +0 -2
  42. package/libc/include/locale.h +0 -0
  43. package/libc/include/malloc.h +0 -13
  44. package/libc/include/math.h +0 -0
  45. package/libc/include/raqm-version.h +0 -5
  46. package/libc/include/stdarg.h +0 -0
  47. package/libc/include/stdbool.h +0 -12
  48. package/libc/include/stddef.h +0 -0
  49. package/libc/include/stdint.h +0 -1
  50. package/libc/include/stdio.h +0 -0
  51. package/libc/include/stdlib.h +0 -110
  52. package/libc/include/string.h +0 -26
  53. package/libc/include/sys/types.h +0 -1
  54. package/libc/include/unistd.h +0 -14
  55. package/libc/main.c +0 -7
  56. package/libc/malloc.cc +0 -29
  57. package/libc/prf.c +0 -667
  58. package/libc/sprintf.c +0 -112
  59. package/libc/strtol.c +0 -79
  60. package/libc/zephyr-string.c +0 -381
  61. package/subset/build.sh +0 -48
  62. package/subset/hb-subset.wasm +0 -0
  63. package/subset/test.cc +0 -50
package/hbjs.js CHANGED
@@ -9,6 +9,7 @@ function hbjs(instance) {
9
9
  var utf8Decoder = new TextDecoder("utf8");
10
10
 
11
11
  var HB_MEMORY_MODE_WRITABLE = 2;
12
+ var HB_SET_VALUE_INVALID = -1;
12
13
 
13
14
  function hb_tag(s) {
14
15
  return (
@@ -54,6 +55,42 @@ function hbjs(instance) {
54
55
  };
55
56
  }
56
57
 
58
+ /**
59
+ * Return the typed array of HarfBuzz set contents.
60
+ * @template {typeof Uint8Array | typeof Uint32Array | typeof Int32Array | typeof Float32Array} T
61
+ * @param {number} setPtr Pointer of set
62
+ * @param {T} arrayClass Typed array class
63
+ * @returns {InstanceType<T>} Typed array instance
64
+ */
65
+ function typedArrayFromSet(setPtr, arrayClass) {
66
+ let heap = heapu8;
67
+ if (arrayClass === Uint32Array) {
68
+ heap = heapu32;
69
+ } else if (arrayClass === Int32Array) {
70
+ heap = heapi32;
71
+ } else if (arrayClass === Float32Array) {
72
+ heap = heapf32;
73
+ }
74
+ const bytesPerElment = arrayClass.BYTES_PER_ELEMENT;
75
+ const setCount = exports.hb_set_get_population(setPtr);
76
+ const arrayPtr = exports.malloc(
77
+ setCount * bytesPerElment,
78
+ );
79
+ const arrayOffset = arrayPtr / bytesPerElment;
80
+ const array = heap.subarray(
81
+ arrayOffset,
82
+ arrayOffset + setCount,
83
+ );
84
+ heap.set(array, arrayOffset);
85
+ exports.hb_set_next_many(
86
+ setPtr,
87
+ HB_SET_VALUE_INVALID,
88
+ arrayPtr,
89
+ setCount,
90
+ );
91
+ return array;
92
+ }
93
+
57
94
  /**
58
95
  * Create an object representing a Harfbuzz face.
59
96
  * @param {object} blob An object returned from `createBlob`.
@@ -98,6 +135,16 @@ function hbjs(instance) {
98
135
  exports.free(axis);
99
136
  return result;
100
137
  },
138
+ /**
139
+ * Return unicodes the face supports
140
+ */
141
+ collectUnicodes: function() {
142
+ var unicodeSetPtr = exports.hb_set_create();
143
+ exports.hb_face_collect_unicodes(ptr, unicodeSetPtr);
144
+ var result = typedArrayFromSet(unicodeSetPtr, Uint32Array);
145
+ exports.hb_set_destroy(ptr);
146
+ return result;
147
+ },
101
148
  /**
102
149
  * Free the object.
103
150
  */
@@ -110,6 +157,9 @@ function hbjs(instance) {
110
157
  var pathBufferSize = 65536; // should be enough for most glyphs
111
158
  var pathBuffer = exports.malloc(pathBufferSize); // permanently allocated
112
159
 
160
+ var nameBufferSize = 256; // should be enough for most glyphs
161
+ var nameBuffer = exports.malloc(nameBufferSize); // permanently allocated
162
+
113
163
  /**
114
164
  * Create an object representing a Harfbuzz font.
115
165
  * @param {object} blob An object returned from `createFace`.
@@ -126,8 +176,24 @@ function hbjs(instance) {
126
176
  return svgLength > 0 ? utf8Decoder.decode(heapu8.subarray(pathBuffer, pathBuffer + svgLength)) : "";
127
177
  }
128
178
 
179
+ /**
180
+ * Return glyph name.
181
+ * @param {number} glyphId ID of the requested glyph in the font.
182
+ **/
183
+ function glyphName(glyphId) {
184
+ exports.hb_font_glyph_to_string(
185
+ ptr,
186
+ glyphId,
187
+ nameBuffer,
188
+ nameBufferSize
189
+ );
190
+ var array = heapu8.subarray(nameBuffer, nameBuffer + nameBufferSize);
191
+ return utf8Decoder.decode(array.slice(0, array.indexOf(0)));
192
+ }
193
+
129
194
  return {
130
195
  ptr: ptr,
196
+ glyphName: glyphName,
131
197
  glyphToPath: glyphToPath,
132
198
  /**
133
199
  * Return a glyph as a JSON path string
@@ -287,12 +353,14 @@ function hbjs(instance) {
287
353
  * - ax: Advance width (width to advance after this glyph is painted)
288
354
  * - ay: Advance height (height to advance after this glyph is painted)
289
355
  * - dx: X displacement (adjustment in X dimension when painting this glyph)
290
- * - d5: Y displacement (adjustment in Y dimension when painting this glyph)
356
+ * - dy: Y displacement (adjustment in Y dimension when painting this glyph)
357
+ * - flags: Glyph flags like `HB_GLYPH_FLAG_UNSAFE_TO_BREAK` (0x1)
291
358
  **/
292
- json: function (font) {
359
+ json: function () {
293
360
  var length = exports.hb_buffer_get_length(ptr);
294
361
  var result = [];
295
- var infosPtr32 = exports.hb_buffer_get_glyph_infos(ptr, 0) / 4;
362
+ var infosPtr = exports.hb_buffer_get_glyph_infos(ptr, 0);
363
+ var infosPtr32 = infosPtr / 4;
296
364
  var positionsPtr32 = exports.hb_buffer_get_glyph_positions(ptr, 0) / 4;
297
365
  var infos = heapu32.subarray(infosPtr32, infosPtr32 + 5 * length);
298
366
  var positions = heapi32.subarray(positionsPtr32, positionsPtr32 + 5 * length);
@@ -303,7 +371,8 @@ function hbjs(instance) {
303
371
  ax: positions[i * 5 + 0],
304
372
  ay: positions[i * 5 + 1],
305
373
  dx: positions[i * 5 + 2],
306
- dy: positions[i * 5 + 3]
374
+ dy: positions[i * 5 + 3],
375
+ flags: exports.hb_glyph_info_get_glyph_flags(infosPtr + i * 20)
307
376
  });
308
377
  }
309
378
  return result;
package/hbjs.symbols ADDED
@@ -0,0 +1,41 @@
1
+ _hb_blob_create
2
+ _hb_blob_destroy
3
+ _hb_blob_get_data
4
+ _hb_blob_get_length
5
+ _hb_buffer_add_utf16
6
+ _hb_buffer_add_utf8
7
+ _hb_buffer_create
8
+ _hb_buffer_destroy
9
+ _hb_buffer_get_glyph_infos
10
+ _hb_buffer_get_glyph_positions
11
+ _hb_buffer_get_length
12
+ _hb_buffer_guess_segment_properties
13
+ _hb_buffer_set_cluster_level
14
+ _hb_buffer_set_direction
15
+ _hb_buffer_set_flags
16
+ _hb_buffer_set_language
17
+ _hb_buffer_set_script
18
+ _hb_face_create
19
+ _hb_face_collect_unicodes
20
+ _hb_face_destroy
21
+ _hb_face_get_upem
22
+ _hb_face_reference_table
23
+ _hb_font_create
24
+ _hb_font_destroy
25
+ _hb_font_glyph_to_string
26
+ _hb_font_set_scale
27
+ _hb_font_set_variations
28
+ _hb_glyph_info_get_glyph_flags
29
+ _hb_language_from_string
30
+ _hb_ot_var_get_axis_infos
31
+ _hb_script_from_string
32
+ _hb_set_create
33
+ _hb_set_destroy
34
+ _hb_set_get_population
35
+ _hb_set_next_many
36
+ _hb_shape
37
+ _hbjs_glyph_svg
38
+ _hbjs_shape_with_trace
39
+ _malloc
40
+ _free
41
+ _free_ptr
package/index.js CHANGED
@@ -6,7 +6,6 @@ module.exports = new Promise(function (resolve, reject) {
6
6
  fs.readFile(path.resolve(__dirname, 'hb.wasm'), function (err, data) {
7
7
  if (err) { reject(err); return; }
8
8
  WebAssembly.instantiate(data).then(function (result) {
9
- result.instance.exports.memory.grow(400); // each page is 64kb in size
10
9
  resolve(hbjs(result.instance));
11
10
  }, reject);
12
11
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harfbuzzjs",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Minimal version of HarfBuzz for JavaScript use",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/hbjs.c DELETED
@@ -1,284 +0,0 @@
1
- #include "harfbuzz/src/hb.h"
2
- #include "harfbuzz/src/hb-ot.h"
3
- #include "string.h"
4
-
5
- enum {
6
- HB_SHAPE_DONT_STOP,
7
- HB_SHAPE_GSUB_PHASE,
8
- HB_SHAPE_GPOS_PHASE
9
- };
10
-
11
- typedef struct user_data_t {
12
- char *str;
13
- unsigned size;
14
- unsigned consumed;
15
- hb_bool_t failure;
16
- unsigned int stop_at;
17
- unsigned int stop_phase;
18
- hb_bool_t stopping;
19
- unsigned int current_phase;
20
- } user_data_t;
21
-
22
-
23
- /* Our modified iota, why not using libc's? it is going to be used
24
- in harfbuzzjs where libc isn't available */
25
- static void _hb_reverse (char *buf, unsigned int len)
26
- {
27
- unsigned start = 0, end = len - 1;
28
- while (start < end)
29
- {
30
- char c = buf[end];
31
- buf[end] = buf[start];
32
- buf[start] = c;
33
- start++; end--;
34
- }
35
- }
36
- static unsigned _hb_itoa (int32_t num, char *buf)
37
- {
38
- unsigned int i = 0;
39
- hb_bool_t is_negative = num < 0;
40
- if (is_negative) num = -num;
41
- do
42
- {
43
- buf[i++] = '0' + num % 10;
44
- num /= 10;
45
- } while (num);
46
- if (is_negative) buf[i++] = '-';
47
- _hb_reverse (buf, i);
48
- buf[i] = '\0';
49
- return i;
50
- }
51
-
52
- static void _append(user_data_t *user_data, char x) {
53
- if (user_data->consumed >= user_data->size) {
54
- user_data->failure = 1;
55
- return;
56
- }
57
- user_data->str[user_data->consumed++] = x;
58
- }
59
-
60
- static void _strcat(user_data_t *user_data, const char *s) {
61
- while (*s) {
62
- _append(user_data, *s++);
63
- }
64
- }
65
-
66
- #define ITOA_BUF_SIZE 12 // 10 digits in int32, 1 for negative sign, 1 for \0
67
-
68
- static void
69
- move_to (hb_position_t to_x, hb_position_t to_y, user_data_t *user_data)
70
- {
71
- /* 4 = command character space + comma + array starts with 0 index + nul character space */
72
- if (user_data->consumed + 2 * ITOA_BUF_SIZE + 4 > user_data->size) return;
73
- _append(user_data, 'M');
74
- user_data->consumed += _hb_itoa (to_x, user_data->str + user_data->consumed);
75
- _append(user_data, ',');
76
- user_data->consumed += _hb_itoa (to_y, user_data->str + user_data->consumed);
77
- }
78
-
79
- static void
80
- line_to (hb_position_t to_x, hb_position_t to_y, user_data_t *user_data)
81
- {
82
- if (user_data->consumed + 2 * ITOA_BUF_SIZE + 4 > user_data->size) return;
83
- _append(user_data, 'L');
84
- user_data->consumed += _hb_itoa (to_x, user_data->str + user_data->consumed);
85
- _append(user_data, ',');
86
- user_data->consumed += _hb_itoa (to_y, user_data->str + user_data->consumed);
87
- }
88
-
89
- static void
90
- quadratic_to (hb_position_t control_x, hb_position_t control_y,
91
- hb_position_t to_x, hb_position_t to_y,
92
- user_data_t *user_data)
93
- {
94
-
95
- if (user_data->consumed + 4 * ITOA_BUF_SIZE + 6 > user_data->size) return;
96
- _append(user_data, 'Q');
97
- user_data->consumed += _hb_itoa (control_x, user_data->str + user_data->consumed);
98
- _append(user_data, ',');
99
- user_data->consumed += _hb_itoa (control_y, user_data->str + user_data->consumed);
100
- _append(user_data, ' ');
101
- user_data->consumed += _hb_itoa (to_x, user_data->str + user_data->consumed);
102
- _append(user_data, ',');
103
- user_data->consumed += _hb_itoa (to_y, user_data->str + user_data->consumed);
104
- }
105
-
106
- static void
107
- cubic_to (hb_position_t control1_x, hb_position_t control1_y,
108
- hb_position_t control2_x, hb_position_t control2_y,
109
- hb_position_t to_x, hb_position_t to_y,
110
- user_data_t *user_data)
111
- {
112
- if (user_data->consumed + 6 * ITOA_BUF_SIZE + 8 > user_data->size) return;
113
- _append(user_data, 'C');
114
- user_data->consumed += _hb_itoa (control1_x, user_data->str + user_data->consumed);
115
- _append(user_data, ',');
116
- user_data->consumed += _hb_itoa (control1_y, user_data->str + user_data->consumed);
117
- _append(user_data, ' ');
118
- user_data->consumed += _hb_itoa (control2_x, user_data->str + user_data->consumed);
119
- _append(user_data, ',');
120
- user_data->consumed += _hb_itoa (control2_y, user_data->str + user_data->consumed);
121
- _append(user_data, ' ');
122
- user_data->consumed += _hb_itoa (to_x, user_data->str + user_data->consumed);
123
- _append(user_data, ',');
124
- user_data->consumed += _hb_itoa (to_y, user_data->str + user_data->consumed);
125
- }
126
-
127
- static void
128
- close_path (user_data_t *user_data)
129
- {
130
- _append(user_data, 'Z');
131
- }
132
-
133
- static hb_draw_funcs_t *funcs = 0;
134
-
135
- int
136
- hbjs_glyph_svg (hb_font_t *font, hb_codepoint_t glyph, char *buf, unsigned buf_size)
137
- {
138
- if (funcs == 0) /* not the best pattern for multi-threaded apps which is not a concern here */
139
- {
140
- funcs = hb_draw_funcs_create (); /* will be leaked */
141
- hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to);
142
- hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to);
143
- hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to);
144
- hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to);
145
- hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path);
146
- }
147
-
148
- user_data_t user_data = {
149
- .str = buf,
150
- .size = buf_size,
151
- .consumed = 0,
152
- .failure = 0,
153
- /* Following members not relevant for SVG */
154
- .stop_at = 0,
155
- .stop_phase = 0,
156
- .stopping = 0,
157
- .current_phase = 0
158
- };
159
- hb_font_draw_glyph (font, glyph, funcs, &user_data);
160
- if (user_data.failure) { return -1; }
161
- buf[user_data.consumed] = '\0';
162
- return user_data.consumed;
163
- }
164
-
165
- static hb_bool_t do_trace (hb_buffer_t *buffer,
166
- hb_font_t *font,
167
- const char *message,
168
- user_data_t *user_data) {
169
- unsigned int consumed;
170
- unsigned int num_glyphs = hb_buffer_get_length (buffer);
171
-
172
- if (strcmp(message, "start table GSUB") == 0) {
173
- user_data->current_phase = HB_SHAPE_GSUB_PHASE;
174
- } else if (strcmp(message, "start table GPOS") == 0) {
175
- user_data->current_phase = HB_SHAPE_GPOS_PHASE;
176
- }
177
-
178
-
179
- if (user_data->current_phase != user_data->stop_phase) {
180
- user_data->stopping = 0;
181
- }
182
-
183
- // If we overflowed, keep going anyway.
184
- if (user_data->failure) return 1;
185
-
186
- if (user_data->stop_phase != HB_SHAPE_DONT_STOP) {
187
- // Do we need to start stopping?
188
- char itoabuf[ITOA_BUF_SIZE];
189
- _hb_itoa(user_data->stop_at, itoabuf);
190
- if ((user_data->current_phase == user_data->stop_phase) &&
191
- (strncmp(message, "end lookup ", 11) == 0) &&
192
- (strcmp(message + 11, itoabuf) == 0)) {
193
- user_data->stopping = 1;
194
- }
195
- }
196
-
197
- // If we need to stop, stop.
198
- if (user_data->stopping) return 0;
199
-
200
- _strcat(user_data, "{\"m\":\"");
201
- _strcat(user_data, message);
202
- _strcat(user_data, "\",\"t\":");
203
- hb_buffer_serialize_glyphs(buffer, 0, num_glyphs,
204
- user_data->str + user_data->consumed,
205
- user_data->size - user_data->consumed,
206
- &consumed,
207
- font,
208
- HB_BUFFER_SERIALIZE_FORMAT_JSON,
209
- HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES);
210
- user_data->consumed += consumed;
211
- _strcat(user_data, "},\n");
212
-
213
-
214
- return 1;
215
- }
216
-
217
- unsigned
218
- hbjs_shape_with_trace (hb_font_t *font, hb_buffer_t* buf,
219
- char* featurestring,
220
- int stop_at, int stop_phase,
221
- char *outbuf, unsigned buf_size) {
222
- user_data_t user_data = {
223
- .str = outbuf,
224
- .size = buf_size,
225
- .consumed = 0,
226
- .failure = 0,
227
- .stop_at = stop_at,
228
- .stop_phase = stop_phase,
229
- .stopping = 0,
230
- .current_phase = 0
231
- };
232
-
233
- int num_features = 0;
234
- hb_feature_t* features = NULL;
235
-
236
- if (*featurestring) {
237
- /* count the features first, so we can allocate memory */
238
- char* p = featurestring;
239
- do {
240
- num_features++;
241
- p = strchr (p, ',');
242
- if (p)
243
- p++;
244
- } while (p);
245
-
246
- features = (hb_feature_t *) calloc (num_features, sizeof (*features));
247
-
248
- /* now do the actual parsing */
249
- p = featurestring;
250
- num_features = 0;
251
- while (p && *p) {
252
- char *end = strchr (p, ',');
253
- if (hb_feature_from_string (p, end ? end - p : -1, &features[num_features]))
254
- num_features++;
255
- p = end ? end + 1 : NULL;
256
- }
257
- }
258
-
259
- hb_buffer_set_message_func (buf, (hb_buffer_message_func_t)do_trace, &user_data, NULL);
260
- user_data.str[user_data.consumed++] = '[';
261
- hb_shape(font, buf, features, num_features);
262
-
263
- if (user_data.failure) return -1;
264
-
265
- user_data.str[user_data.consumed-2] = ']';
266
- user_data.str[user_data.consumed-1] = '\0';
267
- return user_data.consumed;
268
- }
269
-
270
- #ifdef MAIN
271
- #include <stdio.h>
272
- int main() {
273
- hb_blob_t *blob = hb_blob_create_from_file ("/home/ebrahim/Desktop/harfbuzzjs/harfbuzz/test/subset/data/fonts/Roboto-Regular.ttf");
274
- hb_face_t *face = hb_face_create (blob, 0);
275
- hb_blob_destroy (blob);
276
- hb_font_t *font = hb_font_create (face);
277
- hb_face_destroy (face);
278
- char buf[1024];
279
- buf[0] = '\0';
280
- printf ("%d %d\n", hb_blob_get_length (blob), hbjs_ot_glyph_svg (font, 0, buf, sizeof (buf)));
281
- puts (buf);
282
- hb_font_destroy (font);
283
- }
284
- #endif
package/libc/ctype.h DELETED
@@ -1,73 +0,0 @@
1
- // Source: https://github.com/intel/zephyr/blob/c187536/lib/libc/minimal/include/ctype.h
2
- /* ctype.h */
3
-
4
- /*
5
- * Copyright (c) 2015 Intel Corporation.
6
- *
7
- * SPDX-License-Identifier: Apache-2.0
8
- */
9
-
10
- #ifndef __INC_ctype_h__
11
- #define __INC_ctype_h__
12
-
13
- #ifdef __cplusplus
14
- extern "C" {
15
- #endif
16
-
17
- static inline int isupper(int a)
18
- {
19
- return ((unsigned)(a)-'A') < 26;
20
- }
21
-
22
- static inline int isalpha(int c)
23
- {
24
- return (((unsigned)c|32)-'a') < 26;
25
- }
26
-
27
- static inline int isspace(int c)
28
- {
29
- return c == ' ' || ((unsigned)c-'\t') < 5;
30
- }
31
-
32
- static inline int isgraph(int c)
33
- {
34
- return ((((unsigned)c) > ' ') && (((unsigned)c) <= '~'));
35
- }
36
-
37
- static inline int isprint(int c)
38
- {
39
- return ((((unsigned)c) >= ' ') && (((unsigned)c) <= '~'));
40
- }
41
-
42
- static inline int isdigit(int a)
43
- {
44
- return (((unsigned)(a)-'0') < 10);
45
- }
46
-
47
- static inline int isxdigit(int a)
48
- {
49
- unsigned int ua = (unsigned int)a;
50
-
51
- return ((ua - '0') < 10) || ((ua - 'a') < 6) || ((ua - 'A') < 6);
52
- }
53
-
54
- static inline int tolower(int chr)
55
- {
56
- return (chr >= 'A' && chr <= 'Z') ? (chr + 32) : (chr);
57
- }
58
-
59
- static inline int toupper(int chr)
60
- {
61
- return (chr >= 'a' && chr <= 'z') ? (chr - 32) : (chr);
62
- }
63
-
64
- static inline int isalnum(int chr)
65
- {
66
- return isalpha(chr) || isdigit(chr);
67
- }
68
-
69
- #ifdef __cplusplus
70
- }
71
- #endif
72
-
73
- #endif /* __INC_ctype_h__ */