diff options
Diffstat (limited to 'src/pack.c')
-rw-r--r-- | src/pack.c | 178 |
1 files changed, 177 insertions, 1 deletions
@@ -22,6 +22,8 @@ | |||
22 | #include <ctype.h> | 22 | #include <ctype.h> |
23 | #include <inttypes.h> | 23 | #include <inttypes.h> |
24 | #include <limits.h> | 24 | #include <limits.h> |
25 | #include <arpa/inet.h> | ||
26 | #include <errno.h> | ||
25 | #include "pack.h" | 27 | #include "pack.h" |
26 | 28 | ||
27 | /* Data format specification is a simplified form of Perl pack() template. | 29 | /* Data format specification is a simplified form of Perl pack() template. |
@@ -47,6 +49,14 @@ | |||
47 | i A signed integer value. | 49 | i A signed integer value. |
48 | I A unsigned integer value. | 50 | I A unsigned integer value. |
49 | 51 | ||
52 | n An unsigned short (16-bit) in "network" (big-endian) order. | ||
53 | N An unsigned long (32-bit) in "network" (big-endian) order. | ||
54 | v An unsigned short (16-bit) in "VAX" (little-endian) order. | ||
55 | V An unsigned long (32-bit) in "VAX" (little-endian) order. | ||
56 | |||
57 | f A single-precision float in native format. | ||
58 | d A double-precision float in native format. | ||
59 | |||
50 | x A null byte (a.k.a ASCII NUL, "\000", chr(0)) | 60 | x A null byte (a.k.a ASCII NUL, "\000", chr(0)) |
51 | X Back up a byte. | 61 | X Back up a byte. |
52 | @ Null-fill or truncate to absolute position, counted from the | 62 | @ Null-fill or truncate to absolute position, counted from the |
@@ -328,6 +338,166 @@ I_unpacker(struct packenv *env, int rep) | |||
328 | env->buf_pos += sizeof(unsigned); | 338 | env->buf_pos += sizeof(unsigned); |
329 | } | 339 | } |
330 | 340 | ||
341 | /* n - An unsigned short (16-bit) in "network" (big-endian) order. */ | ||
342 | static void | ||
343 | n_packer(struct packenv *env, int rep) | ||
344 | { | ||
345 | if (env->buf_base) { | ||
346 | char *arg = packenv_get(env); | ||
347 | if (arg) { | ||
348 | uintmax_t x; | ||
349 | if (getunum(arg, UINT16_MAX, &x) == 0) { | ||
350 | uint16_t v = htons((uint16_t) x); | ||
351 | memcpy(env->buf_base + env->buf_pos, | ||
352 | &v, sizeof(v)); | ||
353 | } | ||
354 | } | ||
355 | } | ||
356 | env->buf_pos += sizeof(uint16_t); | ||
357 | } | ||
358 | |||
359 | static void | ||
360 | n_unpacker(struct packenv *env, int rep) | ||
361 | { | ||
362 | uint16_t v = ntohs(*(uint16_t *)(env->buf_base + env->buf_pos)); | ||
363 | printunum(env->fp, v); | ||
364 | env->buf_pos += sizeof(uint16_t); | ||
365 | } | ||
366 | |||
367 | /* N - An unsigned long (32-bit) in "network" (big-endian) order. */ | ||
368 | static void | ||
369 | N_packer(struct packenv *env, int rep) | ||
370 | { | ||
371 | if (env->buf_base) { | ||
372 | char *arg = packenv_get(env); | ||
373 | if (arg) { | ||
374 | uintmax_t x; | ||
375 | if (getunum(arg, UINT32_MAX, &x) == 0) { | ||
376 | uint32_t v = htonl((uint32_t) x); | ||
377 | memcpy(env->buf_base + env->buf_pos, | ||
378 | &v, sizeof(v)); | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | env->buf_pos += sizeof(uint32_t); | ||
383 | } | ||
384 | |||
385 | static void | ||
386 | N_unpacker(struct packenv *env, int rep) | ||
387 | { | ||
388 | uint32_t v = ntohl(*(uint32_t *)(env->buf_base + env->buf_pos)); | ||
389 | printunum(env->fp, v); | ||
390 | env->buf_pos += sizeof(uint32_t); | ||
391 | } | ||
392 | |||
393 | /* v - An unsigned short (16-bit) in "VAX" (little-endian) order. */ | ||
394 | static void | ||
395 | v_packer(struct packenv *env, int rep) | ||
396 | { | ||
397 | if (env->buf_base) { | ||
398 | char *arg = packenv_get(env); | ||
399 | if (arg) { | ||
400 | uintmax_t x; | ||
401 | if (getunum(arg, UINT16_MAX, &x) == 0) { | ||
402 | uint16_t v = ntohs((uint16_t) x); | ||
403 | memcpy(env->buf_base + env->buf_pos, | ||
404 | &v, sizeof(v)); | ||
405 | } | ||
406 | } | ||
407 | } | ||
408 | env->buf_pos += sizeof(uint16_t); | ||
409 | } | ||
410 | |||
411 | static void | ||
412 | v_unpacker(struct packenv *env, int rep) | ||
413 | { | ||
414 | uint16_t v = htons(*(uint16_t *)(env->buf_base + env->buf_pos)); | ||
415 | printunum(env->fp, v); | ||
416 | env->buf_pos += sizeof(uint16_t); | ||
417 | } | ||
418 | |||
419 | /* V - An unsigned long (32-bit) in "VAX" (little-endian) order. */ | ||
420 | static void | ||
421 | V_packer(struct packenv *env, int rep) | ||
422 | { | ||
423 | if (env->buf_base) { | ||
424 | char *arg = packenv_get(env); | ||
425 | if (arg) { | ||
426 | uintmax_t x; | ||
427 | if (getunum(arg, UINT32_MAX, &x) == 0) { | ||
428 | uint32_t v = ntohl((uint32_t) x); | ||
429 | memcpy(env->buf_base + env->buf_pos, | ||
430 | &v, sizeof(v)); | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | env->buf_pos += sizeof(uint32_t); | ||
435 | } | ||
436 | |||
437 | static void | ||
438 | V_unpacker(struct packenv *env, int rep) | ||
439 | { | ||
440 | uint32_t v = htonl(*(uint32_t *)(env->buf_base + env->buf_pos)); | ||
441 | printunum(env->fp, v); | ||
442 | env->buf_pos += sizeof(uint32_t); | ||
443 | } | ||
444 | |||
445 | /* f - A single-precision float in native format. */ | ||
446 | static void | ||
447 | f_packer(struct packenv *env, int rep) | ||
448 | { | ||
449 | if (env->buf_base) { | ||
450 | char *arg = packenv_get(env); | ||
451 | if (arg) { | ||
452 | float v; | ||
453 | char *p; | ||
454 | |||
455 | errno = 0; | ||
456 | v = strtof(arg, &p); | ||
457 | if (*p == 0 && errno == 0) | ||
458 | memcpy(env->buf_base + env->buf_pos, | ||
459 | &v, sizeof(v)); | ||
460 | } | ||
461 | } | ||
462 | env->buf_pos += sizeof(float); | ||
463 | } | ||
464 | |||
465 | static void | ||
466 | f_unpacker(struct packenv *env, int rep) | ||
467 | { | ||
468 | float v = *(float *)(env->buf_base + env->buf_pos); | ||
469 | fprintf(env->fp, "%f", v); /* FIXME: Format? */ | ||
470 | env->buf_pos += sizeof(uint32_t); | ||
471 | } | ||
472 | |||
473 | /* d - A double-precision float in native format. */ | ||
474 | static void | ||
475 | d_packer(struct packenv *env, int rep) | ||
476 | { | ||
477 | if (env->buf_base) { | ||
478 | char *arg = packenv_get(env); | ||
479 | if (arg) { | ||
480 | double v; | ||
481 | char *p; | ||
482 | |||
483 | errno = 0; | ||
484 | v = strtod(arg, &p); | ||
485 | if (*p == 0 && errno == 0) | ||
486 | memcpy(env->buf_base + env->buf_pos, | ||
487 | &v, sizeof(v)); | ||
488 | } | ||
489 | } | ||
490 | env->buf_pos += sizeof(double); | ||
491 | } | ||
492 | |||
493 | static void | ||
494 | d_unpacker(struct packenv *env, int rep) | ||
495 | { | ||
496 | double v = *(double *)(env->buf_base + env->buf_pos); | ||
497 | fprintf(env->fp, "%g", v); /* FIXME: Format? */ | ||
498 | env->buf_pos += sizeof(double); | ||
499 | } | ||
500 | |||
331 | static void | 501 | static void |
332 | x_packer(struct packenv *env, int rep) | 502 | x_packer(struct packenv *env, int rep) |
333 | { | 503 | { |
@@ -393,7 +563,13 @@ static struct packspec packspec[] = { | |||
393 | { 'Q', 0, Q_packer, Q_unpacker }, | 563 | { 'Q', 0, Q_packer, Q_unpacker }, |
394 | { 'i', 0, i_packer, i_unpacker }, | 564 | { 'i', 0, i_packer, i_unpacker }, |
395 | { 'I', 0, I_packer, I_unpacker }, | 565 | { 'I', 0, I_packer, I_unpacker }, |
396 | /* FIXME: n N v V f d */ | 566 | { 'n', 0, n_packer, n_unpacker }, |
567 | { 'N', 0, N_packer, N_unpacker }, | ||
568 | { 'v', 0, v_packer, v_unpacker }, | ||
569 | { 'V', 0, V_packer, V_unpacker }, | ||
570 | { 'f', 0, f_packer, f_unpacker }, | ||
571 | { 'd', 0, d_packer, d_unpacker }, | ||
572 | |||
397 | { 'x', 0, x_packer, x_unpacker }, | 573 | { 'x', 0, x_packer, x_unpacker }, |
398 | { 'X', 0, X_packer, X_packer }, | 574 | { 'X', 0, X_packer, X_packer }, |
399 | { '@', F_REP, at_packer, at_unpacker }, | 575 | { '@', F_REP, at_packer, at_unpacker }, |