From 2a045b7ff05615f28579e46fc2c9e870d75ebb00 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 6 Apr 2010 06:50:01 +0000 Subject: [PATCH] enhanced lda with binary heap functions added more wide character handling functions --- qse/include/qse/cmn/chr.h | 40 ++-- qse/include/qse/cmn/lda.h | 207 ++++++++---------- qse/include/qse/cmn/str.h | 414 ++++++++++++++++++++---------------- qse/include/qse/macros.h | 43 +++- qse/lib/awk/parse.c | 44 ++-- qse/lib/awk/run.c | 12 +- qse/lib/cmn/chr_cnv.c | 9 +- qse/lib/cmn/fio.c | 8 +- qse/lib/cmn/lda.c | 132 +++++++++++- qse/lib/cmn/main.c | 71 +++---- qse/lib/cmn/str_bas.c | 16 +- qse/lib/cmn/str_cnv.c | 111 ++++++++-- qse/regress/awk/passwd.dat | 38 ++++ qse/regress/awk/regress.out | 6 +- qse/regress/awk/regress.sh | 2 +- qse/samples/cmn/Makefile.am | 3 +- qse/samples/cmn/Makefile.in | 19 +- qse/samples/cmn/chr.c | 4 +- qse/samples/cmn/fio.c | 10 +- qse/samples/cmn/lda.c | 93 +++++++- qse/samples/cmn/main.c | 20 ++ qse/samples/cmn/str.c | 2 +- 22 files changed, 846 insertions(+), 458 deletions(-) create mode 100644 qse/regress/awk/passwd.dat create mode 100644 qse/samples/cmn/main.c diff --git a/qse/include/qse/cmn/chr.h b/qse/include/qse/cmn/chr.h index 1145330a..b0af70d9 100644 --- a/qse/include/qse/cmn/chr.h +++ b/qse/include/qse/cmn/chr.h @@ -1,5 +1,5 @@ /* - * $Id: chr.h 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: chr.h 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -110,42 +110,42 @@ qse_cint_t qse_ccls_to ( qse_ccls_id_t type ); +/** + * The qse_mblen() function scans a multibyte sequence to get the number of + * bytes needed to form a wide character. It does not scan more than @a mblen + * bytes. + * @return number of bytes processed on success, + * 0 for invalid sequences, + * mblen + 1 for incomplete sequences + */ qse_size_t qse_mblen ( const qse_mchar_t* mb, - qse_size_t mblen + qse_size_t mblen ); -/****f* Common/qse_mbtowc - * NAME - * qse_mbtowc - convert a multibyte sequence to a wide character. - * RETURN - * The qse_mbtowc() function returns 0 if an invalid multibyte sequence is - * detected, mblen + 1 if the sequence is incomplete. It returns the number - * of bytes processed to form a wide character. - * SYNOPSIS +/** + * The qse_mbtowc() function converts a multibyte sequence to a wide character. + * It returns 0 if an invalid multibyte sequence is detected, mblen + 1 if the + * sequence is incomplete. It returns the number of bytes processed to form a + * wide character. */ qse_size_t qse_mbtowc ( const qse_mchar_t* mb, qse_size_t mblen, qse_wchar_t* wc ); -/******/ -/****f* Common/qse_wctomb - * NAME - * qse_wctomb - convert a wide character to a multibyte sequence - * RETURN - * The qse_wctomb() functions returns 0 if the wide character is illegal, - * mblen + 1 if mblen is not large enough to hold the multibyte sequence. - * On successful conversion, it returns the number of bytes in the sequence. - * SYNOPSIS +/** + * The qse_wctomb() function converts a wide character to a multibyte sequence. + * It returns 0 if the wide character is illegal, mblen + 1 if mblen is not + * large enough to hold the multibyte sequence. On successful conversion, it + * returns the number of bytes in the sequence. */ qse_size_t qse_wctomb ( qse_wchar_t wc, qse_mchar_t* mb, qse_size_t mblen ); -/******/ #ifdef __cplusplus } diff --git a/qse/include/qse/cmn/lda.h b/qse/include/qse/cmn/lda.h index e41c260e..6a635acd 100644 --- a/qse/include/qse/cmn/lda.h +++ b/qse/include/qse/cmn/lda.h @@ -1,5 +1,5 @@ /* - * $Id: lda.h 311 2009-12-09 11:35:54Z hyunghwan.chung $ + * $Id: lda.h 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -24,13 +24,9 @@ #include #include -/****o* Common/linear dynamic array - * DESCRIPTION - * provides a linear dynamic array. It grows as more items - * are added. - * - * #include - ****** +/** @file + * This file provides a linear dynamic array. It grows dynamically as items + * are added. */ enum qse_lda_walk_t @@ -62,14 +58,8 @@ typedef enum qse_lda_walk_t qse_lda_walk_t; #define QSE_LDA_KEEPER(lda) ((lda)->keeper) #define QSE_LDA_SIZER(lda) ((lda)->sizer) - - -/****t* Common/qse_lda_copier_t - * NAME - * qse_lda_copier_t - define a node contruction callback - * - * DESCRIPTION - * The qse_lda_copier_t defines a callback function for node construction. +/** + * The qse_lda_copier_t type defines a callback function for node construction. * A node is contructed when a user adds data to a list. The user can * define how the data to add can be maintained in the list. A singly * linked list not specified with any copiers stores the data pointer and @@ -80,44 +70,30 @@ typedef enum qse_lda_walk_t qse_lda_walk_t; * A copier should return the pointer to the copied data. If it fails to copy * data, it may return QSE_NULL. You need to set a proper freeer to free up * memory allocated for copy. - * - * SEE ALSO - * qse_lda_setcopier, qse_lda_getcopier, QSE_LDA_COPIER - * - * SYNOPSIS */ typedef void* (*qse_lda_copier_t) ( qse_lda_t* lda /* lda */, void* dptr /* the pointer to data to copy */, qse_size_t dlen /* the length of data to copy */ ); -/******/ -/****t* Common/qse_lda_freeer_t - * NAME - * qse_lda_freeer_t - define a node destruction callback - * SYNOPSIS +/** + * The qse_lda_freeer_t type defines a node destruction callback. */ typedef void (*qse_lda_freeer_t) ( qse_lda_t* lda /* lda */, void* dptr /* the pointer to data to free */, qse_size_t dlen /* the length of data to free */ ); -/******/ -/****t* Common/qse_lda_comper_t - * NAME - * qse_lda_comper_t - define a data comparator +/** + * The qse_lda_comper_t type defines a key comparator that is called when + * the list needs to compare data. A linear dynamic array is created with a + * default comparator that performs bitwise comparison. * - * DESCRIPTION - * The qse_lda_comper_t type defines a key comparator that is called when - * the list needs to compare data. A linear dynamic array is created with a - * default comparator that performs bitwise comparison. + * The comparator should return 0 if the data are the same and a non-zero + * integer otherwise. * - * The comparator should return 0 if the data are the same and a non-zero - * integer otherwise. - * - * SYNOPSIS */ typedef int (*qse_lda_comper_t) ( qse_lda_t* lda /* a linear dynamic array */, @@ -126,42 +102,27 @@ typedef int (*qse_lda_comper_t) ( const void* dptr2 /* a data pointer */, qse_size_t dlen2 /* a data length */ ); -/******/ -/****t* Common/qse_lda_keeper_t - * NAME - * qse_lda_keeper_t - define a value keeper - * - * DESCRIPTION - * The qse_lda_keeper_t type defines a value keeper that is called when - * a value is retained in the context that it should be destroyed because - * it is identical to a new value. Two values are identical if their beginning - * pointers and their lengths are equal. - * - * SYNOPSIS +/** + * The qse_lda_keeper_t type defines a value keeper that is called when + * a value is retained in the context that it should be destroyed because + * it is identical to a new value. Two values are identical if their beginning + * pointers and their lengths are equal. */ typedef void (*qse_lda_keeper_t) ( qse_lda_t* lda /* lda */, void* vptr /* the pointer to a value */, qse_size_t vlen /* the length of a value */ ); -/******/ -/****t* Common/qse_lda_sizer_t - * NAME - * qse_lda_sizer_t - define an array size calculator - * - * DESCRIPTION - * The qse_lda_sizer_t type defines an array size claculator that is called - * when the array needs to be resized. - * - * SYNOPSIS +/** + * The qse_lda_sizer_t type defines an array size claculator that is called + * when the array needs to be resized. */ typedef qse_size_t (*qse_lda_sizer_t) ( qse_lda_t* lda, /* a linear dynamic array */ qse_size_t hint /* a sizing hint */ ); -/******/ typedef qse_lda_walk_t (*qse_lda_walker_t) ( qse_lda_t* lda /* a linear dynamic array */, @@ -169,11 +130,8 @@ typedef qse_lda_walk_t (*qse_lda_walker_t) ( void* arg /* user-defined data */ ); -/****s* Common/qse_lda_t - * NAME - * qse_lda_t - define a linear dynamic array - * - * SYNOPSIS +/** + * The qse_lda_t type defines a linear dynamic array. */ struct qse_lda_t { @@ -185,24 +143,19 @@ struct qse_lda_t qse_lda_keeper_t keeper; /* data keeper */ qse_lda_sizer_t sizer; /* size calculator */ qse_byte_t scale; /* scale factor */ - qse_size_t size; /* the number of items */ + qse_size_t size; /* number of items */ qse_size_t capa; /* capacity */ qse_lda_node_t** node; }; -/******/ -/****s* - * NAME - * qse_lda_node_t - define a linear dynamic array node - * - * SYNOPSIS +/** + * The qse_lda_node_t type defines a linear dynamic array node */ struct qse_lda_node_t { void* dptr; qse_size_t dlen; }; -/******/ #ifdef __cplusplus extern "C" { @@ -210,53 +163,37 @@ extern "C" { QSE_DEFINE_COMMON_FUNCTIONS (lda) -/****f* Common/qse_lda_open - * NAME - * qse_lda_open - create a linear dynamic array - * - * SYNOPSIS +/** + * The qse_lda_open() function creates a linear dynamic array. */ qse_lda_t* qse_lda_open ( qse_mmgr_t* lda, qse_size_t ext, qse_size_t capa ); -/******/ -/****f* Common/qse_lda_close - * NAME - * qse_lda_close - destroy a linear dynamic array - * - * SYNOPSIS +/** + * The qse_lda_close() function destroys a linear dynamic array. */ void qse_lda_close ( qse_lda_t* lda ); -/******/ -/****f* Common/qse_lda_init - * NAME - * qse_lda_init - initialize a linear dynamic array - * - * SYNOPSIS +/** + * The qse_lda_init() function initializes a linear dynamic array. */ qse_lda_t* qse_lda_init ( qse_lda_t* lda, qse_mmgr_t* mmgr, qse_size_t capa ); -/******/ -/****f* Common/qse_lda_fini - * NAME - * qse_lda_fini - deinitialize a linear dynamic array - * - * SYNOPSIS +/** + * The qse_lda_fini() function finalizes a linear dynamic array. */ void qse_lda_fini ( qse_lda_t* lda ); -/******/ int qse_lda_getscale ( qse_lda_t* lda /* lda */ @@ -383,43 +320,25 @@ qse_size_t qse_lda_update ( qse_size_t dlen ); -/****f* Common/qse_lda_delete - * NAME - * qse_lda_delete - delete data - * - * DESCRIPTION - * The qse_lda_delete() function deletes the as many data as the count - * from the index. - * - * RETURN - * The qse_lda_delete() function returns the number of data deleted. - * - * SYNOPSIS +/** + * The qse_lda_delete() function deletes the as many data as the count + * from the index. It returns the number of data deleted. */ qse_size_t qse_lda_delete ( qse_lda_t* lda, qse_size_t index, qse_size_t count ); -/******/ -/****f* Common/qse_lda_uplete - * NAME - * qse_lda_uplete - delete data node - * - * DESCRIPTION +/** * The qse_lda_uplete() function deletes data node without compaction. - * - * RETURN - * The qse_lda_uplete() function returns the number of data affected. - * + * It returns the number of data affected. */ qse_size_t qse_lda_uplete ( qse_lda_t* lda, qse_size_t index, qse_size_t count ); -/******/ void qse_lda_clear ( qse_lda_t* lda @@ -437,6 +356,52 @@ void qse_lda_rwalk ( void* arg ); +/** + * The qse_lda_pushstack() function appends data to the array. It is a utility + * function to allow stack-like operations over an array. To do so, you should + * not play with other non-stack related functions. + */ +qse_size_t qse_lda_pushstack ( + qse_lda_t* lda, + void* dptr, + qse_size_t dlen +); + +/** + * The qse_lda_popstack() function deletes the last array data. It is a utility + * function to allow stack-like operations over an array. To do so, you should + * not play with other non-stack related functions. + * @note You must not call this function if @a lda is empty. + */ +void qse_lda_popstack ( + qse_lda_t* lda +); + +/** + * The qse_lda_pushheap() function inserts data to an array while keeping the + * largest data at position 0. It is a utiltiy funtion to implement a binary + * max-heap over an array. Inverse the comparator to implement a min-heap. + * @return number of array elements + * @note You must not mess up the array with other non-heap related functions + * to keep the heap property. + */ +qse_size_t qse_lda_pushheap ( + qse_lda_t* lda, + void* dptr, + qse_size_t dlen +); + +/** + * The qse_lda_popheap() function deletes data at position 0 while keeping + * the largest data at positon 0. It is a utiltiy funtion to implement a binary + * max-heap over an array. + * @note You must not mess up the array with other non-heap related functions + * to keep the heap property. + */ +void qse_lda_popheap ( + qse_lda_t* lda +); + #ifdef __cplusplus } #endif diff --git a/qse/include/qse/cmn/str.h b/qse/include/qse/cmn/str.h index 4ec5716e..ef286fb6 100644 --- a/qse/include/qse/cmn/str.h +++ b/qse/include/qse/cmn/str.h @@ -1,5 +1,5 @@ /* - * $Id: str.h 320 2009-12-21 12:29:52Z hyunghwan.chung $ + * $Id: str.h 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -120,31 +120,29 @@ extern "C" { * basic string functions */ -/****f* Common/qse_strlen - * NAME - * qse_strlen - get the number of characters - * DESCRIPTION - * The qse_strlen() function returns the number of characters in a - * null-terminated string. The length returned excludes a terminating null. - * SYNOPSIS +/** + * The qse_strlen() function returns the number of characters in a + * null-terminated string. The length returned excludes a terminating null. */ qse_size_t qse_strlen ( const qse_char_t* str ); -/******/ -/****f* Common/qse_strbytes - * NAME - * qse_strbytes - get the length of a string in bytes - * DESCRIPTOIN - * The qse_strbytes() function returns the number of bytes a null-terminated - * string is holding excluding a terminating null. - * SYNOPSIS +/** + * The qse_strbytes() function returns the number of bytes a null-terminated + * string is holding excluding a terminating null. */ qse_size_t qse_strbytes ( const qse_char_t* str ); -/******/ + +qse_size_t qse_mbslen ( + const qse_mchar_t* mbs +); + +qse_size_t qse_wcslen ( + const qse_wchar_t* wcs +); qse_size_t qse_strcpy ( qse_char_t* buf, @@ -170,36 +168,32 @@ qse_size_t qse_strxncpy ( qse_size_t len ); -/****f* Common/qse_strfcpy - * NAME - * qse_strfcpy - copy a string - * DESCRIPTION - * "format ${1} ${3} ${2} \\${1} string" - * SYNOPSIS +/** + * The qse_strfcpy() function formats a string by position. + * The position specifier is a number enclosed in ${ and }. + * When ${ is preceeded by a backslash, it is treated literally. + * A sameple format string containing the position specifiers are shown below: + * @code + * "${1} ${3} ${2} \\${1} string" + * @endcode */ qse_size_t qse_strfcpy ( qse_char_t* buf, const qse_char_t* fmt, const qse_char_t* str[] ); -/******/ -/****f* Common/qse_strfncpy - * NAME - * qse_strfncpy - copy a string - * SYNOPSIS +/** + * The qse_strfncpy() function formats a string by position. */ qse_size_t qse_strfncpy ( qse_char_t* buf, const qse_char_t* fmt, const qse_cstr_t str[] ); -/******/ -/****f* Common/qse_strxfcpy - * NAME - * qse_strxfcpy - copy a string - * SYNOPSIS +/** + * The qse_strxfcpy() function formats a string by position. */ qse_size_t qse_strxfcpy ( qse_char_t* buf, @@ -207,12 +201,9 @@ qse_size_t qse_strxfcpy ( const qse_char_t* fmt, const qse_char_t* str[] ); -/******/ -/****f* Common/qse_strxfncpy - * NAME - * qse_strxfncpy - copy a string - * SYNOPSIS +/** + * The qse_strxfncpy() function formats a string by position. */ qse_size_t qse_strxfncpy ( qse_char_t* buf, @@ -220,7 +211,6 @@ qse_size_t qse_strxfncpy ( const qse_char_t* fmt, const qse_cstr_t str[] ); -/******/ qse_size_t qse_strxcat ( qse_char_t* buf, @@ -235,11 +225,23 @@ qse_size_t qse_strxncat ( qse_size_t len ); -int qse_strcmp (const qse_char_t* s1, const qse_char_t* s2); -int qse_strxcmp (const qse_char_t* s1, qse_size_t len1, const qse_char_t* s2); +int qse_strcmp ( + const qse_char_t* s1, + const qse_char_t* s2 +); + +int qse_strxcmp ( + const qse_char_t* s1, + qse_size_t len1, + const qse_char_t* s2 +); + int qse_strxncmp ( - const qse_char_t* s1, qse_size_t len1, - const qse_char_t* s2, qse_size_t len2); + const qse_char_t* s1, + qse_size_t len1, + const qse_char_t* s2, + qse_size_t len2 +); int qse_strcasecmp (const qse_char_t* s1, const qse_char_t* s2); @@ -361,20 +363,56 @@ qse_char_t* qse_strxnrstr ( qse_size_t subsz ); -qse_char_t* qse_strchr (const qse_char_t* str, qse_cint_t c); -qse_char_t* qse_strxchr (const qse_char_t* str, qse_size_t len, qse_cint_t c); -qse_char_t* qse_strrchr (const qse_char_t* str, qse_cint_t c); -qse_char_t* qse_strxrchr (const qse_char_t* str, qse_size_t len, qse_cint_t c); +qse_char_t* qse_strchr ( + const qse_char_t* str, + qse_cint_t c +); + +qse_char_t* qse_strxchr ( + const qse_char_t* str, + qse_size_t len, + qse_cint_t c +); + +qse_char_t* qse_strrchr ( + const qse_char_t* str, + qse_cint_t c +); + +qse_char_t* qse_strxrchr ( + const qse_char_t* str, + qse_size_t len, + qse_cint_t c +); + +/** + * The qse_strbeg() function checks if the a string begins with a substring. + * @return the pointer to a beginning of a matching beginning, + * QSE_NULL if no match is found. + */ +qse_char_t* qse_strbeg ( + const qse_char_t* str, + const qse_char_t* sub +); -/* Checks if a string begins with a substring */ -qse_char_t* qse_strbeg (const qse_char_t* str, const qse_char_t* sub); qse_char_t* qse_strxbeg ( - const qse_char_t* str, qse_size_t len, const qse_char_t* sub); + const qse_char_t* str, + qse_size_t len, + const qse_char_t* sub) +; + qse_char_t* qse_strnbeg ( - const qse_char_t* str, const qse_char_t* sub, qse_size_t len); + const qse_char_t* str, + const qse_char_t* sub, + qse_size_t len +); + qse_char_t* qse_strxnbeg ( - const qse_char_t* str, qse_size_t len1, - const qse_char_t* sub, qse_size_t len2); + const qse_char_t* str, + qse_size_t len1, + const qse_char_t* sub, + qse_size_t len2 +); /** * The qse_strend() function checks if the a string ends with a substring. @@ -443,12 +481,8 @@ qse_long_t qse_strxtolong (const qse_char_t* str, qse_size_t len); qse_uint_t qse_strxtouint (const qse_char_t* str, qse_size_t len); qse_ulong_t qse_strxtoulong (const qse_char_t* str, qse_size_t len); -/****f* Common/qse_strspl - * NAME - * qse_strspl - split a string into fields - * SEE ALSO - * qse_strspltrn - * SYNOPSIS +/** + * The qse_strspl() function splits a string into fields. */ int qse_strspl ( qse_char_t* str, @@ -459,24 +493,24 @@ int qse_strspl ( ); /******/ -/****f* Common/qse_strspltrn - * NAME - * qse_strspltrn - split a string translating special escape sequences - * DESCRIPTION - * The argument trset is a translation character set which is composed - * of multiple character pairs. An escape character followed by the - * first character in a pair is translated into the second character - * in the pair. If trset is QSE_NULL, no translation is performed. - * EXAMPLES - * Let's translate a sequence of '\n' and '\r' to a new line and a carriage - * return respectively. +/** + * The qse_strspltrn() function splits a string translating special + * escape sequences. + * The argument @a trset is a translation character set which is composed + * of multiple character pairs. An escape character followed by the + * first character in a pair is translated into the second character + * in the pair. If trset is QSE_NULL, no translation is performed. + * + * Let's translate a sequence of '\n' and '\r' to a new line and a carriage + * return respectively. + * @code * qse_strspltrn (str, QSE_T(':'), QSE_T('['), QSE_T(']'), QSE_T('\\'), QSE_T("n\nr\r"), &nfields); - * Given [xxx]:[\rabc\ndef]:[] as an input, the example breaks the second - * fields to abcdef where is a carriage return and is a - * new line. - * SEE ALSO - * If you don't need any translation, you may call qse_strspl() alternatively. - * SYNOPSIS + * @endcode + * Given [xxx]:[\rabc\ndef]:[] as an input, the example breaks the second + * fields to abcdef where is a carriage return and is a + * new line. + * + * If you don't need any translation, you may call qse_strspl() alternatively. */ int qse_strspltrn ( qse_char_t* str, @@ -486,7 +520,6 @@ int qse_strspltrn ( qse_char_t escape, const qse_char_t* trset ); -/******/ /** * The qse_strtrmx() function strips leading spaces and/or trailing @@ -556,9 +589,50 @@ qse_size_t qse_strxpac ( qse_size_t len /**< length */ ); +/** + * The qse_mbstowcslen() function scans a null-terminated multibyte string + * to calculate the number of wide characters it can be converted to. + * The number of wide characters is returned via @a wcslen if it is not + * #QSE_NULL. The function may be aborted if it has encountered invalid + * or incomplete multibyte sequences. The return value, in this case, + * is less than qse_strlen(mcs). + * @return number of bytes scanned + */ +qse_size_t qse_mbstowcslen ( + const qse_mchar_t* mcs, + qse_size_t* wcslen +); + +/** + * The qse_mbsntowcsnlen() function scans a multibyte string of @a mcslen bytes + * to get the number of wide characters it can be converted to. + * The number of wide characters is returned via @a wcslen if it is not + * #QSE_NULL. The function may be aborted if it has encountered invalid + * or incomplete multibyte sequences. The return value, in this case, + * is less than @a mcslen. + * @return number of bytes scanned + */ +qse_size_t qse_mbsntowcsnlen ( + const qse_mchar_t* mcs, + qse_size_t mcslen, + qse_size_t* wcslen +); + /** * The qse_mbstowcs() function converts a multibyte string to a wide * character string. + * + * @code + * const qse_mchar_t* mbs = "a multibyte string"; + * qse_wchar_t buf[100]; + * qse_size_t bufsz = QSE_COUNTOF(buf), n; + * n = qse_mbstowcs (mbs, buf, bufsz); + * if (bufsz >= QSE_COUNTOF(buf)) { buffer too small } + * if (mbs[n] != '\0') { incomplete processing } + * //if (n != strlen(mbs)) { incomplete processing } + * @endcode + * + * @return number of multibyte characters processed. */ qse_size_t qse_mbstowcs ( const qse_mchar_t* mbs, @@ -569,7 +643,7 @@ qse_size_t qse_mbstowcs ( /** * The qse_mbsntowcsn() function converts a multibyte string to a * wide character string. - * @return number of bytes handled. + * @return number of multibyte characters processed. */ qse_size_t qse_mbsntowcsn ( const qse_mchar_t* mbs, @@ -578,11 +652,15 @@ qse_size_t qse_mbsntowcsn ( qse_size_t* wcslen ); -/****f* Common/qse_wcstombslen +/** * The qse_wcstombslen() function scans a null-terminated wide character - * string @a wcs to get the total number of multibyte characters that it can be - * converted to. The resulting number of characters is stored into memory - * pointed to by @a mbslen. + * string @a wcs to get the total number of multibyte characters that it + * can be converted to. The resulting number of characters is stored into + * memory pointed to by @a mbslen. + * Complete scanning is indicated by the following condition: + * @code + * qse_wcstombslen(wcs,&xx) == qse_strlen(wcs) + * @endcode * @return number of wide characters handled */ qse_size_t qse_wcstombslen ( @@ -592,9 +670,13 @@ qse_size_t qse_wcstombslen ( /** * The qse_wcsntombsnlen() function scans a wide character wcs as long as - * wcslen characters to get the get the total number of multibyte characters + * @a wcslen characters to get the total number of multibyte characters * that it can be converted to. The resulting number of characters is stored * into memory pointed to by @a mbslen. + * Complete scanning is indicated by the following condition: + * @code + * qse_wcstombslen(wcs,&xx) == wcslen + * @endcode * @return number of wide characters handled */ qse_size_t qse_wcsntombsnlen ( @@ -608,12 +690,11 @@ qse_size_t qse_wcsntombsnlen ( * string to a multibyte string and stores it into the buffer pointed to * by mbs. The pointer to a variable holding the buffer length should be * passed to the function as the third parameter. After conversion, it holds - * the length of the multibyte string excluding the terminating-null. + * the length of the multibyte string excluding the terminating-null character. * It may not null-terminate the resulting multibyte string if the buffer * is not large enough. You can check if the resulting mbslen is equal to * the input mbslen to know it. - * @return number of wide characters handled - * SYNOPSIS + * @return number of wide characters processed */ qse_size_t qse_wcstombs ( const qse_wchar_t* wcs, @@ -627,14 +708,26 @@ qse_size_t qse_wcstombs ( * @return the number of wide characters */ qse_size_t qse_wcsntombsn ( - const qse_wchar_t* wcs, /**< a wide string */ + const qse_wchar_t* wcs, /**< wide string */ qse_size_t wcslen, /**< wide string length */ - qse_mchar_t* mbs, /**< a multibyte string buffer */ - qse_size_t* mbslen /**< the buffer size */ + qse_mchar_t* mbs, /**< multibyte string buffer */ + qse_size_t* mbslen /**< buffer size */ ); /** - * The qse_wcstombs_strict() function performs the same as the qse_wcsmbs() + * The qse_mbstowcs_strict() function performs the same as the qse_mbstowcs() + * function except that it returns an error if it can't fully convert the + * input string and/or the buffer is not large enough. + * @return 0 on success, -1 on failure. + */ +int qse_mbstowcs_strict ( + const qse_mchar_t* mbs, + qse_wchar_t* wcs, + qse_size_t wcslen +); + +/** + * The qse_wcstombs_strict() function performs the same as the qse_wcstombs() * function except that it returns an error if it can't fully convert the * input string and/or the buffer is not large enough. * @return 0 on success, -1 on failure. @@ -657,75 +750,51 @@ void qse_str_close ( qse_str_t* str ); -/****f* Common/qse_str_init - * NAME - * qse_str_init - initialize a dynamically resizable string - * NOTE - * If the parameter capa is 0, it doesn't allocate the internal buffer - * in advance. - * SYNOPSIS +/** + * The qse_str_init() function initializes a dynamically resizable string + * If the parameter capa is 0, it doesn't allocate the internal buffer + * in advance. */ qse_str_t* qse_str_init ( qse_str_t* str, qse_mmgr_t* mmgr, qse_size_t capa ); -/******/ -/****f* Common/qse_str_fini - * NAME - * qse_str_fini - finialize a dynamically resizable string - * SYNOPSIS +/** + * The qse_str_fini() function finalizes a dynamically resizable string. */ void qse_str_fini ( qse_str_t* str ); -/******/ -/****f* Common/qse_str_yield - * NAME - * qse_str_yield - yield the buffer - * - * DESCRIPTION - * The qse_str_yield() function assigns the buffer to an variable of the - * qse_xstr_t type and recreate a new buffer of the new_capa capacity. - * The function fails if it fails to allocate a new buffer. - * - * RETURN - * The qse_str_yield() function returns 0 on success, and -1 on failure. - * - * SYNOPSIS +/** + * The qse_str_yield() function assigns the buffer to an variable of the + * qse_xstr_t type and recreate a new buffer of the @a new_capa capacity. + * The function fails if it fails to allocate a new buffer. + * @return 0 on success, and -1 on failure. */ int qse_str_yield ( - qse_str_t* str /* a dynamic string */, - qse_xstr_t* buf /* the pointer to a qse_xstr_t variable */, - int new_capa /* new capacity in number of characters */ + qse_str_t* str, /**< string */ + qse_xstr_t* buf, /**< buffer pointer */ + int new_capa /**< new capacity */ ); -/******/ -/****f* Common/qse_str_getsizer - * NAME - * qse_str_getsizer - get the sizer - * RETURN - * a sizer function set or QSE_NULL if no sizer is set. - * SYNOPSIS +/** + * The qse_str_getsizer() function gets the sizer. + * @return sizer function set or QSE_NULL if no sizer is set. */ qse_str_sizer_t qse_str_getsizer ( qse_str_t* str ); -/******/ -/****f* Common/qse_str_setsizer - * NAME - * qse_str_setsizer - specify a sizer - * DESCRIPTION - * The qse_str_setsizer() function specify a new sizer for a dynamic string. - * With no sizer specified, the dynamic string doubles the current buffer - * when it needs to increase its size. The sizer function is passed a dynamic - * string and the minimum capacity required to hold data after resizing. - * The string is truncated if the sizer function returns a smaller number - * than the hint passed. - * SYNOPSIS +/** + * The qse_str_setsizer() function specify a new sizer for a dynamic string. + * With no sizer specified, the dynamic string doubles the current buffer + * when it needs to increase its size. The sizer function is passed a dynamic + * string and the minimum capacity required to hold data after resizing. + * The string is truncated if the sizer function returns a smaller number + * than the hint passed. */ void qse_str_setsizer ( qse_str_t* str, @@ -733,87 +802,58 @@ void qse_str_setsizer ( ); /******/ -/****f* Common/qse_str_getcapa - * NAME - * qse_str_getcapa - get capacity - * DESCRIPTION - * The qse_str_getcapa() function returns the current capacity. - * You may use QSE_STR_CAPA(str) macro for performance sake. - * RETURNS - * current capacity in number of characters. - * SYNOPSIS +/** + * The qse_str_getcapa() function returns the current capacity. + * You may use QSE_STR_CAPA(str) macro for performance sake. + * @return current capacity in number of characters. */ qse_size_t qse_str_getcapa ( qse_str_t* str ); -/******/ -/****f* Common/qse_str_setcapa - * NAME - * qse_str_setcapa - set new capacity - * DESCRIPTION - * The qse_str_setcapa() function sets the new capacity. If the new capacity - * is smaller than the old, the overflowing characters are removed from - * from the buffer. - * RETURNS - * (qse_size_t)-1 on failure, new capacity on success - * SYNOPSIS +/** + * The qse_str_setcapa() function sets the new capacity. If the new capacity + * is smaller than the old, the overflowing characters are removed from + * from the buffer. + * @return (qse_size_t)-1 on failure, new capacity on success */ qse_size_t qse_str_setcapa ( qse_str_t* str, qse_size_t capa ); -/******/ -/****f* Common/qse_str_getlen - * NAME - * qse_str_getlen - get length - * SYNOPSIS +/** + * The qse_str_getlen() function return the string length. */ qse_size_t qse_str_getlen ( qse_str_t* str ); -/******/ -/****f* Common/qse_str_setlen - * NAME - * qse_str_setlen - change length - * RETURNS - * (qse_size_t)-1 on failure, new length on success - * SYNOPSIS +/** + * The qse_str_setlen() function changes the string length. + * @return (qse_size_t)-1 on failure, new length on success */ qse_size_t qse_str_setlen ( qse_str_t* str, qse_size_t len ); -/******/ -/****f* Common/qse_str_clear - * NAME - * qse_str_clear - clear a string - * DESCRIPTION - * The qse_str_clear() funtion deletes all characters in a string and sets - * the length to 0. It doesn't resize the internal buffer. - * SYNOPSIS +/** + * The qse_str_clear() funtion deletes all characters in a string and sets + * the length to 0. It doesn't resize the internal buffer. */ void qse_str_clear ( qse_str_t* str ); -/******/ -/****f* Common/qse_str_swap - * NAME - * qse_str_swap - swap buffers of two dynamic string - * DESCRIPTION - * The qse_str_swap() function exchanges the pointers to a buffer between - * two strings. It updates the length and the capacity accordingly. - * SYNOPSIS +/** + * The qse_str_swap() function exchanges the pointers to a buffer between + * two strings. It updates the length and the capacity accordingly. */ void qse_str_swap ( qse_str_t* str1, qse_str_t* str2 ); -/******/ qse_size_t qse_str_cpy ( qse_str_t* str, diff --git a/qse/include/qse/macros.h b/qse/include/qse/macros.h index 584a0097..5773a8a5 100644 --- a/qse/include/qse/macros.h +++ b/qse/include/qse/macros.h @@ -1,5 +1,5 @@ /* - * $Id: macros.h 289 2009-09-16 06:35:29Z hyunghwan.chung $ + * $Id: macros.h 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -27,6 +27,14 @@ * contains various useful macro definitions. */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L) +# define QSE_INLINE inline +#elif defined(__GNUC__) && defined(__GNUC_GNU_INLINE__) +# define QSE_INLINE /*extern*/ inline +#else +# define QSE_INLINE +#endif + /** * The #QSE_NULL macro defines a special pointer value to indicate an error or * that it does not point to anything. @@ -128,13 +136,13 @@ #define QSE_ABS(x) ((x) < 0? -(x): (x)) -#define QSE_ERR_THROW(id) goto __err_ ## id -#define QSE_ERR_CATCH(id) while(0) __err_ ## id: +#define QSE_THROW_ERR(id) goto __err_ ## id +#define QSE_CATCH_ERR(id) while(0) __err_ ## id: -#define QSE_LOOP_CONTINUE(id) goto __loop_ ## id ## _begin__ -#define QSE_LOOP_BREAK(id) goto __loop_ ## id ## _end__ -#define QSE_LOOP_BEGIN(id) __loop_ ## id ## _begin__: { -#define QSE_LOOP_END(id) QSE_LOOP_CONTINUE(id) } __loop_ ## id ## _end__: +#define QSE_CONTINUE_LOOP(id) goto __loop_ ## id ## _begin__ +#define QSE_BREAK_LOOP(id) goto __loop_ ## id ## _end__ +#define QSE_BEGIN_LOOP(id) __loop_ ## id ## _begin__: { +#define QSE_END_LOOP(id) QSE_LOOP_CONTINUE(id) } __loop_ ## id ## _end__: #define QSE_REPEAT(n,blk) \ do { \ @@ -196,6 +204,16 @@ # define QSE_END_PACKED_STRUCT() }; #endif +/** + * The QSE_STRUCT_FIELD() macro provides a neutral way to specify + * a field ID for initialzing a structure in both C9X and C89 + */ +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L)) || defined(__GNUC__) +# define QSE_STRUCT_FIELD(id) .id = +#else +# define QSE_STRUCT_FIELD(id) +#endif + #ifdef NDEBUG # define QSE_ASSERT(expr) ((void)0) # define QSE_ASSERTX(expr,desc) ((void)0) @@ -227,8 +245,17 @@ * The QSE_DEFINE_COMMON_FIELDS() macro defines common object fields. */ #define QSE_DEFINE_COMMON_FIELDS(name) \ - qse_mmgr_t* mmgr; + qse_mmgr_t* mmgr; + +#define QSE_BEGIN_CLASS(name) \ + typedef struct name name; \ + struct name \ + { \ + qse_mmgr_t* mmgr; \ + +#define QSE_END_CLASS(name) }; + /** * The QSE_DEFINE_COMMON_FUNCTIONS() macro defines common object functions. * - @code void qse_xxx_setmmgr (qse_xxx_t* xxx, qse_mmgr_t* mmgr); @endcode diff --git a/qse/lib/awk/parse.c b/qse/lib/awk/parse.c index d8f7e779..6dbc52ad 100644 --- a/qse/lib/awk/parse.c +++ b/qse/lib/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c 312 2009-12-10 13:03:54Z hyunghwan.chung $ + * $Id: parse.c 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -226,8 +226,6 @@ static int skip_spaces (qse_awk_t* awk); static int skip_comment (qse_awk_t* awk); static int classify_ident ( qse_awk_t* awk, const qse_char_t* name, qse_size_t len); -static int is_plain_var (qse_awk_nde_t* nde); -static int is_var (qse_awk_nde_t* nde); static int deparse (qse_awk_t* awk); static qse_map_walk_t deparse_func ( @@ -400,6 +398,26 @@ static global_t gtab[] = #define SETERR_ARG(awk,code,ep,el) SETERR_ARG_LOC(awk,code,ep,el,QSE_NULL) +static QSE_INLINE int is_plain_var (qse_awk_nde_t* nde) +{ + return nde->type == QSE_AWK_NDE_GBL || + nde->type == QSE_AWK_NDE_LCL || + nde->type == QSE_AWK_NDE_ARG || + nde->type == QSE_AWK_NDE_NAMED; +} + +static QSE_INLINE int is_var (qse_awk_nde_t* nde) +{ + return nde->type == QSE_AWK_NDE_GBL || + nde->type == QSE_AWK_NDE_LCL || + nde->type == QSE_AWK_NDE_ARG || + nde->type == QSE_AWK_NDE_NAMED || + nde->type == QSE_AWK_NDE_GBLIDX || + nde->type == QSE_AWK_NDE_LCLIDX || + nde->type == QSE_AWK_NDE_ARGIDX || + nde->type == QSE_AWK_NDE_NAMEDIDX; +} + static int get_char (qse_awk_t* awk) { qse_ssize_t n; @@ -5762,26 +5780,6 @@ static int classify_ident ( return TOK_IDENT; } -static int is_plain_var (qse_awk_nde_t* nde) -{ - return nde->type == QSE_AWK_NDE_GBL || - nde->type == QSE_AWK_NDE_LCL || - nde->type == QSE_AWK_NDE_ARG || - nde->type == QSE_AWK_NDE_NAMED; -} - -static int is_var (qse_awk_nde_t* nde) -{ - return nde->type == QSE_AWK_NDE_GBL || - nde->type == QSE_AWK_NDE_LCL || - nde->type == QSE_AWK_NDE_ARG || - nde->type == QSE_AWK_NDE_NAMED || - nde->type == QSE_AWK_NDE_GBLIDX || - nde->type == QSE_AWK_NDE_LCLIDX || - nde->type == QSE_AWK_NDE_ARGIDX || - nde->type == QSE_AWK_NDE_NAMEDIDX; -} - struct deparse_func_t { qse_awk_t* awk; diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index e06c73d0..3da15fc5 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c 312 2009-12-10 13:03:54Z hyunghwan.chung $ + * $Id: run.c 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -273,17 +273,17 @@ static qse_cstr_t* xstr_to_cstr (qse_xstr_t* xstr) } #endif -qse_size_t qse_awk_rtx_getnargs (qse_awk_rtx_t* run) +QSE_INLINE qse_size_t qse_awk_rtx_getnargs (qse_awk_rtx_t* run) { return (qse_size_t) STACK_NARGS (run); } -qse_awk_val_t* qse_awk_rtx_getarg (qse_awk_rtx_t* run, qse_size_t idx) +QSE_INLINE qse_awk_val_t* qse_awk_rtx_getarg (qse_awk_rtx_t* run, qse_size_t idx) { return STACK_ARG (run, idx); } -qse_awk_val_t* qse_awk_rtx_getgbl (qse_awk_rtx_t* run, int id) +QSE_INLINE qse_awk_val_t* qse_awk_rtx_getgbl (qse_awk_rtx_t* run, int id) { QSE_ASSERT (id >= 0 && id < (int)QSE_LDA_SIZE(run->awk->parse.gbls)); return STACK_GBL (run, id); @@ -618,7 +618,7 @@ static int set_global ( return 0; } -void qse_awk_rtx_setretval (qse_awk_rtx_t* rtx, qse_awk_val_t* val) +QSE_INLINE void qse_awk_rtx_setretval (qse_awk_rtx_t* rtx, qse_awk_val_t* val) { qse_awk_rtx_refdownval (rtx, STACK_RETVAL(rtx)); STACK_RETVAL(rtx) = val; @@ -626,7 +626,7 @@ void qse_awk_rtx_setretval (qse_awk_rtx_t* rtx, qse_awk_val_t* val) qse_awk_rtx_refupval (rtx, val); } -int qse_awk_rtx_setgbl (qse_awk_rtx_t* rtx, int id, qse_awk_val_t* val) +QSE_INLINE int qse_awk_rtx_setgbl (qse_awk_rtx_t* rtx, int id, qse_awk_val_t* val) { QSE_ASSERT (id >= 0 && id < (int)QSE_LDA_SIZE(rtx->awk->parse.gbls)); return set_global (rtx, (qse_size_t)id, QSE_NULL, val); diff --git a/qse/lib/cmn/chr_cnv.c b/qse/lib/cmn/chr_cnv.c index 45e5d786..a07f2943 100644 --- a/qse/lib/cmn/chr_cnv.c +++ b/qse/lib/cmn/chr_cnv.c @@ -1,5 +1,5 @@ /* - * $Id: chr_cnv.c 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: chr_cnv.c 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -41,6 +41,13 @@ qse_size_t qse_mblen (const qse_mchar_t* mb, qse_size_t mblen) if (n == (size_t)-2) return mblen + 1; /* incomplete sequence */ return (qse_size_t)n; + + #if 0 + n = mblen (mb, mblen, &mbs); + if (n == 0) return 1; /* a null character */ + if (n == (size_t)-1) return 0; /* invalid or incomplete sequence */ + return (qse_size_t)n; + #endif #else #error #### NOT SUPPORTED #### #endif diff --git a/qse/lib/cmn/fio.c b/qse/lib/cmn/fio.c index 225ac01b..f835ba50 100644 --- a/qse/lib/cmn/fio.c +++ b/qse/lib/cmn/fio.c @@ -1,5 +1,5 @@ /* - * $Id: fio.c 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: fio.c 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -213,16 +213,16 @@ qse_fio_t* qse_fio_init ( qse_tio_t* tio; tio = qse_tio_open (fio->mmgr, 0); - if (tio == QSE_NULL) QSE_ERR_THROW (tio); + if (tio == QSE_NULL) QSE_THROW_ERR (tio); if (qse_tio_attachin (tio, fio_input, fio) == -1 || qse_tio_attachout (tio, fio_output, fio) == -1) { qse_tio_close (tio); - QSE_ERR_THROW (tio); + QSE_THROW_ERR (tio); } - QSE_ERR_CATCH (tio) + QSE_CATCH_ERR (tio) { #ifdef _WIN32 CloseHandle (handle); diff --git a/qse/lib/cmn/lda.c b/qse/lib/cmn/lda.c index d4f04894..28c64e7e 100644 --- a/qse/lib/cmn/lda.c +++ b/qse/lib/cmn/lda.c @@ -1,5 +1,5 @@ /* - * $Id: lda.c 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: lda.c 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -39,7 +39,7 @@ QSE_IMPLEMENT_COMMON_FUNCTIONS (lda) #define DPTR(node) ((node)->dptr) #define DLEN(node) ((node)->dlen) -static int comp_data (lda_t* lda, +static int default_comparator (lda_t* lda, const void* dptr1, size_t dlen1, const void* dptr2, size_t dlen2) { @@ -58,7 +58,7 @@ static int comp_data (lda_t* lda, return n; } -static node_t* alloc_node (lda_t* lda, void* dptr, size_t dlen) +static QSE_INLINE node_t* alloc_node (lda_t* lda, void* dptr, size_t dlen) { node_t* n; @@ -136,7 +136,7 @@ lda_t* qse_lda_init (lda_t* lda, mmgr_t* mmgr, size_t capa) lda->node = QSE_NULL; lda->copier = QSE_LDA_COPIER_SIMPLE; - lda->comper = comp_data; + lda->comper = default_comparator; if (qse_lda_setcapa (lda, capa) == QSE_NULL) return QSE_NULL; return lda; @@ -162,7 +162,8 @@ int qse_lda_getscale (lda_t* lda) void qse_lda_setscale (lda_t* lda, int scale) { QSE_ASSERTX (scale > 0 && scale <= QSE_TYPE_MAX(qse_byte_t), - "The scale should be larger than 0 and less than or equal to the maximum value that the qse_byte_t type can hold"); + "The scale should be larger than 0 and less than or " + "equal to the maximum value that the qse_byte_t type can hold"); if (scale <= 0) scale = 1; if (scale > QSE_TYPE_MAX(qse_byte_t)) scale = QSE_TYPE_MAX(qse_byte_t); @@ -198,7 +199,7 @@ comper_t qse_lda_getcomper (lda_t* lda) void qse_lda_setcomper (lda_t* lda, comper_t comper) { - if (comper == QSE_NULL) comper = comp_data; + if (comper == QSE_NULL) comper = default_comparator; lda->comper = comper; } @@ -236,8 +237,11 @@ lda_t* qse_lda_setcapa (lda_t* lda, size_t capa) { void* tmp; + if (capa == lda->capa) return lda; + if (lda->size > capa) { + /* to trigger freeers on the items truncated */ qse_lda_delete (lda, capa, lda->size - capa); QSE_ASSERT (lda->size <= capa); } @@ -246,13 +250,14 @@ lda_t* qse_lda_setcapa (lda_t* lda, size_t capa) { if (lda->mmgr->realloc != QSE_NULL && lda->node != QSE_NULL) { - tmp = (qse_lda_node_t**)QSE_MMGR_REALLOC ( - lda->mmgr, lda->node, QSE_SIZEOF(*lda->node)*capa); + tmp = (node_t**) QSE_MMGR_REALLOC ( + lda->mmgr, lda->node, + QSE_SIZEOF(*lda->node)*capa); if (tmp == QSE_NULL) return QSE_NULL; } else { - tmp = (qse_lda_node_t**) QSE_MMGR_ALLOC ( + tmp = (node_t**) QSE_MMGR_ALLOC ( lda->mmgr, QSE_SIZEOF(*lda->node)*capa); if (tmp == QSE_NULL) return QSE_NULL; @@ -261,7 +266,7 @@ lda_t* qse_lda_setcapa (lda_t* lda, size_t capa) size_t x; x = (capa > lda->capa)? lda->capa: capa; QSE_MEMCPY (tmp, lda->node, - QSE_SIZEOF(*lda->node) * x); + QSE_SIZEOF(*lda->node)*x); QSE_MMGR_FREE (lda->mmgr, lda->node); } } @@ -514,6 +519,8 @@ void qse_lda_walk (lda_t* lda, walker_t walker, void* arg) qse_lda_walk_t w = QSE_LDA_WALK_FORWARD; size_t i = 0; + if (lda->size <= 0) return; + while (1) { if (lda->node[i] != QSE_NULL) @@ -562,3 +569,108 @@ void qse_lda_rwalk (lda_t* lda, walker_t walker, void* arg) } } +size_t qse_lda_pushstack (lda_t* lda, void* dptr, size_t dlen) +{ + return qse_lda_insert (lda, lda->size, dptr, dlen); +} + +void qse_lda_popstack (lda_t* lda) +{ + QSE_ASSERT (lda->size > 0); + qse_lda_delete (lda, lda->size - 1, 1); +} + +#define HEAP_PARENT(x) (((x)-1) / 2) +#define HEAP_LEFT(x) ((x)*2 + 1) +#define HEAP_RIGHT(x) ((x)*2 + 2) + +size_t qse_lda_pushheap (lda_t* lda, void* dptr, size_t dlen) +{ + size_t cur, par; + int n; + + /* add a value to the bottom */ + cur = lda->size; + if (qse_lda_insert (lda, cur, dptr, dlen) == QSE_LDA_NIL) + return QSE_LDA_NIL; + + while (cur != 0) + { + node_t* tmp; + + /* compare with the parent */ + par = HEAP_PARENT(cur); + n = lda->comper (lda, + DPTR(lda->node[cur]), DLEN(lda->node[cur]), + DPTR(lda->node[par]), DLEN(lda->node[par])); + if (n <= 0) break; /* ok */ + + /* swap the current with the parent */ + tmp = lda->node[cur]; + lda->node[cur] = lda->node[par]; + lda->node[par] = tmp; + + cur = par; + } + + return lda->size; +} + +void qse_lda_popheap (lda_t* lda) +{ + size_t cur, child; + node_t* tmp; + + QSE_ASSERT (lda->size > 0); + + /* destroy the top */ + tmp = lda->node[0]; + if (lda->freeer) lda->freeer (lda, DPTR(tmp), DLEN(tmp)); + QSE_MMGR_FREE (lda->mmgr, tmp); + + /* move the last item to the top position also shrink the size */ + lda->node[0] = lda->node[--lda->size]; + + if (lda->size <= 1) return; /* only 1 element. nothing further to do */ + + for (cur = 0; cur < lda->size; cur = child) + { + size_t left, right; + int n; + + left = HEAP_LEFT(cur); + right = HEAP_RIGHT(cur); + + if (left >= lda->size) + { + /* the left child does not exist. + * reached the bottom. abort exchange */ + break; + } + + if (right >= lda->size) + { + /* the right child does not exist. only the left */ + child = left; + } + else + { + /* get the larger child of the two */ + n = lda->comper (lda, + DPTR(lda->node[left]), DLEN(lda->node[left]), + DPTR(lda->node[right]), DLEN(lda->node[right])); + child = (n > 0)? left: right; + } + + /* compare the current one with the child */ + n = lda->comper (lda, + DPTR(lda->node[cur]), DLEN(lda->node[cur]), + DPTR(lda->node[child]), DLEN(lda->node[child])); + if (n > 0) break; /* current one is larger. stop exchange */ + + /* swap the current with the child */ + tmp = lda->node[cur]; + lda->node[cur] = lda->node[child]; + lda->node[child] = tmp; + } +} diff --git a/qse/lib/cmn/main.c b/qse/lib/cmn/main.c index 3dc623f7..9ab61f09 100644 --- a/qse/lib/cmn/main.c +++ b/qse/lib/cmn/main.c @@ -19,10 +19,9 @@ */ #include -#include -#include -#include +#include #include +#include "mem.h" #if defined(_WIN32) && !defined(__MINGW32__) @@ -37,62 +36,62 @@ int qse_runmain (int argc, qse_achar_t* argv[], int(*mf) (int,qse_char_t*[])) { int i, ret; qse_char_t** v; + qse_mmgr_t* mmgr = QSE_MMGR_GETDFL (); setlocale (LC_ALL, ""); - v = (qse_char_t**) malloc (argc * QSE_SIZEOF(qse_char_t*)); - if (v == NULL) return -1; + v = (qse_char_t**) QSE_MMGR_ALLOC ( + mmgr, argc * QSE_SIZEOF(qse_char_t*)); + if (v == QSE_NULL) return -1; + + for (i = 0; i < argc; i++) v[i] = QSE_NULL; - for (i = 0; i < argc; i++) v[i] = NULL; for (i = 0; i < argc; i++) { - qse_size_t n, len, rem; - char* p = argv[i]; + qse_size_t n, len, nlen; + qse_size_t mbslen; - len = 0; rem = strlen (p); - while (*p != '\0') + mbslen = qse_mbslen (argv[i]); + + n = qse_mbstowcslen (argv[i], &len); + if (n < mbslen) { - int x = mblen (p, rem); - if (x == -1) - { - ret = -1; - goto exit_main; - } - if (x == 0) break; - p += x; rem -= x; len++; + ret = -1; goto oops; } - #if (defined(vms) || defined(__vms)) && (QSE_SIZEOF_VOID_P >= 8) - v[i] = (qse_char_t*) _malloc32 ((len+1)*QSE_SIZEOF(qse_char_t)); - #else - v[i] = (qse_char_t*) malloc ((len+1)*QSE_SIZEOF(qse_char_t)); - #endif - if (v[i] == NULL) + len++; /* include the terminating null */ + + v[i] = (qse_char_t*) QSE_MMGR_ALLOC ( + mmgr, len*QSE_SIZEOF(qse_char_t)); + if (v[i] == QSE_NULL) { - ret = -1; - goto exit_main; + ret = -1; goto oops; } - n = mbstowcs (v[i], argv[i], len); - if (n == (size_t)-1) + nlen = len; + n = qse_mbstowcs (argv[i], v[i], &nlen); + if (nlen >= len) { - /* error */ - return -1; + /* no null-termination */ + ret = -1; goto oops; + } + if (argv[i][n] != '\0') + { + /* partial processing */ + ret = -1; goto oops; } - - if (n == len) v[i][len] = QSE_T('\0'); } /* TODO: envp... */ - //ret = mf (argc, v, NULL); + //ret = mf (argc, v, QSE_NULL); ret = mf (argc, v); -exit_main: +oops: for (i = 0; i < argc; i++) { - if (v[i] != NULL) free (v[i]); + if (v[i] != QSE_NULL) QSE_MMGR_FREE (mmgr, v[i]); } - free (v); + QSE_MMGR_FREE (mmgr, v); return ret; } diff --git a/qse/lib/cmn/str_bas.c b/qse/lib/cmn/str_bas.c index 37b1735e..e1d48521 100644 --- a/qse/lib/cmn/str_bas.c +++ b/qse/lib/cmn/str_bas.c @@ -1,5 +1,5 @@ /* - * $Id: str_bas.c 320 2009-12-21 12:29:52Z hyunghwan.chung $ + * $Id: str_bas.c 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -36,6 +36,20 @@ qse_size_t qse_strbytes (const qse_char_t* str) return (p - str) * QSE_SIZEOF(qse_char_t); } +qse_size_t qse_mbslen (const qse_mchar_t* mbs) +{ + const qse_mchar_t* p = mbs; + while (*p != QSE_T('\0')) p++; + return p - mbs; +} + +qse_size_t qse_wcslen (const qse_wchar_t* wcs) +{ + const qse_wchar_t* p = wcs; + while (*p != QSE_T('\0')) p++; + return p - wcs; +} + qse_size_t qse_strcpy (qse_char_t* buf, const qse_char_t* str) { qse_char_t* org = buf; diff --git a/qse/lib/cmn/str_cnv.c b/qse/lib/cmn/str_cnv.c index 2e669a9a..72b1dd4c 100644 --- a/qse/lib/cmn/str_cnv.c +++ b/qse/lib/cmn/str_cnv.c @@ -1,5 +1,5 @@ /* - * $Id: str_cnv.c 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: str_cnv.c 323 2010-04-05 12:50:01Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -133,6 +133,45 @@ qse_ulong_t qse_strxtoulong (const qse_char_t* str, qse_size_t len) return v; } +qse_size_t qse_mbstowcslen (const qse_mchar_t* mcs, qse_size_t* wcslen) +{ + qse_wchar_t wc; + qse_size_t n, ml, wl = 0; + const qse_mchar_t* p = mcs; + + while (*p != '\0') p++; + ml = p - mcs; + + for (p = mcs; ml > 0; p += n, ml -= n) + { + n = qse_mbtowc (p, ml, &wc); + /* insufficient input or wrong sequence */ + if (n == 0 || n > ml) break; + wl++; + } + + if (wcslen) *wcslen = wl; + return p - mcs; +} + +qse_size_t qse_mbsntowcsnlen (const qse_mchar_t* mcs, qse_size_t mcslen, qse_size_t* wcslen) +{ + qse_wchar_t wc; + qse_size_t n, ml = mcslen, wl = 0; + const qse_mchar_t* p = mcs; + + for (p = mcs; ml > 0; p += n, ml -= n) + { + n = qse_mbtowc (p, ml, &wc); + /* insufficient or invalid sequence */ + if (n == 0 || n > ml) break; + wl++; + } + + if (wcslen) *wcslen = wl; + return mcslen - ml; +} + qse_size_t qse_mbstowcs ( const qse_mchar_t* mbs, qse_wchar_t* wcs, qse_size_t* wcslen) { @@ -141,24 +180,26 @@ qse_size_t qse_mbstowcs ( /* get the length of mbs and pass it to qse_mbsntowcsn as * qse_mbtowc called by qse_mbsntowcsn needs it. */ + wlen = *wcslen; + if (wlen <= 0) + { + /* buffer too small. also cannot null-terminate it */ + *wcslen = 0; + return 0; /* 0 byte processed */ + } + for (mp = mbs; *mp != '\0'; mp++); - - if (*wcslen <= 0) - { - /* buffer too small. cannot null-terminate it */ - return 0; - } - if (*wcslen == 1) - { - wcs[0] = L'\0'; - return 0; - } - - wlen = *wcslen - 1; mlen = qse_mbsntowcsn (mbs, mp - mbs, wcs, &wlen); + if (wlen < *wcslen) + { + /* null-terminate wcs if it is large enough. */ + wcs[wlen] = L'\0'; + } - wcs[wlen] = L'\0'; - *wcslen = wlen; + /* if null-terminated properly, the input wcslen must be less than + * the output wcslen. (input length includs the terminating null + * while the output length excludes the terminating null) */ + *wcslen = wlen; return mlen; } @@ -305,6 +346,29 @@ qse_size_t qse_wcsntombsn ( return p - wcs; } +int qse_mbstowcs_strict ( + const qse_mchar_t* mbs, qse_wchar_t* wcs, qse_size_t wcslen) +{ + qse_size_t n; + qse_size_t wn = wcslen; + + n = qse_mbstowcs (mbs, wcs, &wn); + if (wn >= wcslen) + { + /* wcs not big enough to be null-terminated. + * if it has been null-terminated properly, + * wn should be less than wcslen. */ + return -1; + } + if (mbs[n] != QSE_MT('\0')) + { + /* incomplete sequence or invalid sequence */ + return -1; + } + + return 0; +} + int qse_wcstombs_strict ( const qse_wchar_t* wcs, qse_mchar_t* mbs, qse_size_t mbslen) { @@ -312,13 +376,6 @@ int qse_wcstombs_strict ( qse_size_t mn = mbslen; n = qse_wcstombs (wcs, mbs, &mn); - if (wcs[n] != QSE_WT('\0')) - { - /* if qse_wcstombs() processed all wide characters, - * the character at position 'n' should be a null character - * as 'n' is the number of wide characters processed. */ - return -1; - } if (mn >= mbslen) { /* mbs not big enough to be null-terminated. @@ -326,6 +383,14 @@ int qse_wcstombs_strict ( * mn should be less than mbslen. */ return -1; } + if (wcs[n] != QSE_WT('\0')) + { + /* if qse_wcstombs() processed all wide characters, + * the character at position 'n' should be a null character + * as 'n' is the number of wide characters processed. */ + return -1; + } return 0; } + diff --git a/qse/regress/awk/passwd.dat b/qse/regress/awk/passwd.dat new file mode 100644 index 00000000..ecfcbd86 --- /dev/null +++ b/qse/regress/awk/passwd.dat @@ -0,0 +1,38 @@ +root:x:0:0:root:/root:/bin/bash +daemon:x:1:1:daemon:/usr/sbin:/bin/sh +bin:x:2:2:bin:/bin:/bin/sh +sys:x:3:3:sys:/dev:/bin/sh +sync:x:4:65534:sync:/bin:/bin/sync +games:x:5:60:games:/usr/games:/bin/sh +man:x:6:12:man:/var/cache/man:/bin/sh +lp:x:7:7:lp:/var/spool/lpd:/bin/sh +mail:x:8:8:mail:/var/mail:/bin/sh +news:x:9:9:news:/var/spool/news:/bin/sh +uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh +proxy:x:13:13:proxy:/bin:/bin/sh +www-data:x:33:33:www-data:/var/www:/bin/sh +backup:x:34:34:backup:/var/backups:/bin/sh +list:x:38:38:Mailing List Manager:/var/list:/bin/sh +irc:x:39:39:ircd:/var/run/ircd:/bin/sh +gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh +nobody:x:65534:65534:nobody:/nonexistent:/bin/sh +libuuid:x:100:101::/var/lib/libuuid:/bin/sh +syslog:x:101:102::/home/syslog:/bin/false +klog:x:102:103::/home/klog:/bin/false +hplip:x:103:7:HPLIP system user,,,:/var/run/hplip:/bin/false +avahi-autoipd:x:104:110:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false +gdm:x:105:111:Gnome Display Manager:/var/lib/gdm:/bin/false +saned:x:106:113::/home/saned:/bin/false +pulse:x:107:114:PulseAudio daemon,,,:/var/run/pulse:/bin/false +messagebus:x:108:117::/var/run/dbus:/bin/false +polkituser:x:109:118:PolicyKit,,,:/var/run/PolicyKit:/bin/false +avahi:x:110:119:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false +haldaemon:x:111:120:Hardware abstraction layer,,,:/var/run/hald:/bin/false +statd:x:112:65534::/var/lib/nfs:/bin/false +sshd:x:113:65534::/var/run/sshd:/usr/sbin/nologin +speech-dispatcher:x:114:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/sh +couchdb:x:115:116:CouchDB Administrator,,,:/var/lib/couchdb:/bin/bash +kernoops:x:116:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false +mysql:x:117:124:MySQL Server,,,:/var/lib/mysql:/bin/false +openldap:x:118:125:OpenLDAP Server Account,,,:/nonexistent:/bin/false +postfix:x:119:126::/var/spool/postfix:/bin/false diff --git a/qse/regress/awk/regress.out b/qse/regress/awk/regress.out index bd2788f1..98a75b12 100644 --- a/qse/regress/awk/regress.out +++ b/qse/regress/awk/regress.out @@ -2087,7 +2087,7 @@ IGNORECASE= 1 1 1 -------------------------------------------------------------------------------- - ../../cmd/awk/.libs/qseawk --newline=on -F: -f columnate.awk /etc/passwd &1 + ../../cmd/awk/.libs/qseawk --newline=on -F: -f columnate.awk ./passwd.dat &1 -------------------------------------------------------------------------------- root x 0 0 root /root /bin/bash daemon x 1 1 daemon /usr/sbin /bin/sh @@ -2119,12 +2119,14 @@ messagebus x 108 117 /var/run polkituser x 109 118 PolicyKit,,, /var/run/PolicyKit /bin/false avahi x 110 119 Avahi mDNS daemon,,, /var/run/avahi-daemon /bin/false haldaemon x 111 120 Hardware abstraction layer,,, /var/run/hald /bin/false -hyung-hwan x 1000 1000 hyung-hwan chung,,, /home/hyung-hwan /bin/bash statd x 112 65534 /var/lib/nfs /bin/false sshd x 113 65534 /var/run/sshd /usr/sbin/nologin speech-dispatcher x 114 29 Speech Dispatcher,,, /var/run/speech-dispatcher /bin/sh couchdb x 115 116 CouchDB Administrator,,, /var/lib/couchdb /bin/bash kernoops x 116 65534 Kernel Oops Tracking Daemon,,, / /bin/false +mysql x 117 124 MySQL Server,,, /var/lib/mysql /bin/false +openldap x 118 125 OpenLDAP Server Account,,, /nonexistent /bin/false +postfix x 119 126 /var/spool/postfix /bin/false -------------------------------------------------------------------------------- ../../cmd/awk/.libs/qseawk --newline=on --include=on -f levenshtein-utests.awk &1 -------------------------------------------------------------------------------- diff --git a/qse/regress/awk/regress.sh b/qse/regress/awk/regress.sh index 9e355e06..62e7fe73 100755 --- a/qse/regress/awk/regress.sh +++ b/qse/regress/awk/regress.sh @@ -154,7 +154,7 @@ PROGS=" lang-041.awk!!!--newline=on -o- lang-042.awk!!!--newline=on -o- - columnate.awk!/etc/passwd!!--newline=on -F: + columnate.awk!./passwd.dat!!--newline=on -F: levenshtein-utests.awk!!!--newline=on --include=on rcalc.awk!!!--newline=on -v target=89000 quicksort.awk!quicksort.dat!! diff --git a/qse/samples/cmn/Makefile.am b/qse/samples/cmn/Makefile.am index 64bb2bef..19903341 100644 --- a/qse/samples/cmn/Makefile.am +++ b/qse/samples/cmn/Makefile.am @@ -1,6 +1,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -DNDEBUG -bin_PROGRAMS = chr str sll map lda fio pio sio time rex01 +bin_PROGRAMS = chr str sll map lda fio pio sio time main rex01 LDFLAGS = -L../../lib/cmn LDADD = -lqsecmn @@ -14,6 +14,7 @@ fio_SOURCES = fio.c pio_SOURCES = pio.c sio_SOURCES = sio.c time_SOURCES = time.c +main_SOURCES = main.c rex01_SOURCES = rex01.c if ENABLE_CXX diff --git a/qse/samples/cmn/Makefile.in b/qse/samples/cmn/Makefile.in index 53b221c4..1032e846 100644 --- a/qse/samples/cmn/Makefile.in +++ b/qse/samples/cmn/Makefile.in @@ -36,7 +36,7 @@ build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = chr$(EXEEXT) str$(EXEEXT) sll$(EXEEXT) map$(EXEEXT) \ lda$(EXEEXT) fio$(EXEEXT) pio$(EXEEXT) sio$(EXEEXT) \ - time$(EXEEXT) rex01$(EXEEXT) + time$(EXEEXT) main$(EXEEXT) rex01$(EXEEXT) subdir = samples/cmn DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -65,6 +65,10 @@ am_lda_OBJECTS = lda.$(OBJEXT) lda_OBJECTS = $(am_lda_OBJECTS) lda_LDADD = $(LDADD) lda_DEPENDENCIES = +am_main_OBJECTS = main.$(OBJEXT) +main_OBJECTS = $(am_main_OBJECTS) +main_LDADD = $(LDADD) +main_DEPENDENCIES = am_map_OBJECTS = map.$(OBJEXT) map_OBJECTS = $(am_map_OBJECTS) map_LDADD = $(LDADD) @@ -106,12 +110,12 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(lda_SOURCES) $(map_SOURCES) \ - $(pio_SOURCES) $(rex01_SOURCES) $(sio_SOURCES) $(sll_SOURCES) \ - $(str_SOURCES) $(time_SOURCES) -DIST_SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(lda_SOURCES) \ +SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(lda_SOURCES) $(main_SOURCES) \ $(map_SOURCES) $(pio_SOURCES) $(rex01_SOURCES) $(sio_SOURCES) \ $(sll_SOURCES) $(str_SOURCES) $(time_SOURCES) +DIST_SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(lda_SOURCES) \ + $(main_SOURCES) $(map_SOURCES) $(pio_SOURCES) $(rex01_SOURCES) \ + $(sio_SOURCES) $(sll_SOURCES) $(str_SOURCES) $(time_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -265,6 +269,7 @@ fio_SOURCES = fio.c pio_SOURCES = pio.c sio_SOURCES = sio.c time_SOURCES = time.c +main_SOURCES = main.c rex01_SOURCES = rex01.c all: all-am @@ -352,6 +357,9 @@ fio$(EXEEXT): $(fio_OBJECTS) $(fio_DEPENDENCIES) lda$(EXEEXT): $(lda_OBJECTS) $(lda_DEPENDENCIES) @rm -f lda$(EXEEXT) $(LINK) $(lda_OBJECTS) $(lda_LDADD) $(LIBS) +main$(EXEEXT): $(main_OBJECTS) $(main_DEPENDENCIES) + @rm -f main$(EXEEXT) + $(LINK) $(main_OBJECTS) $(main_LDADD) $(LIBS) map$(EXEEXT): $(map_OBJECTS) $(map_DEPENDENCIES) @rm -f map$(EXEEXT) $(LINK) $(map_OBJECTS) $(map_LDADD) $(LIBS) @@ -383,6 +391,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rex01.Po@am__quote@ diff --git a/qse/samples/cmn/chr.c b/qse/samples/cmn/chr.c index 9d9c09f4..5dd4d6fe 100644 --- a/qse/samples/cmn/chr.c +++ b/qse/samples/cmn/chr.c @@ -37,7 +37,7 @@ static int test2 (void) for (i = 0; i < QSE_COUNTOF(x); i++) { - qse_size_t k = strlen(x[i]); + qse_size_t k = qse_mbslen(x[i]); qse_size_t j = 0; qse_wchar_t wc; @@ -102,7 +102,7 @@ static int test3 (void) for (i = 0; i < QSE_COUNTOF(x); i++) { - int len = wcslen (x[i]); + int len = qse_wcslen (x[i]); if (len == 0) len++; /* for x[0] */ qse_printf (QSE_T("[")); diff --git a/qse/samples/cmn/fio.c b/qse/samples/cmn/fio.c index ab0a79a7..3c66a3c1 100644 --- a/qse/samples/cmn/fio.c +++ b/qse/samples/cmn/fio.c @@ -32,7 +32,7 @@ static int test1 (void) return -1; } - n = qse_fio_write (fio, x, strlen(x)); + n = qse_fio_write (fio, x, qse_mbslen(x)); qse_printf (QSE_T("written %d bytes\n"), (int)n); @@ -77,7 +77,7 @@ static int test1 (void) qse_printf (QSE_T("moved file offset to %lld\n"), (long long)off); } - n = qse_fio_write (fio, x2, strlen(x2)); + n = qse_fio_write (fio, x2, qse_mbslen(x2)); qse_printf (QSE_T("written %d bytes\n"), (int)n); qse_fio_close (fio); @@ -110,7 +110,7 @@ static int test2 (void) for (i = 0; i < 2; i++) { - n = qse_fio_write (fio, x, strlen(x)); + n = qse_fio_write (fio, x, qse_mbslen(x)); qse_printf (QSE_T("written %d bytes\n"), (int)n); off = qse_fio_seek (fio, 0, QSE_FIO_CURRENT); @@ -156,7 +156,7 @@ static int test2 (void) qse_printf (QSE_T("moved file offset to %lld\n"), (long long)off); } - n = qse_fio_write (fio, x2, strlen(x2)); + n = qse_fio_write (fio, x2, qse_mbslen(x2)); qse_printf (QSE_T("written %d bytes\n"), (int)n); off = qse_fio_seek (fio, 0, QSE_FIO_CURRENT); @@ -174,7 +174,7 @@ static int test2 (void) qse_printf (QSE_T("failed to truncate the file\n")); } - n = qse_fio_write (fio, x2, strlen(x2)); + n = qse_fio_write (fio, x2, qse_mbslen(x2)); qse_printf (QSE_T("written %d bytes\n"), (int)n); off = qse_fio_seek (fio, 0, QSE_FIO_CURRENT); diff --git a/qse/samples/cmn/lda.c b/qse/samples/cmn/lda.c index 2be89079..8d36546d 100644 --- a/qse/samples/cmn/lda.c +++ b/qse/samples/cmn/lda.c @@ -2,6 +2,7 @@ #include #include #include +#include #define R(f) \ @@ -28,6 +29,13 @@ qse_lda_walk_t rwalker1 (qse_lda_t* lda, qse_size_t index, void* arg) return QSE_LDA_WALK_BACKWARD; } +qse_lda_walk_t walker3 (qse_lda_t* lda, qse_size_t index, void* arg) +{ + qse_printf (QSE_T("%d => [%d]\n"), + index, *(int*)QSE_LDA_DPTR(lda,index)); + return QSE_LDA_WALK_FORWARD; +} + static int test1 () { qse_lda_t* s1; @@ -102,6 +110,8 @@ static int test1 () qse_printf (QSE_T("lda size => %lu\n"), QSE_LDA_SIZE(s1)); qse_lda_rwalk (s1, rwalker1, QSE_NULL); +qse_lda_setcapa (s1, 3); + qse_lda_close (s1); return 0; } @@ -328,7 +338,7 @@ static int test4 () s1 = qse_lda_open (QSE_MMGR_GETDFL(), 0, 3); if (s1 == QSE_NULL) { - qse_printf (QSE_T("cannot open a string\n")); + qse_printf (QSE_T("cannot open an array\n")); return -1; } @@ -359,11 +369,92 @@ static int test4 () return 0; } + +qse_lda_comper_t default_comparator; + +static int inverse_comparator (qse_lda_t* lda, + const void* dptr1, size_t dlen1, + const void* dptr2, size_t dlen2) +{ + return -default_comparator (lda, dptr1, dlen1, dptr2, dlen2); +} + +static int test5 () +{ + qse_lda_t* s1; + int i, j; + + s1 = qse_lda_open (QSE_MMGR_GETDFL(), 0, 3); + if (s1 == QSE_NULL) + { + qse_printf (QSE_T("cannot open an array\n")); + return -1; + } + + qse_lda_setcopier (s1, QSE_LDA_COPIER_INLINE); + qse_lda_setscale (s1, QSE_SIZEOF(i)); + + /* inverse the comparator to implement min-heap */ + default_comparator = qse_lda_getcomper (s1); + qse_lda_setcomper (s1, inverse_comparator); + + for (i = 0; i < 25; i++) + { + j = random () % 100; + qse_lda_pushheap (s1, &j, 1); + } + + qse_printf (QSE_T("lda size => %lu\n"), QSE_LDA_SIZE(s1)); + qse_lda_walk (s1, walker3, QSE_NULL); + + while (QSE_LDA_SIZE(s1) > 10 ) + { + qse_printf (QSE_T("top => %d\n"), *(int*)QSE_LDA_DPTR(s1,0)); + qse_lda_popheap (s1); + } + + for (i = 0; i < 25; i++) + { + j = random () % 100; + qse_lda_pushheap (s1, &j, 1); + } + + qse_printf (QSE_T("lda size => %lu\n"), QSE_LDA_SIZE(s1)); + qse_lda_walk (s1, walker3, QSE_NULL); + + while (QSE_LDA_SIZE(s1)) + { + qse_printf (QSE_T("top => %d\n"), *(int*)QSE_LDA_DPTR(s1,0)); + qse_lda_popheap (s1); + } + + qse_lda_setcomper (s1, default_comparator); + for (i = 0; i < 25; i++) + { + j = random () % 100; + qse_lda_pushheap (s1, &j, 1); + } + + qse_printf (QSE_T("lda size => %lu\n"), QSE_LDA_SIZE(s1)); + qse_lda_walk (s1, walker3, QSE_NULL); + + while (QSE_LDA_SIZE(s1)) + { + qse_printf (QSE_T("top => %d\n"), *(int*)QSE_LDA_DPTR(s1,0)); + qse_lda_popheap (s1); + } + + + qse_lda_close (s1); + return 0; +} + int main () { R (test1); R (test2); R (test3); R (test4); + R (test5); return 0; } diff --git a/qse/samples/cmn/main.c b/qse/samples/cmn/main.c new file mode 100644 index 00000000..4ab2acbc --- /dev/null +++ b/qse/samples/cmn/main.c @@ -0,0 +1,20 @@ +#include +#include + +static int test_main (int argc, qse_char_t* argv[]) +{ + int i; + + for (i = 0; i < argc; i++) + { + qse_printf (QSE_T("%d => [%s]\n"), i, argv[i]); + } + + return 0; +} + +int qse_main (int argc, qse_achar_t* argv[]) +{ + return qse_runmain (argc, argv, test_main); +} + diff --git a/qse/samples/cmn/str.c b/qse/samples/cmn/str.c index 7dbf88aa..da185fef 100644 --- a/qse/samples/cmn/str.c +++ b/qse/samples/cmn/str.c @@ -168,7 +168,7 @@ static int test5 (void) for (i = 0; i < QSE_COUNTOF(x); i++) { - qse_size_t k = strlen(x[i]); + qse_size_t k = qse_mbslen(x[i]); qse_size_t j = 0; qse_wchar_t wc; qse_wchar_t buf[10];