#include "safe_stdio.h" #include /** * @file safe_stdio.c * @brief 安全な標準ファイル入出力用の関数のコード */ /** * @brief 1つの文字列をスキャンし,デリミタで要素へ分割するための情報を取得 * @param str スキャン対象の文字列 * @param delim デリミタ(文字セット) * @param begin 各要素文字列の先頭位置 (返り値) * @param length 各要素文字列の長さ (返り値) * @param max_n begin[], length[] のサイズ * @return 要素の個数 */ size_t sscan_str( const char *str, const char *delim, size_t begin[], size_t length[], size_t max_n ) { size_t ix = 0; /* 文字列のパース位置 */ size_t n_elem = 0; /* 要素の個数 */ size_t spn; /* 最初のデリミタを飛ばす */ spn = strspn(str + ix, delim); ix += spn; while ( n_elem < max_n ) { /* 要素部分 */ spn = strcspn(str + ix, delim); if ( spn == 0 ) break; /* 配列に登録 */ begin[n_elem] = ix; length[n_elem] = spn; n_elem ++; ix += spn; /* デリミタを飛ばす */ spn = strspn(str + ix, delim); if ( spn == 0 ) break; ix += spn; } return n_elem; } /** * @brief ファイルから必ず1行を読みとる.バッファサイズ以上の部分は捨てられる * @param fp ファイルハンドラ * @param str 1行分を保存するバッファ * @param size_str str[]のバッファサイズ * @return 成功した場合は str を返す
* EOFまたはエラーの場合 NULL */ char *fget_str( FILE *fp, char *str, size_t size_str ) { char *ret; ret = fgets(str, size_str, fp); if ( ret != NULL ) { size_t length = strlen(str); /* バッファが足りない場合,読み飛ばす */ if ( 0 < length && str[length-1] != '\n' ) { char junk[256]; char *r; while ( (r=fgets(junk,256,fp)) != NULL ) { size_t len = strlen(junk); if ( len == 0 ) break; length += len; if ( junk[len-1] == '\n' ) break; } fprintf(stderr,"[WARNING] %s: truncated: total length = %zu\n", __FUNCTION__, length); } } return ret; } /** * @brief ファイルから1行を読みとり,デリミタで要素へ分割するための情報を取得 * @param fp ファイルハンドラ * @param str 1行分を保存するバッファ * @param size_str str[]のバッファサイズ * @param delim デリミタ(文字セット) * @param begin 各要素文字列の先頭位置 (返り値) * @param length 各要素文字列の長さ (返り値) * @param max_n begin[], length[] のサイズ * @return 成功した場合,要素の個数
* EOFの場合,負値 */ ssize_t fscan_str( FILE *fp, char str[], size_t size_str, const char *delim, size_t begin[], size_t length[], size_t max_n ) { ssize_t ret = -1; char *s; s = fget_str(fp,str,size_str); if ( s != NULL ) { size_t len = strlen(str); if ( 0 < len && str[len - 1] == '\n' ) str[len - 1] = '\0'; ret = sscan_str( str, delim, begin, length, max_n ); } return ret; }