/* Usage: nn = read (f, &buf, n); */ static void posix_read (SLFile_FD_Type *f, SLang_Ref_Type *ref, unsigned int *nbytes) { unsigned int len; char *b; SLang_BString_Type *bstr; b = NULL; len = *nbytes; if ((NULL == (b = SLmalloc (len + 1))) || (-1 == do_read (f, b, &len))) goto return_error; if (len != *nbytes) { char *b1 = SLrealloc (b, len + 1); if (b1 == NULL) goto return_error; b = b1; } bstr = SLbstring_create_malloced ((unsigned char *) b, len, 0); if (bstr != NULL) { if (-1 == SLang_assign_to_ref (ref, SLANG_BSTRING_TYPE, (VOID_STAR)&bstr)) { SLbstring_free (bstr); return; } SLbstring_free (bstr); (void) SLang_push_uinteger (len); return; } return_error: if (b != NULL) SLfree ((char *)b); (void) SLang_assign_to_ref (ref, SLANG_NULL_TYPE, NULL); (void) SLang_push_integer (-1); }
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; }