水無瀬の部屋 > Programming > sample > tools > snprintf.cpp |
---|
1: //*********************************************************
2: // プロジェクト: TOOLS
3: // ファイル名: snprintf.cpp
4: //*********************************************************
5: #include <header/snprintf.h> // snprintf(), vsnprintf(),
6: #include <header/tooldbg.h> // ASSERT(),
7: #include <header/toolbase.h> //
8: //#include <stdio.h> // _vsnprintf(),
9:
10:
11: // デバッグ時のみ
12: #ifdef _DEBUG
13: #include <limits.h> // INT_MAX,
14: #endif // #ifdef _DEBUG
15:
16:
17: //---------------------------------------------------------
18: // テスト関数 の 宣言
19: //---------------------------------------------------------
20: DECLARE_TESTPROC( test_snprintf );
21:
22:
23: //*********************************************************
24: // _my_vsnprintf()
25: // 関数 vsprintf() の出力文字数制限機能付き版。
26: // 実際に buffer へ格納した 文字数 を返す。
27: // 最大で bufsize-1 文字 を格納する。
28: // 文字列終端文字 '\0' を付加する。
29: // ただし bufsize が 0 の場合は付加しない。
30: // 返却値の 文字数 に文字列終端文字 '\0' は含まれない。
31: // 格納されるはずの 文字数 が bufsize 以上の場合は 負数 を返す。
32: //
33: // char *buffer
34: // 出力先の記憶領域
35: //
36: // size_t bufsize
37: // 出力先領域のサイズを 文字数 で指定する。
38: //
39: // const char *fmt
40: // 出力書式文字列
41: // printf, sprintf, fprintf に同じ。
42: //
43: // va_list vp
44: // 可変個引数
45: //
46: //*********************************************************
47: int // 出力文字数
48: _my_vsnprintf
49: (
50: char *buffer, // 出力先の記憶領域
51: size_t bufsize, // 出力先領域の 要素数
52: const char *fmt, // 出力書式文字列
53: va_list vp // 可変個引数
54: )
55: {
56: CALLONCE_TESTPROC( test_snprintf ); // [テスト]
57:
58: // パラメタの仮定
59: ASSERT( (0 <= bufsize) && (bufsize < INT_MAX) );
60: ASSERT( IsValidStringBufferPtr( buffer, bufsize ) );
61: ASSERT( IsValidStringPtr( fmt ) );
62: DESTROY_TEXT_BUFFER( buffer, bufsize ); // [破壊]
63:
64: // '\0' すら格納できない!
65: if ( bufsize <= 0 )
66: {
67: return -1;
68: }
69:
70: // 書式を指定して文字列を出力する。
71: ASSERT( 0 < bufsize );
72: const int count = _vsnprintf( buffer, bufsize-1, fmt, vp );
73: ASSERT( (count < 0)
74: || ((0 <= count) && ((size_t)count < bufsize)) );
75: ASSERT( ((count < 0) || ((bufsize-1) == (size_t)count))
76: || ('\0' == buffer[ count ]) );
77:
78: // 文字列終端文字 '\0' を付加する。
79: if ( (0 < count) && ((size_t)count < bufsize) )
80: {
81: buffer[ count ] = '\0';
82: }
83: else
84: {
85: buffer[ bufsize - 1 ] = '\0';
86: }
87:
88: ASSERT( (count < 0)
89: || ((0 <= count) && (((size_t)count) < bufsize)) );
90: ASSERT( ((count < 0) && ('\0' == buffer[ bufsize-1 ]))
91: || ('\0' == buffer[ count ]) );
92: ASSERT( IsValidStringPtr( buffer ) );
93: return (0 <= count) ? count : -1;
94: }//_my_vsnprintf
95:
96: //*********************************************************
97: // _my_snprintf()
98: // 関数 sprintf() の出力文字数制限機能付き版。
99: // 実際に buffer へ格納した 文字数 を返す。
100: // 最大で bufsize-1 文字 を格納する。
101: // 文字列終端文字 '\0' を付加する。
102: // ただし bufsize が 0 の場合は付加しない。
103: // 返却値の 文字数 に文字列終端文字 '\0' は含まれない。
104: // 格納されるはずの 文字数 が bufsize 以上の場合は 負数 を返す。
105: //
106: // char *buffer
107: // 出力先の記憶領域
108: //
109: // size_t bufsize
110: // 出力先領域の 文字数
111: //
112: // const char *fmt
113: // 出力書式文字列
114: // printf, sprintf, fprintf に同じ。
115: //
116: // ...
117: // 可変個引数
118: //
119: //*********************************************************
120: int // 出力文字数
121: _my_snprintf
122: (
123: char *buffer, // 出力先の記憶領域
124: size_t bufsize, // 出力先領域の 文字数
125: const char *fmt, // 出力書式文字列
126: ... // 可変個引数
127: )
128: {
129: CALLONCE_TESTPROC( test_snprintf ); // [テスト]
130:
131: // パラメタの仮定
132: ASSERT( (0 <= bufsize) && (bufsize < INT_MAX) );
133: ASSERT( IsValidStringBufferPtr( buffer, bufsize ) );
134: ASSERT( IsValidStringPtr( fmt ) );
135: DESTROY_TEXT_BUFFER( buffer, bufsize ); // [破壊]
136:
137: // '\0' すら格納できない!
138: if ( bufsize <= 0 )
139: {
140: return -1;
141: }
142:
143: // 書式を指定して文字列を出力する。
144: va_list vp;
145: va_start( vp, fmt );
146: const int count = _my_vsnprintf( buffer, bufsize, fmt, vp );
147: va_end( vp );
148:
149: ASSERT( (-1 == count) || ((0 <= count) && ((((size_t)count) < bufsize))) );
150: ASSERT( ((count < 0) && ('\0' == buffer[ bufsize-1 ]))
151: || ('\0' == buffer[ count ]) );
152: ASSERT( IsValidStringPtr( buffer ) );
153: return (0 <= count) ? count : -1;
154: }//_my_snprintf
155:
156:
157: //******************************************************************************************************************
158: // TEST
159: //******************************************************************************************************************
160:
161:
162: #ifdef _DEBUG // デバッグ時のみ
163:
164:
165: //*********************************************************
166: // test_snprintf
167: //*********************************************************
168: DEFINE_TESTPROC( test_snprintf )
169: {
170: //---------------------------------------------------------
171: // 定数 の テスト
172: //---------------------------------------------------------
173:
174: //---------------------------------------------------------
175: // ファイルスコープ関数 の テスト
176: //---------------------------------------------------------
177:
178: //---------------------------------------------------------
179: // 公開関数 の テスト
180: //---------------------------------------------------------
181:
182: const struct
183: {
184: int count;
185: const char *string;
186: size_t bufsize;
187: const char *result;
188: }
189: testcase[] =
190: {
191: #define MAKE_TESTCASE( count, string, bufsize, result ) { count, string, bufsize, result }
192: MAKE_TESTCASE( -1, "", 0, "" ),
193: MAKE_TESTCASE( 0, "", 1, "" ),
194: MAKE_TESTCASE( 0, "", 2, "" ),
195: MAKE_TESTCASE( -1, "-", 0, "" ),
196: MAKE_TESTCASE( -1, "-", 1, "" ),
197: MAKE_TESTCASE( 1, "-", 2, "-" ),
198: MAKE_TESTCASE( 1, "-", 3, "-" ),
199: MAKE_TESTCASE( -1, "--", 0, "" ),
200: MAKE_TESTCASE( -1, "--", 1, "" ),
201: MAKE_TESTCASE( -1, "--", 2, "-" ),
202: MAKE_TESTCASE( 2, "--", 3, "--" ),
203: MAKE_TESTCASE( 2, "--", 4, "--" ),
204: #undef MAKE_TESTCASE
205: };
206: {for( int i = 0; i < numof( testcase ); ++i )
207: {
208: char buffer[ 1024 ];
209: const int count = _my_snprintf( buffer, testcase[ i ].bufsize, "%s", testcase[ i ].string );
210: VERIFY( count == testcase[ i ].count );
211: VERIFY( (0 == testcase[ i ].bufsize)
212: || streql( buffer, testcase[ i ].result ) );
213: }}
214:
215: }//test_snprintf
216:
217:
218: #endif // #ifdef _DEBUG
219:
220:
221: //** end **
222:
参照:
水無瀬の部屋 > sample > tools > snprintf.cpp |
---|
このページは cpp2web が出力しました。
水無瀬 優 postmaster@katsura-kotonoha.sakura.ne.jp
http://katsura-kotonoha.sakura.ne.jp/prog/code/tools/snprintf_cpp.shtml