/* vim: ts=4 sw=4 sts=4 ff=unix fenc=utf-8 : * ===================================================================== * sc_string.c * Copyright (c) 2003 - 2011 sys0tem * LICENSE : * LGPL (GNU Lesser General Public License - Version 3,29 June 2007) * http://www.gnu.org/copyleft/lesser.html * or * EPL (Eclipse Public License - v1.0) * http://www.eclipse.org/legal/epl-v10.html * ===================================================================== */ #include <sc_os.h> #if (SC_isWindows) /* Windows の場合 */ #include <malloc.h> #else /* Windows 以外は大抵 alloca.h に alloca がある */ #include <alloca.h> #endif /* if (isWindows) */ #include <sc_mmgr.h> #include <sc_string.h> /* --------------------------------------------------------------------- * プロトタイプ宣言 * --------------------------------------------------------------------- */ static bool SC_String_append(SC_String* str, const char* addstr); static void SC_String_setLength(SC_String* str, size_t len); static bool SC_String_isEmpty(SC_String* str); static void SC_String_clear(SC_String* str); /** * 指定された文字列 s の長さを返します。 * 最大で max までの長さを返します。 * * @param s 文字列 * @param max 最大の長さ * @return 文字列の長さ */ size_t SC_strnlen(const char* s, size_t max) { size_t count = 0; for (; count < max; count++) { if (s[count] == '\0') { break; } } return count; } /** * 指定された文字列 s の複製を作成し、 * 新しい文字列へのポインタを返します。 * 最大で n 文字だけ複製します。 * メモリ確保に失敗した場合、NULL を返します。 * * @param s 文字列 * @param n 複製する最大文字数 * @param file ソースファイル * @param line 行番号 * @return 複製された文字列 */ char* SC_strndup(const char* s, size_t n, const char* file, int line) { size_t len; char* newStr; if (s == NULL) { return NULL; } len = strnlen(s, n); if (file == NULL) { newStr = (char*) SC_realMalloc(len + 1); } else { newStr = (char*) SC_malloc(len + 1, file, line); } if (newStr == NULL) { /* メモリ確保失敗 */ return NULL; } newStr[len] = '\0'; return (char*) memcpy(newStr, s, len); } /** * 指定された文字列 s の複製を作成し、 * 新しい文字列へのポインタを返します。 * 最大で n 文字だけ複製します。 * メモリ確保に失敗した場合、NULL を返します。 * 本関数はメモリ確保に alloca を使用します。 * * @param s 文字列 * @param n 複製する最大文字数 * @param file ソースファイル * @param line 行番号 * @return 複製された文字列 */ char* SC_strndupa(const char* s, size_t n) { size_t len; char* newStr; if (s == NULL) { return NULL; } len = strnlen(s, n); newStr = (char*) alloca(len + 1); if (newStr == NULL) { /* メモリ確保失敗 */ return NULL; } newStr[len] = '\0'; return (char*) memcpy(newStr, s, len); } /** * 指定された target より、search に指定されたデータを検索し、 * 見つかった位置のポインタを返します。 * 見つからない場合 NULL を返します。 * 検索対象が NULL の場合、NULL を返します。 * 検索データが NULL の場合、target の先頭を返します。 * * @param target 検索対象 * @param tSize 検索対象サイズ * @param search 検索データ * @param sSize 検索データサイズ * @return 検索位置のポインタ */ const char* SC_memindex(const char* target, size_t tSize, const char* search, size_t sSize) { int i; int ret; if (target == NULL) { /* 検索対象が NULL なら NULL を返します。 */ return NULL; } if (search == NULL) { /* 検索データが NULL なら target の先頭を返す */ return target; } for (i = (sSize - 1); i < tSize; i++) { if (target[i] == search[sSize - 1]) { ret = memcmp(&target[i - sSize + 1], search, sSize); if (ret == 0) { return &(target[i - sSize + 1]); } } } return NULL; } /** * 文字列 str より、文字列 search がある位置を返します。 * 見つからない場合は -1 を返します。 * * @param str 文字列 * @param search 検索文字 * @return true/false (空文字/空文字でない) */ int SC_indexOf(const char* str, const char* search) { char* posPtr = strstr(str, search); if (posPtr == NULL) { /* 見つからない */ return -1; } /* 見つかったので位置を返す */ return (posPtr - str); } /** * 文字列 str より、文字列 search を末尾から検索し、 * インデックスを返します。 * 見つからない場合は -1 を返します。 * * @param str 文字列 * @param search 検索文字 * @return true/false (空文字/空文字でない) */ int SC_lastIndexOf(const char* str, const char* search) { int i; int check; int len = strlen(str); int searchLen = strlen(search); if (searchLen == 0) { return -1; } for (i = (len - searchLen); i >= 0; i--) { if (str[i] == search[0]) { check = strncmp(&str[i], search, searchLen); if (check == 0) { return i; } } } return -1; } /** * SC_String を生成します。 * * @param bufSize 初期バッファサイズ * @return SC_String */ SC_String* SC_String_new(size_t bufSize) { SC_String* str = (SC_String*) malloc(sizeof(SC_String)); if (str == NULL) { /* メモリ確保失敗 */ return NULL; } str->buffer = (char*) malloc(bufSize); if (str->buffer == NULL) { /* メモリ確保失敗 */ free(str); return NULL; } str->_useSize = 0; str->_bufSize = bufSize; memset(str->buffer, '\0', str->_bufSize); str->append = SC_String_append; str->setLength = SC_String_setLength; str->isEmpty = SC_String_isEmpty; str->clear = SC_String_clear; return str; } /** * SC_String を破棄します。 * * @param str 破棄する SC_String */ void SC_String_delete(SC_String* str) { free(str->buffer); free(str); } /** * 指定された文字列を追加します。 * * @param str 文字列 * @param addstr 追加する文字列 * @param true/false (追加成功/追加失敗) */ static bool SC_String_append(SC_String* str, const char* addstr) { size_t len = strlen(addstr) + 1; size_t totalLen = str->_useSize + len; char* tmpBuff; if (str->_bufSize < totalLen) { /* バッファ拡張 */ tmpBuff = (char*) realloc(str->buffer, (totalLen << 1)); if (tmpBuff == NULL) { /* メモリ確保失敗 */ return false; } str->buffer = tmpBuff; str->_bufSize = (totalLen << 1); } strcat(str->buffer, addstr); str->_useSize = totalLen - 1; return true; } /** * 文字列の長さを len に切り詰めます。 * 文字列の長さが len 以下の場合は、なにもしません。 * * @param str 文字列 * @param len 切り詰める長さ */ static void SC_String_setLength(SC_String* str, size_t len) { if (len < str->_useSize) { str->buffer[len] = '\0'; str->_useSize = len; } } /** * 文字列が空文字かどうかを返します。 * * @param str 文字列 * @return true/false (空文字/空文字でない) */ static bool SC_String_isEmpty(SC_String* str) { if (str->_useSize == 0) { return true; } return false; } /** * 文字列をクリアします。 * 確保済みのメモリは開放しません。 * 確保済みのメモリも開放する場合は、SC_String_delete * を使用してください。 * * @param str 文字列 */ static void SC_String_clear(SC_String* str) { *(str->buffer) = '\0'; str->_useSize = 0; }