#ifndef ACL_VSTRING_INCLUDE_H
#define ACL_VSTRING_INCLUDE_H

#ifdef  __cplusplus
extern "C" {
#endif

#include "acl_define.h"
#include <stdarg.h>
#include "acl_vbuf.h"

/**
 * װ ACL_VBUFACL_VSTRING ṹͶ
 */
typedef struct ACL_VSTRING {
	ACL_VBUF vbuf;
	ssize_t  maxlen;
} ACL_VSTRING;

/**
 * ʼ ACL_VSTRING ṹָȱʡĻСûԼĺ
 * ڲ ACL_VSTRING str ʽǶ̬䷽ʽʹʱҪô˺гʼ,
 * ⣬ acl_vstring_free_buf ʽͷɸúڲ
 * @param vp {ACL_VSTRING*} ַΪ
 * @param len {size_t} ʼʱС
 */
ACL_API void acl_vstring_init(ACL_VSTRING *vp, size_t len);

/**
 *  acl_vstring_init ʼ ACL_VSTRING ʱҪô˺ͷŻڴ
 * @param vp {ACL_VSTRING*} ַΪ
 */
ACL_API void acl_vstring_free_buf(ACL_VSTRING *vp);

/**
 * ̬һ ACL_VSTRING ָڲĳʼС
 * @param len {size_t} ʼʱС
 * @return {ACL_VSTRING*} · ACL_VSTRING 
 */
ACL_API ACL_VSTRING *acl_vstring_alloc(size_t len);

/**
 * ̬һ ACL_VSTRING ָڲĳʼС
 * ͬʱָڴضŻڴ
 * @param slice {ACL_SLICE_POOL*} Ƭڴع
 * @param len {size_t} ʼʱС
 * @return {ACL_VSTRING*} · ACL_VSTRING 
 */
ACL_API ACL_VSTRING *acl_vstring_slice_alloc(ACL_SLICE_POOL *slice, size_t len);

/**
 * ̬һ ACL_VSTRING ָڲĳʼС
 * ͬʱָڴضŻڴ
 * @param len {size_t} ʼʱС
 * @return {ACL_VSTRING*} · ACL_VSTRING 
 */
ACL_API ACL_VSTRING *acl_vstring_dbuf_alloc(ACL_DBUF_POOL *dbuf, size_t len);

/**
 * ڴӳļʽڴʱô˺ ACL_VSTRING ̬
 * @param fd {ACL_FILE_HANDLE} Чļ
 * @param max_len {size_t} ӳڴС
 * @param init_len {size_t} ʼʱڴӳС
 * @return {ACL_VSTRING*} ´ ACL_VSTRING 
 */
ACL_API ACL_VSTRING *acl_vstring_mmap_alloc(ACL_FILE_HANDLE fd,
	size_t max_len, size_t init_len);

/**
 * ڴӳļʽڴʱô˺ ACL_VSTRING ̬
 * @param fd {ACL_FILE_HANDLE} Чļ
 * @param max_len {size_t} ӳڴС
 * @param init_len {size_t} ʼʱڴӳС
 * @param offset {ssize_t} ӳļеʼλ
 * @return {ACL_VSTRING*} ´ ACL_VSTRING 
 */
ACL_API ACL_VSTRING *acl_vstring_mmap_alloc2(ACL_FILE_HANDLE fd,
	size_t max_len, size_t init_len, size_t offset);

/**
 *  ACL_VSTRING , ĿǰúĹܻ
 * @param vp {ACL_VSTRING*}
 * @param ...  ACL_VSTRING_CTL_XXX ʾĿƲ־Ϊ
 *  ACL_VSTRING_CTL_END
 */
ACL_API void acl_vstring_ctl(ACL_VSTRING *vp,...);

#define ACL_VSTRING_CTL_MAXLEN      1
#define ACL_VSTRING_CTL_END         0

/**
 * ڵݽضָȣͬʱ֤ '\0' β
 * @param vp {ACL_VSTRING*}
 * @param len {size_t} ض̺ĳ
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_truncate(ACL_VSTRING *vp, size_t len);

/**
 * ͷ acl_vstring_alloc ̬ ACL_VSTRING 
 * @param vp {ACL_VSTRING*}
 */
ACL_API void acl_vstring_free(ACL_VSTRING *vp);

/**
 * ַ
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} Դַ
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_strcpy(ACL_VSTRING *vp, const char *src);

/**
 * ַó涨
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} Դַ
 * @param len {size_t} 涨
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_strncpy(ACL_VSTRING *vp,
		const char *src, size_t len);

/**
 * ӿַ
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} Դַ
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_strcat(ACL_VSTRING *vp, const char *src);

/**
 * ӿַó涨
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} Դַ
 * @param len {size_t} 涨
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_strncat(ACL_VSTRING *vp,
		const char *src, size_t len);

/**
 * ڴݣͬʱ֤Ŀ껺β '\0'
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} Դݵַ
 * @param len {size_t} Դݳ
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_memcpy(ACL_VSTRING *vp,
		const char *src, size_t len);

/**
 * ƶڴ, ԴĿַڴͬһڴҲԲ
 * ͬһڴú֤Ŀַβ '\0' β
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} Դݵַ
 * @param len {size_t} Դݳ
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_memmove(ACL_VSTRING *vp,
		const char *src, size_t len);

/**
 * ڴú֤Ŀ껺 '\0' β
 * @param vp {ACL_VSTRING*}
 * @param src {const char*} Դݵַ
 * @param len {size_t} Դݳ
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_memcat(ACL_VSTRING *vp,
		const char *src, size_t len);

/**
 * ĳַ
 * @param vp {ACL_VSTRING*}
 * @param ch {int} Ҫҵַ
 * @return {char*} Ŀַλõĵַ, δ鵽򷵻 NULL, 
 *  ע÷صַǲܱͷŵģΪ ACL_VSTRING ͳһй
 */
ACL_API char *acl_vstring_memchr(ACL_VSTRING *vp, int ch);

/**
 * ĳַַСд
 * @param vp {ACL_VSTRING*}
 * @param needle {const char*} Ҫҵַ
 * @return {char*} Ŀַλõĵַ, δ鵽򷵻 NULL, 
 *  ע÷صַǲܱͷŵģΪ ACL_VSTRING ͳһй
 */
ACL_API char *acl_vstring_strstr(ACL_VSTRING *vp, const char *needle);

/**
 * ĳַַСд
 * @param vp {ACL_VSTRING*}
 * @param needle {const char*} Ҫҵַ
 * @return {char*} Ŀַλõĵַ, δ鵽򷵻 NULL, 
 *  ע÷صַǲܱͷŵģΪ ACL_VSTRING ͳһй
 */
ACL_API char *acl_vstring_strcasestr(ACL_VSTRING *vp, const char *needle);

/**
 * ӺǰַַСд
 * @param vp {ACL_VSTRING*}
 * @param needle {const char*} Ҫҵַ
 * @return {char*} Ŀַλõĵַ, δ鵽򷵻 NULL, 
 *  ע÷صַǲܱͷŵģΪ ACL_VSTRING ͳһй
 */
ACL_API char *acl_vstring_rstrstr(ACL_VSTRING *vp, const char *needle);

/**
 * ӺǰַַСд
 * @param vp {ACL_VSTRING*}
 * @param needle {const char*} Ҫҵַ
 * @return {char*} Ŀַλõĵַ, δ鵽򷵻 NULL,
 *  ע÷صַǲܱͷŵģΪ ACL_VSTRING ͳһй
 */
ACL_API char *acl_vstring_rstrcasestr(ACL_VSTRING *vp, const char *needle);

/**
 * 򻺳ĳָλúݣͬʱ֤Ŀ껺 '\0' β
 * @param vp {ACL_VSTRING*}
 * @param start {size_t} ָλ
 * @param buf {const char*} ݵַ
 * @param len {size_t} ݳ
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_insert(ACL_VSTRING *vp, size_t start,
		const char *buf, size_t len);

/**
 * 򻺳ͷݣͬʱ֤Ŀ껺 '\0' β
 * @param vp {ACL_VSTRING*}
 * @param buf {const char*} ݵַ
 * @param len {size_t} ݳ
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_prepend(ACL_VSTRING *vp,
		const char *buf, size_t len);

/**
 * 򻺳ʽʽ
 * @param vp {ACL_VSTRING*}
 * @param format {const char*} ʽַ
 * @param ... 
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *ACL_PRINTF(2, 3) acl_vstring_sprintf(ACL_VSTRING *vp,
		const char *format,...);

/**
 * Ըӷʽ򻺳ʽʽ
 * @param vp {ACL_VSTRING*}
 * @param format {const char*} ʽַ
 * @param ... 
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *ACL_PRINTF(2, 3) acl_vstring_sprintf_append(
		ACL_VSTRING *vp, const char *format,...);

/**
 * ڵͬʱ ACL_VSTRING ͷţûҪ
 * acl_myfree ͷŷصڴ
 * @param vp {ACL_VSTRING*}
 * @return {char*} ֵַΪ NULL ʱûҪ
 *  acl_myfree ͷŸõַڴй©
 */
ACL_API char *acl_vstring_export(ACL_VSTRING *vp);

/**
 * ûĴ洢ַĶ̬ڴ벢µ ACL_VSTRING 
 * @param str {char*} ⲿ̬Ĵ洢ַڴַ
 * @return {ACL_VSTRING*} · ACL_VSTRING 
 */
ACL_API ACL_VSTRING *acl_vstring_import(char *str);

/**
 * ̬ڴ ACL_VSTRING ճ
 * עvp ǵ acl_vstring_alloc ģҲܵ acl_vstring_init
 *     йʼ, vp  acl_mymalloc λջϵһ
 *    : ACL_VSTRING v
 * @param vp {ACL_VSTRING*}  acl_mymalloc ɻһջ, 
 *  acl_mymalloc ʽɵʱӦͨ acl_myfree ͷ
 * @param buf {void*} ûݵڴ, ջ
 * @param len {size_t} buf ڴĳ
 */
ACL_API void acl_vstring_glue(ACL_VSTRING *vp, void *buf, size_t len);

/**
 * ȡĳλõַ
 * @param vp {ACL_VSTRING*}
 * @param len {size_t} λãֵԽ磬ڲ fatal
 * @return {char} ҵַ
 */
ACL_API char acl_vstring_charat(ACL_VSTRING *vp, size_t len);

/**
 * 涨ʽ
 * @param vp {ACL_VSTRING*}
 * @param format {const char*}
 * @param ap {va_list}
 * @return {ACL_VSTRING*}  vp ͬ
 * @see acl_vstring_sprintf
 */
ACL_API ACL_VSTRING *acl_vstring_vsprintf(ACL_VSTRING *vp,
		const char *format, va_list ap);

/**
 * 涨ʽβ
 * @param vp {ACL_VSTRING*}
 * @param format {const char*}
 * @param ap {va_list}
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *acl_vstring_vsprintf_append(ACL_VSTRING *vp,
		const char *format, va_list ap);

/**
 * 涨ʽͷ
 * @param vp {ACL_VSTRING*}
 * @param format {const char*}
 * @param ... 
 * @return {ACL_VSTRING*}  vp ͬ
 */
ACL_API ACL_VSTRING *ACL_PRINTF(2, 3) acl_vstring_sprintf_prepend(
		ACL_VSTRING *vp, const char *format, ...);

/**
 * Դлһ( "\r\n"  "\n")ͬʱʣݻ, 
 * δУֻԴ
 * @param vp {ACL_VSTRING*} ַݻ
 * @param src {const char**} Դַַָ, غַָƶһλ
 * @param dlen {size_t} Դַݳ
 * @return {const ACL_VSTRING*} NULL, ʾδҵ "\r\n"  "\n"Ὣʣ
 *  ݿڣӦҪͨ ACL_VSTRING_LEN жϻǷ
 *  ݣ!NULLʾ
 *  עкӦõ ACL_VSTRING_RESET(vp) 
 */
ACL_API const ACL_VSTRING *acl_buffer_gets_nonl(ACL_VSTRING *vp,
		const char **src, size_t dlen);

/**
 * Դлһ( "\r\n"  "\n")ͬʱʣݻ, 
 * δУֻԴ
 * @param vp {ACL_VSTRING*} ַݻ
 * @param src {const char**} Դַַָ, غַָƶһλ
 * @param dlen {size_t} Դַݳ
 * @return {const ACL_VSTRING*} NULL, ʾδҵ "\r\n"  "\n"Ὣʣ
 *  ݿڣӦҪͨ ACL_VSTRING_LEN жϻǷ
 *  ݣ!NULLʾ
 *  עкӦõ ACL_VSTRING_RESET(vp) 
 */
ACL_API const ACL_VSTRING *acl_buffer_gets(ACL_VSTRING *vp,
		const char **src, size_t dlen);

 /*
  * Macros. Unsafe macros have UPPERCASE names.
  */
#define ACL_VSTRING_SPACE(vp, len) ACL_VBUF_SPACE(&(vp)->vbuf, len)

/**
 * ȡõǰ ACL_VSTRING ݴ洢ַ
 * @param vp {ACL_VSTRING*}
 * @return {char*}
 */
#define acl_vstring_str(vp) ((char *) (vp)->vbuf.data)

/**
 * ȡõǰ ACL_VSTRING 洢ݵĳ
 * @param vp {ACL_VSTRING*}
 * @return {int}
 */
#define ACL_VSTRING_LEN(vp) (size_t) ((vp)->vbuf.ptr - (vp)->vbuf.data)

/**
 * ȡõǰ ACL_VSTRING ڲܴС
 * @param vp {ACL_VSTRING*}
 * @return {int}
 */
#define	ACL_VSTRING_SIZE(vp) ((vp)->vbuf.len)

/**
 * ȡõǰ ACL_VSTRING ƫָλ
 * @param vp {ACL_VSTRING*}
 * @return {char*}
 */
#define acl_vstring_end(vp) ((char *) (vp)->vbuf.ptr)

/**
 *  ACL_VSTRING ƫָλ 0
 * @param vp {ACL_VSTRING*}
 */
#define ACL_VSTRING_TERMINATE(vp) ACL_VBUF_TERM(&(vp)->vbuf)

/**
 *  ACL_VSTRING ڲַָʼλãὫβ 0Ӧÿ
 * ͨ ACL_VSTRING_TERMINATE β 0
 * @param vp {ACL_VSTRING*}
 */
#define ACL_VSTRING_RESET(vp) {	\
	(vp)->vbuf.ptr = (vp)->vbuf.data; \
	acl_vbuf_clearerr(&(vp)->vbuf); \
}

/**
 * һַ ACL_VSTRING 
 * @param vp {ACL_VSTRING*}
 * @param ch {int} ַ
 */
#define	ACL_VSTRING_ADDCH(vp, ch) ACL_VBUF_PUT(&(vp)->vbuf, ch)

/**
 * ƶƫָڲβ
 * @param vp {ACL_VSTRING*}
 */
#define ACL_VSTRING_SKIP(vp) { \
	while ((vp)->vbuf.ptr < (vp)->vbuf.data + (vp)->vbuf.len && *(vp)->vbuf.ptr) { \
		(vp)->vbuf.ptr++; \
	} \
}

/**
 * ǰ ACL_VSTRING лжݿ
 * @param vp {ACL_VSTRING*}
 */
#define acl_vstring_avail(vp) ((vp)->vbuf.len - ((vp)->vbuf.ptr - (vp)->vbuf.data))

 /**
  * The following macro is not part of the public interface, because it can
  * really screw up a buffer by positioning past allocated memory.
  */
#define ACL_VSTRING_AT_OFFSET(vp, offset) { \
	(vp)->vbuf.ptr = (vp)->vbuf.data + (offset); \
}

ACL_API int acl_vstring_space(ACL_VBUF *bp, ssize_t len);
ACL_API int acl_vstring_put_ready(ACL_VBUF *bp);

#ifdef  __cplusplus
}
#endif

#endif
