#ifndef	ACL_MYSTRING_INCLUDE_H
#define	ACL_MYSTRING_INCLUDE_H

#ifdef  __cplusplus
extern "C" {
#endif

#include "acl_define.h"

#include <string.h>

/**
 * : ȫַ꺯, Ա֤һֽΪ  "\0"
 * @param _dst {char*} Ŀڴָ
 * @param _src {const char*} Դַָ
 * @param _size {int} ĿڴĿռС
 */
#ifndef ACL_SAFE_STRNCPY
#define ACL_SAFE_STRNCPY(_dst, _src, _size) do {                              \
    if ((_size) > 0) {                                                        \
        size_t _n = strlen((_src));                                           \
        _n = _n > (size_t ) (_size) - 1? (size_t) (_size) - 1 : _n;           \
        memcpy(_dst, _src, _n);                                               \
        (_dst)[_n] = 0;                                                       \
    }                                                                         \
} while (0)
#endif

#ifndef ACL_SAFE_STRCPY
#define ACL_SAFE_STRCPY(_dst, _src) do {                                      \
	size_t _n = strlen((_src));                                           \
	_n = _n > sizeof((_dst)) - 1 ? sizeof((_dst)) -1 : _n;                \
	memcpy((_dst), (_src), _n);                                           \
	(_dst)[_n] = '\0';                                                    \
} while (0)
#endif

/**
 * ַתΪСдֱԭڴռв
 * @param s {char *} ַ
 * @return {char*} ɹַַ򷵻 NULL
 */
ACL_API char *acl_lowercase(char *s);

/**
 * ַǰ n ֽתΪСд
 * @param s {char *} ַ
 * @param n {int} תֽ
 * @return {char*} ɹַַ򷵻 NULL
 */
ACL_API char *acl_lowercase2(char *s, size_t n);

/**
 * ַתΪСд洢һڴ
 * @param s {const char*} Դַ
 * @param buf {char*} 洢תڴָ
 * @param size {size_t} buf ĿռС
 * @return {char*} ɹַַ򷵻 NULL
 */
ACL_API char *acl_lowercase3(const char *s, char *buf, size_t size);

/**
 * ַתΪдֱԭڴռв
 * @param s {char *} ַ
 * @return {char*} ɹַַ򷵻 NULL
 */
ACL_API char *acl_uppercase(char *s);

/**
 * ַתΪдֱԭڴռв, ת
 * @param s {char *} ַ
 * @param n {int} תֽ
 * @return {char*} ɹַַ򷵻 NULL
 */
ACL_API char *acl_uppercase2(char *s, size_t n);

/**
 * ַǰ n ֽתΪд
 * @param s {char *} ַ
 * @param buf {char*} 洢תڴ
 * @param size {size_t} buf ĿռС(ֽ)
 * @return {char*} ɹַַ򷵻 NULL
 */
ACL_API char *acl_uppercase3(const char *s, char *buf, size_t size);

/**
 * ַһַָзָ
 * @param src {char**} Ҫַָĵַָ룬Ƿǿָ룬
 *  ǿַʱú NULL
 * @param sep {const char*} ָǿַ
 * @return {char*} ǰַָָλãsrc ָһҪ
 *  ָʼλã
 *  1 NULL ʱʾָ̽ʱ src ָλñ '\0'
 *  2ط NULL ʱʱ src ַָǻǿַ
 *     ַָٴηָʱ϶ܷ NULL򣬵ٴηָʱ
 *     ط NULL ָ
 *  : Դַ"abcd=|efg=|hijk", ָ "=|"һηָ
 *  src ָ "efg"صĵַΪ "abcd"
 */
ACL_API char *acl_strtok(char **src, const char *sep);
#define acl_mystrtok	acl_strtok

/**
 * һ߼, ĳеβӷ "\\" ӣһкϲ,
 * ͬʱһַеԼתַس("\r\n" or "\n")ȥ
 * @param src {char**} Դַĵַָ
 * @return {char*} һ, ؿʾûпõ߼
 */
ACL_API char *acl_strline(char **src);
#define acl_mystrline	acl_strline

/**
 * ȥַе " ", "\t"
 * @param str {char*} Դַ
 * @return {char*} Դַͬĵַ
 */
ACL_API char *acl_strtrim(char *str);
#define acl_mystr_trim	acl_strtrim

/**
 * Դַȥַ
 * @param haystack {const char*} Դַ
 * @param needle {const char*} ҪԴַбȥַ
 * @param buf {char*} 洢ڴ濪ʼλ
 * @param bsize {int} buf ĿռС
 * @return {int}  buf еַ
 */
ACL_API int acl_strstrip(const char *haystack, const char *needle,
		char *buf, int bsize);
#define acl_mystr_strip	acl_strstrip

/**
 * ԴַҵһеĽλòȥسзԺַ
 * @param str {char*} Դַ
 * @return {int} 0 ʾɹ-1ʾʧ, ҲӦ÷תĳ!
 */
ACL_API int acl_strtrunc_byln(char *str);
#define acl_mystr_truncate_byln	acl_strtrunc_byln

/**
 * ӺǰȽַСд޶ȽϷΧ
 * @param s1 {const char*} ַַ
 * @param s2 {const char*} ַַ
 * @param n {size_t} ȽϷΧ
 * @return {int} ȽϽ. 0: , >0: һַڵڶַ,
 *  < 0: һַСڶַ
 */
ACL_API int acl_strrncasecmp(const char *s1, const char *s2, size_t n);

/**
 * ӺǰȽַ, Сд޶ȽϷΧ
 * @param s1 {const char*} ַַ
 * @param s2 {const char*} ַַ
 * @param n {size_t} ȽϷΧ
 * @return {int} ȽϽ. 0: , >0: һַڵڶַ,
 *  < 0: һַСڶַ
 */
ACL_API int acl_strrncmp(const char *s1, const char *s2, size_t n);

/**
 * ӺǰɨַСд
 * @param haystack {char *} Դַ
 * @param needle {const char *} ƥҵַ
 * @return {char *} != NULL: Ok, NULL: δ
 */
ACL_API char *acl_rstrstr(const char *haystack, const char *needle);

/**
 * ǰɨַСд
 * @param haystack {const char *} Դַ
 * @param needle {const char *} ƥҵַ
 * @return {char *} != NULL: Ok, NULL: δ
 */
ACL_API char *acl_strcasestr(const char *haystack, const char *needle);

/**
 * ӺǰɨַСд
 * @param haystack {char *} Դַ
 * @param needle {const char *} ƥҵַ
 * @return {char *} != NULL: Ok, NULL: δ
 */
ACL_API char *acl_rstrcasestr(const char *haystack, const char *needle);

/**
 * ַĳȣ㳤ȣԽҪ strlen
 * ȫ磬ַû "\0" βúͲԽ
 * @param s {const char*} ַ
 * @param count {size_t} 㳤
 * @return {size_t} ַ s ʵʳ
 */
ACL_API size_t acl_strnlen(const char * s, size_t count);

/**
 * ȽַǷͬСд
 * @param s1 {const char*}
 * @param s2 {cosnt char*}
 * @return {int} 0: ͬ; < 0: s1 < s2; > 0: s1 > s2
 */
ACL_API int acl_strcasecmp(const char *s1, const char *s2);

/**
 * ȽַǷͬСдУͬʱ޶Ƚϳ
 * @param s1 {const char*}
 * @param s2 {cosnt char*}
 * @param n {size_t} ޶Ƚϵ󳤶
 * @return {int} 0: ͬ; < 0: s1 < s2; > 0: s1 > s2
 */
ACL_API int acl_strncasecmp(const char *s1, const char *s2, size_t n);
/**
 * WINDOWS²֧һЩַȽϺ
 */
#if defined(_WIN32) || defined(_WIN64)
# ifndef strcasestr
#  define strcasestr	acl_strcasestr
# endif
# ifndef strcasecmp
#  define strcasecmp	acl_strcasecmp
# endif
# ifndef strncasecmp
#  define strncasecmp	acl_strncasecmp
# endif
#endif

#ifndef strrncasecmp
# define strrncasecmp	acl_strrncasecmp
#endif
#ifndef strrncmp
# define strrncmp	acl_strrncmp
#endif

/*----------------------------------------------------------------------------
 * ֤ʽ:
 * /home/avwall/test.txt
 * @param psrc_file_path {const char*} Դַ
 * @param pbuf {char*} 洢ڴ
 * @param sizeb {int} pbuf ĿռС
 * @return {int} 0 ɹ-1ʧ
 */
ACL_API int acl_file_path_correct(const char *psrc_file_path,
		char *pbuf, int sizeb);

/*----------------------------------------------------------------------------
 * ֤·˺Ϊ¸ʽ:
 * Դ:   /home/avwall/, /home//////avwall/, /home/avwall, /////home/avwall///
 *       /home/avwall////, /home///avwall///, ///home///avwall///
 * : /home/avwall/
 * @param psrc_dir {const char*} Դַ
 * @param pbuf {char*} 洢ڴ
 * @param sizeb {int} pbuf ĿռС
 * @return {int} 0 ʾɹ-1ʾʧ
 */
ACL_API int acl_dir_correct(const char *psrc_dir, char *pbuf, int sizeb);

/*----------------------------------------------------------------------------
 * : /home/avwall/log.txt ȡ /home/avwall/ Ϊ
 * @param pathname {const char*} Դַ
 * @param pbuf {char*} 洢ڴ
 * @param bsize {int} pbuf ĿռС
 * @return {int} 0 ɹ-1ʧ
 */
ACL_API int acl_dir_getpath(const char *pathname, char *pbuf, int bsize);

/**
 * ַתΪתʧʱʹôֵΪֵ߽жϣ¼
 * ڲʹ strtol/strtoll ṩ˸Ϊȫַתķַ
 * ʽתʧʱͨصõȱʡֵתʧ
 */
/**
 * ַתΪ32λ
 * @param s {const char*} ַָ
 * @param def {int} תʧʱصֵ
 * @return {int}
 */
ACL_API int acl_safe_atoi(const char *s, int def);

/**
 * ַתΪlong
 * @param s {const char*} ַָ
 * @param def {long} תʧʱصֵ
 * @return {long}
 */
ACL_API long acl_safe_atol(const char *s, long def);

/**
 * ַתΪ64λ
 * @param s {const char*} ַָ
 * @param def {long long} תʧʱصֵ
 * @return {long long}
 */
ACL_API long long acl_safe_atoll(const char *s, long long def);

/**
 * ַתΪ64λзų
 * @param s {const char*} ַָ
 * @return {long long} зų
 */
ACL_API long long acl_atoll(const char *s);

/**
 * ַתΪ64λ޷ų
 * @param str {const char*} ַָ
 * @return {acl_uint64} ޷ų
 */
ACL_API acl_uint64 acl_atoui64(const char *str);

/**
* ַתΪ64λų
* @param str {const char*} ַָ
* @return {acl_int64} ޷ų
*/
ACL_API acl_int64 acl_atoi64(const char *str);

/**
 * 64λ޷ųתΪַ
 * @param value {acl_uint64} 64λ޷ų
 * @param buf {char*} ȡתڴռ
 * @param size {sizt_t} buf ĿռСҪСΪ21ֽ
 * @return {const char*} תĽתɹΪգΪ
 */
ACL_API const char *acl_ui64toa(acl_uint64 value, char *buf, size_t size);

/**
 * 64λųתΪַ
 * @param value {acl_int64} 64λų
 * @param buf {char*} ȡתڴռ
 * @param size {sizt_t} buf ĿռСҪСΪ21ֽ
 * @return {const char*} תĽתɹΪգΪ
 */
ACL_API const char *acl_i64toa(acl_int64 value, char *buf, size_t size);

/**
 * 64λųתΪĳƵַ
 * @param value {acl_int64} 64λų
 * @param buf {char*} ȡתڴռ
 * @param size {sizt_t} buf ĿռСҪСΪ21ֽ
 * @param radix {int} , : 8 ʾ˽, 10 ʾʮ, 16 ʾʮ
 * @return {const char*} תĽתɹΪգΪ
 */
ACL_API const char *acl_i64toa_radix(acl_int64 value, char *buf,
		size_t size, int radix);

/**
 * 64λ޷ųתΪĳƵַ
 * @param value {acl_int64} 64λų
 * @param buf {char*} ȡתڴռ
 * @param size {sizt_t} buf ĿռСҪСΪ21ֽ
 * @param radix {int} , : 8 ʾ˽, 10 ʾʮ, 16 ʾʮ
 * @return {const char*} תĽתɹΪգΪ
 */
ACL_API const char *acl_ui64toa_radix(acl_uint64 value, char *buf,
		size_t size, int radix);

/*--------------------------------------------------------------------------*/

typedef struct ACL_LINE_STATE {
	int   offset;		/* ĵǰƫ */
	char  finish;		/* Ƿɹҵһ */
	char  last_ch;		/* ŵһַ */
	char  last_lf;		/* һַǷΪз LF */
} ACL_LINE_STATE;

/**
 * һ ACL_LINE_STATE  acl_find_blank_line Ĳ
 * @return {ACL_LINE_STATE*} Զطǿָ
 */
ACL_API ACL_LINE_STATE *acl_line_state_alloc(void);

/**
 * ͷ acl_line_state_alloc  ACL_LINE_STATE 
 * @param state {ACL_LINE_STATE*} ǿ ACL_LINE_STATE 
 */
ACL_API void acl_line_state_free(ACL_LINE_STATE *state);

/**
 *  ACL_LINE_STATE ״̬
 * @param state {ACL_LINE_STATE*}  acl_line_state_alloc ̬Ķ
 *  ջֱӵ malloc ڴطĶ󣬵ֻ acl_line_state_alloc
 *  Ķſʹ acl_line_state_free ͷ
 * @param offset {int}  ACL_LINE_STATE  offset ĳʼֵ
 * @return {ACL_LINE_STATE*}  state ָ
 */
ACL_API ACL_LINE_STATE *acl_line_state_reset(ACL_LINE_STATE *state, int offset);

/**
 * ݻвһ(пΪ: \r\n  \n)ú֧ʽ
 * ѭñ
 * @param s {const char*} ݻַ
 * @param n {int} s ݻĳ
 * @param state {ACL_LINE_STATE*}  acl_line_state_alloc Ķ
 * @return {int} ʣĵֽ
 */
ACL_API int acl_find_blank_line(const char *s, int n, ACL_LINE_STATE *state);

/*--------------------------------------------------------------------------*/

#ifdef  __cplusplus
}
#endif

#endif
