unsigned int _pSLpack_compute_size (char *format) { unsigned int n; n = 0; (void) compute_size_for_format (format, &n); return n; }
SLstrlen_Type _pSLpack_compute_size (char *format) { SLstrlen_Type n; n = 0; (void) compute_size_for_format (format, &n); return n; }
void _pSLpack_pad_format (char *format) { unsigned int len, max_len; Format_Type ft; char *buf, *b; check_native_byte_order (); /* Just check the syntax */ if (-1 == compute_size_for_format (format, &max_len)) return; /* This should be sufficient to handle any needed xyy padding characters. * I cannot see how this will be overrun */ max_len = 4 * (strlen (format) + 1); if (NULL == (buf = SLmalloc (max_len + 1))) return; b = buf; len = 0; while (1 == parse_a_format (&format, &ft)) { struct { char a; short b; } s_h; struct { char a; int b; } s_i; struct { char a; long b; } s_l; struct { char a; float b; } s_f; struct { char a; double b; } s_d; unsigned int pad; if (ft.repeat == 0) continue; if (ft.data_type == 0) { /* pad */ sprintf (b, "x%u", ft.repeat); b += strlen (b); len += ft.repeat; continue; } switch (ft.data_type) { default: case SLANG_STRING_TYPE: case SLANG_BSTRING_TYPE: case SLANG_CHAR_TYPE: case SLANG_UCHAR_TYPE: pad = 0; break; case SLANG_SHORT_TYPE: case SLANG_USHORT_TYPE: pad = ((unsigned int) ((char *)&s_h.b - (char *)&s_h.a)); break; case SLANG_INT_TYPE: case SLANG_UINT_TYPE: pad = ((unsigned int) ((char *)&s_i.b - (char *)&s_i.a)); break; case SLANG_LONG_TYPE: case SLANG_ULONG_TYPE: pad = ((unsigned int) ((char *)&s_l.b - (char *)&s_l.a)); break; case SLANG_FLOAT_TYPE: pad = ((unsigned int) ((char *)&s_f.b - (char *)&s_f.a)); break; case SLANG_DOUBLE_TYPE: pad = ((unsigned int) ((char *)&s_d.b - (char *)&s_d.a)); break; } /* Pad to a length that is an integer multiple of pad. */ if (pad) pad = pad * ((len + pad - 1)/pad) - len; if (pad) { sprintf (b, "x%u", pad); b += strlen (b); len += pad; } *b++ = ft.format_type; if (ft.repeat > 1) { sprintf (b, "%u", ft.repeat); b += strlen (b); } len += ft.repeat * ft.sizeof_type; } *b = 0; (void) SLang_push_malloced_string (buf); }
void _pSLunpack (char *format, SLang_BString_Type *bs) { Format_Type ft; unsigned char *b; unsigned int len; unsigned int num_bytes; check_native_byte_order (); if (-1 == compute_size_for_format (format, &num_bytes)) return; b = SLbstring_get_pointer (bs, &len); if (b == NULL) return; if (len < num_bytes) { _pSLang_verror (SL_INVALID_PARM, "unpack format %s is too large for input string", format); return; } while (1 == parse_a_format (&format, &ft)) { char *str, *s; if (ft.repeat == 0) continue; if (ft.data_type == 0) { /* skip padding */ b += ft.repeat; continue; } if (ft.is_scalar) { SLang_Array_Type *at; SLindex_Type dims; if (ft.repeat == 1) { SLang_Class_Type *cl; cl = _pSLclass_get_class (ft.data_type); memcpy ((char *)cl->cl_transfer_buf, (char *)b, ft.sizeof_type); if (ft.byteorder != NATIVE_ORDER) byteswap (ft.byteorder, (unsigned char *)cl->cl_transfer_buf, ft.sizeof_type, 1); if (-1 == (cl->cl_apush (ft.data_type, cl->cl_transfer_buf))) return; b += ft.sizeof_type; continue; } dims = (SLindex_Type) ft.repeat; at = SLang_create_array (ft.data_type, 0, NULL, &dims, 1); if (at == NULL) return; num_bytes = ft.repeat * ft.sizeof_type; memcpy ((char *)at->data, (char *)b, num_bytes); if (ft.byteorder != NATIVE_ORDER) byteswap (ft.byteorder, (unsigned char *)at->data, ft.sizeof_type, ft.repeat); if (-1 == SLang_push_array (at, 1)) return; b += num_bytes; continue; } /* string type: s, S, or Z */ if (ft.format_type == 's') len = ft.repeat; else len = get_unpadded_strlen ((char *)b, ft.pad, ft.repeat); str = SLmalloc (len + 1); if (str == NULL) return; memcpy ((char *) str, (char *)b, len); str [len] = 0; /* Avoid a bstring if possible */ s = SLmemchr (str, 0, len); if (s == NULL) { if (-1 == SLang_push_malloced_string (str)) return; } else { SLang_BString_Type *new_bs; new_bs = SLbstring_create_malloced ((unsigned char *)str, len, 1); if (new_bs == NULL) return; if (-1 == SLang_push_bstring (new_bs)) { SLfree (str); return; } SLbstring_free (new_bs); } b += ft.repeat; } }
static SLang_BString_Type * pack_according_to_format (char *format, unsigned int nitems) { unsigned int size, num; unsigned char *buf, *b; SLang_BString_Type *bs; Format_Type ft; buf = NULL; if (-1 == compute_size_for_format (format, &size)) goto return_error; if (NULL == (buf = (unsigned char *) SLmalloc (size + 1))) goto return_error; b = buf; while (1 == parse_a_format (&format, &ft)) { unsigned char *ptr; unsigned int repeat; repeat = ft.repeat; if (ft.data_type == 0) { memset ((char *) b, ft.pad, repeat); b += repeat; continue; } if (ft.is_scalar) { unsigned char *bstart; num = repeat; bstart = b; while (repeat != 0) { unsigned int nelements; SLang_Array_Type *at; if (nitems == 0) { _pSLang_verror (SL_INVALID_PARM, "Not enough items for pack format"); goto return_error; } if (-1 == SLang_pop_array_of_type (&at, ft.data_type)) goto return_error; nelements = at->num_elements; if (repeat < nelements) nelements = repeat; repeat -= nelements; nelements = nelements * ft.sizeof_type; memcpy ((char *)b, (char *)at->data, nelements); b += nelements; SLang_free_array (at); nitems--; } if (ft.byteorder != NATIVE_ORDER) byteswap (ft.byteorder, bstart, ft.sizeof_type, num); continue; } /* Otherwise we have a string */ if (-1 == SLang_pop_bstring (&bs)) goto return_error; ptr = SLbstring_get_pointer (bs, &num); if (repeat < num) num = repeat; memcpy ((char *)b, (char *)ptr, num); b += num; repeat -= num; if ((repeat == 0) && (ft.format_type == 'z')) { if (num) *(b-1) = 0; } else memset ((char *)b, ft.pad, repeat); SLbstring_free (bs); b += repeat; nitems--; } *b = 0; bs = SLbstring_create_malloced (buf, size, 0); if (bs == NULL) goto return_error; SLdo_pop_n (nitems); return bs; return_error: SLdo_pop_n (nitems); if (buf != NULL) SLfree ((char *) buf); return NULL; }