Exemple #1
0
static ss_t *aux_resize(ss_t **s, const sbool_t cat, const ss_t *src,
			const size_t n, char fill_byte)
{
	ASSERT_RETURN_IF(!s, ss_void);
	if (!src)
		src = ss_void;
	const size_t src_size = sd_get_size(src),
		     at = (cat && *s) ? sd_get_size(*s) : 0,
		     out_size = at + n;  /* BEHAVIOR: n overflow TODO */
	const sbool_t aliasing = *s == src;
	if (src_size < n) { /* fill */
		if (ss_reserve(s, out_size) >= out_size) {
			char *o = get_str(*s);
			if (!aliasing) {
				const char *p = get_str_r(src);
				memcpy(o + at, p, src_size);
			}
			memset(o + at + src_size, fill_byte,
				n - src_size);
			set_size(*s, out_size);
		}
	} else { /* else: cut (implicit) */
		if (ss_reserve(s, out_size) >= out_size) {
			if (!aliasing)
				memcpy(get_str(*s) + at, get_str_r(src), n);
			set_size(*s, out_size);
		}
	}
	return *s;
}
Exemple #2
0
static ss_t *aux_resize_u(ss_t **s, const sbool_t cat, ss_t *src,
			  const size_t u_chars, int fill_char)
{
	ASSERT_RETURN_IF(!s, ss_void);
	if (!src)
		src = ss_void;
	const size_t at = (cat && *s) ? sd_get_size(*s) : 0,
		     char_size = sc_wc_to_utf8_size(fill_char),
		     current_u_chars = ss_len_u(src);
	RETURN_IF(u_chars == current_u_chars, ss_check(s)); /* same */
	const sbool_t aliasing = *s == src;
	const size_t srcs = sd_get_size(src);
	if (current_u_chars < u_chars) { /* fill */
		const size_t new_elems = u_chars - current_u_chars,
			     at_inc = srcs + new_elems * char_size;
		SS_OVERFLOW_CHECK(s, at, at_inc);
		const size_t out_size = at + at_inc;
		if (ss_reserve(s, out_size) >= out_size) {
			if (!cat && !aliasing) /* copy */
				ss_clear(s);
			if (!aliasing) {
				memcpy(get_str(*s) + at, get_str_r(src), srcs);
				inc_unicode_size(*s, current_u_chars);
				inc_size(*s, srcs);
			}
			size_t i = 0;
			for (; i < new_elems; i++)
				ss_cat_char(s, fill_char);
		}
	} else { /* cut */
		const char *ps = get_str_r(src);
		size_t actual_unicode_count = 0;
		const size_t head_size = sc_unicode_count_to_utf8_size(
						ps, 0, srcs, u_chars,
						&actual_unicode_count);
		SS_OVERFLOW_CHECK(s, at, head_size);
		const size_t out_size = at + head_size;
		S_ASSERT(u_chars == actual_unicode_count);
		if (!aliasing) { /* copy or cat */
			if (ss_reserve(s, out_size) >= out_size) {
				if (!cat && !aliasing) /* copy */
					ss_clear(s);
				memcpy(get_str(*s) + at, ps, head_size);
				inc_unicode_size(*s, actual_unicode_count);
				inc_size(*s, head_size);
			}
		} else { /* cut */
			set_size(*s, head_size);
			set_unicode_size(*s, actual_unicode_count);
		}
	}
	return *s;
}
Exemple #3
0
sbool_t aux_jpeg_dec_init(struct jpeg_decompress_struct *jd,
			  struct aux_jpeg *ja, struct RGB_Info *ri,
			  const ss_t *jpg_in, ss_t **rgb_out)
{
	RETURN_IF(!ja || !ri || !jpg_in || !rgb_out, S_FALSE);
	jpeg_create_decompress(jd);
	jd->err->trace_level = 0;
	jd->err->error_exit = jpg_error_exit;
	ja->in = jpg_in;
	ja->out = rgb_out;
	jd->src = &ja->jsrc;
	aux_jpeg_common_init(ja);
	ja->jsrc.init_source = aux_jpegd_init;
	ja->jsrc.fill_input_buffer = aux_jpegd_fill_input_buffer;
	ja->jsrc.skip_input_data = aux_jpegd_skip_input_data;
	ja->jsrc.resync_to_restart = jpeg_resync_to_restart;
	ja->jsrc.term_source = aux_jpegd_term_source;
	ja->jsrc.next_input_byte = (JOCTET *)ss_get_buffer_r(jpg_in);
	ja->jsrc.bytes_in_buffer = ss_size(jpg_in);
	RETURN_IF(jpeg_read_header(jd, TRUE) != JPEG_HEADER_OK, 0);
	jpeg_start_decompress(jd);
	set_rgbi(ri, jd->output_width, jd->output_height,
		 jd->out_color_components * 8, jd->out_color_components);
	RETURN_IF(!valid_rgbi(ri), S_FALSE);
	size_t rgb_size = ri->row_size * ri->height;
	if (ss_reserve(rgb_out, rgb_size) >= rgb_size)
		return S_TRUE;
	jpeg_destroy_decompress(jd);
	return S_FALSE;
}
Exemple #4
0
static ss_t *aux_rtrim(ss_t **s, const sbool_t cat, const ss_t *src)
{
	ASSERT_RETURN_IF(!s, ss_void);
	if (!src)
		src = ss_void;
	const size_t ss = sd_get_size(src),
		     at = (cat && *s) ? sd_get_size(*s) : 0;
	if (ss > 0) {
		const sbool_t aliasing = *s == src;
		const char *ps = get_str_r(src);
		size_t i = ss - 1;
		for (; i > 0 && isspace(ps[i]); i--);
		if (isspace(ps[i]))
			i--;
		const size_t nspaces = ss - i - 1,
			     copy_size = ss - nspaces,
			     out_size = at + copy_size,
			     cat_usize = cat ? get_unicode_size(*s) : 0,
			     src_usize = *s ? get_unicode_size(*s) : 0;
		if (ss_reserve(s, out_size) >= out_size) {
			char *pt = get_str(*s);
			if (!aliasing)
				 memcpy(pt + at, ps, copy_size);
			set_size(*s, out_size);
			set_unicode_size(*s, cat_usize + src_usize - nspaces);
		}
	} else {
		if (cat)
			ss_check(s);
		else
			ss_clear(s);
	}
	return *s;
}
Exemple #5
0
static size_t tga2rgb(ss_t **rgb, struct RGB_Info *ri, const ss_t *tga)
{
	const char *t = ss_get_buffer_r(tga);
	const size_t ts = ss_size(tga);
	RETURN_IF(ts < TGA_RGBHDR || !valid_tga(t), 0);
	set_rgbi(ri, S_LD_LE_U16(t + TGA_W), S_LD_LE_U16(t + TGA_H),
		 t[TGA_BPP], t[TGA_TYPE] == TGA_RAW_GRAY ? 1 : t[TGA_BPP]/8);
	RETURN_IF(!valid_rgbi(ri), 0);
	size_t rgb_bytes = ri->row_size * ri->height;
	RETURN_IF(ts < rgb_bytes + TGA_RGBHDR, 0);
	RETURN_IF(ss_reserve(rgb, rgb_bytes) < rgb_bytes, 0);
	if ((t[TGA_DESC] & TGA_TOP_LEFT) != 0) {
		if (ri->chn == 1)
			ss_cpy_cn(rgb, t + TGA_RGBHDR, rgb_bytes);
		else
			tga_rgb_swap(ri->bpp, rgb_bytes,
				     ss_get_buffer_r(tga) + TGA_RGBHDR,
				     ss_get_buffer(*rgb));
	} else {
		ss_set_size(*rgb, 0);
		ssize_t i = (ssize_t)(ri->height - 1) * ri->row_size;
		for (; i >= 0; i -= ri->row_size)
			if (ri->chn == 1)
				ss_cat_cn(rgb, t + TGA_RGBHDR + i,
					  ri->row_size);
			else
				tga_rgb_swap(ri->bpp, ri->row_size,
					     t + TGA_RGBHDR + i,
					     ss_get_buffer(*rgb) + i);
	}
	ss_set_size(*rgb, rgb_bytes);
	return rgb_bytes;
}
Exemple #6
0
static ss_t *aux_erase(ss_t **s, const sbool_t cat, const ss_t *src,
		       const size_t off, const size_t n)
{
	ASSERT_RETURN_IF(!s, ss_void);
	if (!src)
		src = ss_void;
	const size_t ss0 = sd_get_size(src),
			   at = (cat && *s) ? sd_get_size(*s) : 0;
	const sbool_t overflow = off + n > ss0;
	const size_t src_size = overflow ? ss0 - off : n,
		     copy_size = ss0 - off - src_size;
	if (*s == src) { /* BEHAVIOR: aliasing: copy-only */
		if (off + n >= ss0) { /* tail clean cut */
			set_size(*s, off);
		} else {
			char *ps = get_str(*s);
			memmove(ps + off, ps + off + n, copy_size);
			set_size(*s, ss0 - n);
		}
		set_unicode_size_cached(*s, S_FALSE);
	} else { /* copy or cat */
		const size_t out_size = at + off + copy_size;
		if (ss_reserve(s, out_size) >= out_size) {
			char *po = get_str(*s);
			memcpy(po + at, get_str_r(src), off);
			memcpy(po + at + off,
			       get_str_r(src) + off + n, copy_size);
			set_size(*s, out_size);
			set_unicode_size_cached(*s, S_FALSE);
		}
	}
	return ss_check(s);
}
Exemple #7
0
static ss_t *aux_toenc(ss_t **s, const sbool_t cat, const ss_t *src, senc_f_t f)
{
	ASSERT_RETURN_IF(!s, ss_void);
	if (!src)
		src = ss_void;
	const int aliasing = *s == src;
	const size_t in_size = sd_get_size(src),
		     at = (cat && *s) ? sd_get_size(*s) : 0,
		     out_size = at + f(NULL, in_size, NULL);
	if (ss_reserve(s, out_size) >= out_size) {
		const ss_t *src1 = aliasing ? *s : src;
		f((const unsigned char *)get_str_r(src1), in_size,
		  (unsigned char *)get_str(*s) + at);
		if (at == 0) {
			set_unicode_size_cached(*s, S_TRUE);
			set_unicode_size(*s, in_size * 2);
		} else { /* cat */
			if (is_unicode_size_cached(*s) &&
			    at == sd_get_size(*s))
				set_unicode_size(*s, get_unicode_size(*s) +
						     in_size * 2);
			else
				set_unicode_size_cached(*s, S_FALSE);
		}
		set_size(*s, out_size);
	}
	return ss_check(s);
}
Exemple #8
0
static sbool_t aux_png_read_set_rows(png_bytep *rows, const png_info *pi,
				     ss_t **rgb)
{
	RETURN_IF(!rows || !pi || !rgb, S_FALSE);
	size_t rs = aux_png_row_size(pi), rgb_size = rs * pi->height;
	RETURN_IF(ss_reserve(rgb, rgb_size) < rgb_size, S_FALSE);
	ss_set_size(*rgb, rgb_size);
	return aux_png_set_rows(rows, pi, ss_get_buffer(*rgb));
}
Exemple #9
0
ss_t *ss_cpy_char(ss_t **s, const int c)
{
	ASSERT_RETURN_IF(!s, ss_void);
	if (ss_reserve(s, SSU8_MAX_SIZE) >= SSU8_MAX_SIZE) {
		ss_clear(s);
		return ss_cat_char(s, c);
	}
	return *s;
}
Exemple #10
0
ss_t *ss_cpy_printf_va(ss_t **s, const size_t size, const char *fmt, va_list ap)
{
	ASSERT_RETURN_IF(!s, ss_void);
	ASSERT_RETURN_IF((!size || !fmt) && ss_clear(s), *s);
	if (*s) {
		ss_reserve(s, size);
		ss_clear(s);
	}
	return ss_cat_printf_va(s, size, fmt, ap);
}
Exemple #11
0
sbool_t aux_jpeg_enc_init(struct jpeg_compress_struct *jc,
			  struct aux_jpeg *ja, const struct RGB_Info *ri,
			  const ss_t *rgb, ss_t **jpg_out)
{
	RETURN_IF(!ja || !valid_rgbi(ri) || !rgb || !jpg_out, S_FALSE);
	ss_set_size(*jpg_out, 0);
	jpeg_create_compress(jc);
	jc->in_color_space = ri->chn == 1 ? JCS_GRAYSCALE : JCS_RGB;
	jpeg_set_defaults(jc);
	jc->input_components = ri->chn;
	jc->data_precision = ri->bpp / ri->chn;
	jc->image_width = ri->width;
	jc->image_height = ri->height;
	jpeg_default_colorspace(jc);
	jc->smoothing_factor = JPG_SMOOTH;
	jc->arith_code = FALSE;
	if (ri->chn == 1)
		jpeg_set_colorspace(jc, JCS_GRAYSCALE);
	jc->mem->max_memory_to_use = JPG_TMP_MAX_MEM;
	jc->restart_in_rows = 0;
	jc->optimize_coding = TRUE;
	jc->err->trace_level = 0;
	jc->err->error_exit = jpg_error_exit;
#ifdef S_HW_FPU
	jc->dct_method = JDCT_FLOAT;
#else
	jc->dct_method = JDCT_ISLOW;
#endif
#ifdef JPG_SUBS_HQ /* No chroma subsampling (better quality, +30% size) */
	jc->comp_info[0].h_samp_factor = jc->comp_info[0].v_samp_factor =
	jc->comp_info[1].h_samp_factor = jc->comp_info[1].v_samp_factor =
	jc->comp_info[2].h_samp_factor = jc->comp_info[2].v_samp_factor = 1;
#endif
	jpeg_set_quality(jc, JPG_QUALITY, TRUE);
	aux_jpeg_common_init(ja);
	/* Max out size: this is an heuristic (adjusted afterwards) */
	ja->max_out_size = (ri->width * ri->height * ri->bpp) / 8;
	RETURN_IF(ss_reserve(jpg_out, ja->max_out_size) < ja->max_out_size,
		  S_FALSE);
	ja->in = rgb;
	ja->out = jpg_out;
	ja->ri_enc = ri;
	ja->errors = S_FALSE;
	ja->jdest.init_destination = aux_jpege_init;
	ja->jdest.empty_output_buffer = aux_jpege_empty_output_buffer;
	ja->jdest.term_destination = aux_jpege_term_destination;
	jc->client_data = ja;
	jc->dest = &ja->jdest;
	return S_TRUE;
}
Exemple #12
0
ss_t *ss_cpy_printf(ss_t **s, const size_t size, const char *fmt, ...)
{
	ASSERT_RETURN_IF(!s, ss_void);
	ASSERT_RETURN_IF((!size || !fmt) && ss_clear(s), *s);
	if (*s) {
		ss_reserve(s, size);
		ss_clear(s);
	}
	va_list ap;
	va_start(ap, fmt);
	ss_cat_printf_va(s, size, fmt, ap);
	va_end(ap);
	return *s;
}
Exemple #13
0
static ss_t *aux_erase_u(ss_t **s, const sbool_t cat, const ss_t *src,
			 const size_t char_off, const size_t n)
{
	ASSERT_RETURN_IF(!s, ss_void);
	if (!src)
		src = ss_void;
	const char *ps = get_str_r(src);
	const size_t sso0 = *s ? sd_get_size(*s) : 0,
		     ss0 = sd_get_size(src),
		     head_size = sc_unicode_count_to_utf8_size(ps, 0, ss0,
							char_off, NULL);
	RETURN_IF(head_size >= ss0, ss_check(s)); /* BEHAVIOR */
	size_t actual_n = 0;
	const size_t cus = *s ? get_unicode_size(*s) : 0,
		     cut_size = sc_unicode_count_to_utf8_size(ps,
				head_size, ss0, n, &actual_n),
		     tail_size = ss0 - cut_size - head_size;
	size_t out_size = ss0 - cut_size,
	       prefix_usize = 0;
	if (*s == src) { /* aliasing: copy-only */
		char *po = get_str(*s);
		memmove(po + head_size, ps + head_size + cut_size, tail_size);
	} else { /* copy/cat */
		const size_t at = (cat && *s) ? sd_get_size(*s) : 0;
		out_size += at;
		if (ss_reserve(s, out_size) >= out_size) {
			char *po = get_str(*s);
			memcpy(po + at, get_str_r(src), head_size);
			memcpy(po + at + head_size,
			       get_str_r(src) + head_size + cut_size,
			       tail_size);
			set_size(*s, out_size);
			if (is_unicode_size_cached(*s) &&
			    (at == 0 || at == sso0)) {
				prefix_usize = get_unicode_size(*s);
			} else {
				set_unicode_size_cached(*s, S_FALSE);
			}
		}
	}
	if (cus > actual_n)
		set_unicode_size(*s, prefix_usize + cus - actual_n);
	else /* BEHAVIOR: unicode char count invalidation */
		set_unicode_size_cached(*s, S_FALSE);
	set_size(*s, out_size);
	return ss_check(s);
}
Exemple #14
0
static ss_t *aux_ltrim(ss_t **s, const sbool_t cat, const ss_t *src)
{
	ASSERT_RETURN_IF(!s, ss_void);
	if (!src)
		src = ss_void;
	const size_t ss = sd_get_size(src);
	if (ss > 0) {
		const sbool_t aliasing = *s == src;
		const char *ps = get_str_r(src);
		size_t i = 0;
		for (; i < ss && isspace(ps[i]); i++);
		size_t at, cat_usize;
		if (cat) {
			if (*s) {
				at = sd_get_size(*s);
				cat_usize = get_unicode_size(*s);
			} else {
				at = cat_usize = 0;
			}
		} else {
			at = cat_usize = 0;
		}
		const size_t out_size = at + ss - i,
			     src_usize = get_unicode_size(src);
		if (ss_reserve(s, out_size) >= out_size) {
			char *pt = get_str(*s);
			if (!aliasing) /* copy or cat: shift data */
				memcpy(pt + at, ps + i, ss - i);
			else
				if (i > 0) /* copy: shift data */
					memmove(pt, ps + i, ss - i);
			set_size(*s, at + ss - i);
			set_unicode_size(*s, cat_usize + src_usize - i);
		}
	} else {
		if (cat)
			ss_check(s);
		else
			ss_clear(s);
	}
	return *s;
}
Exemple #15
0
static ss_t *aux_toint(ss_t **s, const sbool_t cat, const sint_t num)
{
	ASSERT_RETURN_IF(!s, ss_void);
	char btmp[128], *p = btmp + sizeof(btmp) - 1;
	sint_t n = num < 0 ? -num : num;
	do {
		*p-- = '0' + n % 10;
		n /= 10;
	} while (n);
	if (num < 0)
		*p-- = '-';
	const size_t off = (size_t)((p - (char *)btmp) + 1),
		     digits = sizeof(btmp) - off,
		     at = (cat && *s) ? sd_get_size(*s) : 0;
	SS_OVERFLOW_CHECK(s, at, digits);
	const size_t out_size = at + digits;
        if (ss_reserve(s, out_size) >= out_size) {
		memcpy(get_str(*s) + at, btmp + off, digits);
		set_size(*s, out_size);
		inc_unicode_size(*s, digits);
	}
	return *s;
}
Exemple #16
0
static size_t rgb2tga(ss_t **tga, const ss_t *rgb, const struct RGB_Info *ri)
{
	RETURN_IF(!rgb || (!valid_rgbi(ri) && (ri->bpp / ri->chn) != 8), 0);
	RETURN_IF(ri->chn != 1 && ri->chn != 3 && ri->chn != 4, 0);
	size_t buf_size = ri->bmp_size + TGA_RGBHDR;
	RETURN_IF(ss_reserve(tga, buf_size) < buf_size, 0);
	char *h = ss_get_buffer(*tga);
	memset(h, 0, TGA_RGBHDR);
	h[TGA_ID] = TGA_NO_X_INFO;
	h[TGA_CMAP] = TGA_NO_CMAP;
	h[TGA_TYPE] = ri->chn == 1 ? TGA_RAW_GRAY : TGA_RAW_RGB;
	S_ST_LE_U16(h + TGA_W, ri->width);
	S_ST_LE_U16(h + TGA_H, ri->height);
	h[TGA_BPP] = ri->bpp;
	h[TGA_DESC] = TGA_TOP_LEFT;
	ss_cpy_cn(tga, h, TGA_RGBHDR);
	if (ri->chn == 1)
		ss_cat(tga, rgb);
	else
		tga_rgb_swap(ri->bpp, ri->bmp_size, ss_get_buffer_r(rgb),
			     ss_get_buffer(*tga) + TGA_RGBHDR);
	ss_set_size(*tga, buf_size);
	return ss_size(*tga);
}
Exemple #17
0
static ss_t *aux_replace(ss_t **s, const sbool_t cat, const ss_t *src,
			 const size_t off, const ss_t *s1, const ss_t *s2)
{
	ASSERT_RETURN_IF(!s, ss_void);
	if (!s1)
		s1 = ss_void;
	if (!s2)
		s2 = ss_void;
	if (!src)
		src = ss_void;
	const size_t at = (cat && *s) ? sd_get_size(*s) : 0;
	const char *p0 = get_str_r(src),
		   *p2 = get_str_r(s2);
	const size_t l1 = sd_get_size(s1), l2 = sd_get_size(s2);
	size_t i = off, l = sd_get_size(src);
	ss_t *out = NULL;
	ssize_t size_delta = l2 > l1 ? (ssize_t)(l2 - l1) :
				       -(ssize_t)(l1 - l2);
	sbool_t aliasing = S_FALSE;
	size_t out_size = at + l;
	char *o, *o0;
	if (l2 >= l1) { /* resize required */
		size_t nfound = 0;
		/* scan required size */
		for (;; i+= l1, nfound++)
			if ((i = ss_find(src, i, s1)) == S_NPOS)
				break;
		if (nfound == 0)	/* 0 occurrences: return */
			return ss_check(s);
		if (size_delta >= 0)
			out_size += (size_t)size_delta * nfound;
		else
			out_size -= (size_t)(-size_delta) * nfound;
		/* allocate output string */
		out = ss_alloc(out_size);
		if (!out) {
			S_ERROR("not enough memory");
			sd_set_alloc_errors(*s);
			return ss_check(s);
		}
		o0 = o = get_str(out);
		/* copy prefix data (cat) */
		if (at > 0)
			memcpy(o, get_str_r(*s), at);
	} else {
		if (s && *s && *s == src) {
			aliasing = S_TRUE;
		} else {
			if (ss_reserve(s, out_size) < out_size) /* BEHAVIOR */
				return ss_check(s);
		}
		o0 = o = get_str(*s);
	}
	typedef void (*memcpy_t)(void *, const void *, size_t);
	memcpy_t f_cpy;
	if (aliasing) {
		f_cpy = (memcpy_t)memmove;
	} else {
		f_cpy = (memcpy_t)memcpy;
		o += at;
		if (off > 0)	/* copy not affected data */
			memcpy(o, p0, off);
	}
	o += off;
	size_t i_next = s1 == s2? S_NPOS : /* no replace */
			ss_find(src, i + off, s1);
	for (i = off;;) {
		/* before match copy: */
		if (i_next == S_NPOS) {
			f_cpy(o, p0 + i, l - i);
			o += (l - i);
			break;
		}
		f_cpy(o, p0 + i, i_next - i);
		o += (i_next - i);
		/* replace: */
		f_cpy(o, p2, l2);
		o += l2;
		i = i_next + l1;
		/* prepare next search: */
		i_next = ss_find(src, i, s1);
	}
	if (out) {
		ss_t *s_bck = *s;
		*s = out;
		ss_free(&s_bck);
	}
	set_size(*s, (size_t)(o - o0));
	return *s;
}