str.c revision b09be485e9373be4288f5615bbce6ebed65a425a
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2003 Timo Sirainen */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "buffer.h"
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen#include "printf-format-fix.h"
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include "str.h"
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include <stdio.h>
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainenstring_t *str_new(pool_t pool, size_t initial_size)
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainen{
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen return buffer_create_dynamic(pool, initial_size);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen}
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenstring_t *t_str_new(size_t initial_size)
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen{
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen return str_new(pool_datastack_create(), initial_size);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen}
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenvoid str_free(string_t **str)
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen{
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen buffer_free(*str);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen}
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenstatic void str_add_nul(string_t *str)
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen{
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen size_t len;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen len = str_len(str);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen buffer_write(str, len, "", 1);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen /* remove the \0 - we don't want to keep it */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen buffer_set_used_size(str, len);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen}
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenchar *str_free_without_data(string_t **str)
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen{
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen str_add_nul(*str);
d6684856fb99e51bc22a6346e08b2d81c996f963Josef 'Jeff' Sipek return buffer_free_without_data(*str);
d6684856fb99e51bc22a6346e08b2d81c996f963Josef 'Jeff' Sipek}
d6684856fb99e51bc22a6346e08b2d81c996f963Josef 'Jeff' Sipek
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenconst char *str_c(string_t *str)
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen{
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen str_add_nul(str);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen return buffer_get_data(str, NULL);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenconst unsigned char *str_data(const string_t *str)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return buffer_get_data(str, NULL);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipekchar *str_c_modifiable(string_t *str)
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek{
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek str_add_nul(str);
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek return buffer_get_modifiable_data(str, NULL);
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek}
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainensize_t str_len(const string_t *str)
30517c760897cc4f249da1830ae1996f4d7b5aeaTimo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return buffer_get_used_size(str);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen
204ee6ed414f5e4eeb6f6c10763b55daf56f11acJosef 'Jeff' Sipekvoid str_append(string_t *str, const char *cstr)
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen{
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen buffer_append(str, cstr, strlen(cstr));
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvoid str_append_n(string_t *str, const void *cstr, size_t max_len)
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen{
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen size_t len;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen len = 0;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen while (len < max_len && ((const char *)cstr)[len] != '\0')
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen len++;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen buffer_append(str, cstr, len);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen}
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainenvoid str_append_c(string_t *str, unsigned char chr)
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen{
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen buffer_append_c(str, chr);
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen}
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid str_append_str(string_t *dest, const string_t *src)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen const char *cstr;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t len;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen cstr = buffer_get_data(src, &len);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen buffer_append(dest, cstr, len);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen}
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenvoid str_printfa(string_t *str, const char *fmt, ...)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen{
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen va_list args;
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen va_start(args, fmt);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen str_vprintfa(str, fmt, args);
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen va_end(args);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen}
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenvoid str_vprintfa(string_t *str, const char *fmt, va_list args)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen{
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen#define SNPRINTF_INITIAL_EXTRA_SIZE 256
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen va_list args2;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen char *tmp;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen unsigned int init_size;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen size_t pos = str->used;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen int ret, ret2;
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen VA_COPY(args2, args);
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen /* the format string is modified only if %m exists in it. it happens
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen only in error conditions, so don't try to t_push() here since it'll
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen just slow down the normal code path. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fmt = printf_format_fix_get_len(fmt, &init_size);
660ecbaf80e6b3cf3a70ed1e0cdf7f8af6d895d0Josef 'Jeff' Sipek init_size += SNPRINTF_INITIAL_EXTRA_SIZE;
660ecbaf80e6b3cf3a70ed1e0cdf7f8af6d895d0Josef 'Jeff' Sipek
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* @UNSAFE */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tmp = buffer_get_space_unsafe(str, pos, init_size);
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen ret = vsnprintf(tmp, init_size, fmt, args);
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen i_assert(ret >= 0);
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen if ((unsigned int)ret >= init_size) {
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen /* didn't fit with the first guess. now we know the size,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen so try again. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tmp = buffer_get_space_unsafe(str, pos, ret + 1);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen ret2 = vsnprintf(tmp, ret + 1, fmt, args2);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(ret2 == ret);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen /* drop the unused data, including terminating NUL */
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen buffer_set_used_size(str, pos + ret);
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen}
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainenvoid str_insert(string_t *str, size_t pos, const char *cstr)
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen{
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen buffer_insert(str, pos, cstr, strlen(cstr));
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen}
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainenvoid str_delete(string_t *str, size_t pos, size_t len)
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen{
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen buffer_delete(str, pos, len);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen}
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenvoid str_truncate(string_t *str, size_t len)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen{
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen buffer_set_used_size(str, len);
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen}
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen