• R/O
  • SSH
  • HTTPS

cadencii: コミット


コミットメタ情報

リビジョン1914 (tree)
日時2012-01-07 19:45:08
作者kbinani

ログメッセージ

[vConnect/trunk/stand2.0] modified: TextReader, TextWriter, EncodingConverter; 改行コードをCRLFに変更

変更サマリ

差分

--- vConnect/trunk/stand2.0/stand/TextReader.h (revision 1913)
+++ vConnect/trunk/stand2.0/stand/TextReader.h (revision 1914)
@@ -1,272 +1,272 @@
1-/*
2- * TextReader.h
3- * Copyright © 2012 kbinani
4- *
5- * This file is part of vConnect-STAND.
6- *
7- * vConnect-STAND is free software; you can redistribute it and/or
8- * modify it under the terms of the GPL License.
9- *
10- * vConnect-STAND is distributed in the hope that it will be useful,
11- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13- */
14-#ifndef __TextReader_h__
15-#define __TextReader_h__
16-
17-#include <stdio.h>
18-#include "EncodingConverter.h"
19-
20-namespace vconnect
21-{
22- /**
23- * テキストファイルを読み込むためのクラス
24- * @todo 1 行が BUFFER_SIZE を超えるテキストを読む場合動作がデタラメ
25- */
26- class TextReader
27- {
28- private:
29- /**
30- * 1行の最大文字数
31- */
32- static const int BUFFER_SIZE = 1024;
33-
34- /**
35- * テキストエンコーディングのコンバータ
36- */
37- EncodingConverter *converter;
38-
39- /**
40- * ファイルハンドル
41- */
42- FILE *fileHandle;
43-
44- /**
45- * 指定されたエンコーディングの読み込み単位バイト数
46- * たとえば UTF8 なら 1 バイト、UTF16 なら 2 バイト単位で読み込む
47- */
48- int bytesPerWord;
49-
50- /**
51- * bytesPerWord バイト分のバッファー
52- */
53- char *unitBuffer;
54-
55- /**
56- * ファイルからデータを読み込むときに使うバッファー
57- */
58- char *buffer;
59-
60- public:
61- /**
62- * テキストエンコーディングを指定して、テキストファイルを開く
63- * @param path 開くファイルのパス
64- * @param encoding テキストエンコーディング
65- */
66- TextReader( string path, string encoding )
67- {
68- this->converter = new EncodingConverter( encoding, EncodingConverter::getInternalEncoding() );
69- this->fileHandle = fopen( path.c_str(), "rb" );
70- this->bytesPerWord = EncodingConverter::getBytesPerWord( encoding );
71- this->unitBuffer = new char[this->bytesPerWord];
72-
73- int bufferBytes = this->bytesPerWord * BUFFER_SIZE;
74- this->buffer = new char[bufferBytes];
75- }
76-
77- /**
78- * デストラクタ
79- */
80- ~TextReader()
81- {
82- this->close();
83- }
84-
85- /**
86- * テキストファイルから 1 行読み込む
87- * @return 行データ
88- */
89- string readLine()
90- {
91- FILE *fp = this->fileHandle;
92- int unit_buflen = this->bytesPerWord;
93- int unit_bufbytes = sizeof( char ) * unit_buflen;
94- int i;
95- int bufbytes = this->bytesPerWord * BUFFER_SIZE;
96-
97- string result = "";
98- bool isEndOfLine = false;
99- while( false == isEndOfLine ){
100- memset( this->buffer, 0, bufbytes );
101- int offset = -unit_buflen;
102- for( i = 0; i < bufbytes - 1; i++ ){
103- // このループ中でbuf[offset]からbuf[offset+buflen]までを埋めます
104- offset += unit_buflen;
105- int j;
106-
107- // 1文字分読み込む
108- int len = fillUnitBuffer( this->unitBuffer, unit_buflen, fp );
109-
110- if( len != unit_buflen ){
111- // EOFまで読んだ場合
112- for( j = 0; j < unit_buflen; j++ ){
113- this->buffer[j + offset] = '\0';
114- }
115- isEndOfLine = true;
116- break;
117- }else if( isCR( this->unitBuffer, unit_buflen ) ){
118- // 読んだのがCRだった場合
119- // 次の文字がLFかどうかを調べる
120- len = fillUnitBuffer( this->unitBuffer, unit_buflen, fp );
121- if( len == unit_buflen ){
122- if( isLF( this->unitBuffer, unit_buflen ) ){
123- // LFのようだ
124- }else{
125- // LFでないので、ファイルポインタを戻す
126- fseek( fp, -unit_bufbytes, SEEK_CUR );
127- }
128- }
129- isEndOfLine = true;
130- break;
131- }else if( isLF( this->unitBuffer, unit_buflen ) ){
132- // 読んだのがLFだった場合
133- // 次の文字がCRかどうかを調べる
134- len = fillUnitBuffer( this->unitBuffer, unit_buflen, fp );
135- if( len == unit_buflen ){
136- if( isCR( this->unitBuffer, unit_buflen ) ){
137- // CRのようだ
138- // LF-CRという改行方法があるかどうかは知らないけれどサポートしとこう
139- }else{
140- // CRでないので、ファイルポインタを戻す
141- fseek( fp, -unit_bufbytes, SEEK_CUR );
142- }
143- }
144- isEndOfLine = true;
145- break;
146- }else{
147- // 通常の処理
148- for( j = 0; j < unit_buflen; j++ ){
149- this->buffer[offset + j] = this->unitBuffer[j];
150- }
151- }
152- }
153-
154- string source = this->buffer;
155- result += this->converter->convert( source );
156- }
157-
158- return result;
159- }
160-
161- /**
162- * ファイル読み込みがファイル末尾に達したかどうか
163- * @return ファイル末尾に達している場合 true を、そうでなければ false を返す。
164- */
165- bool isEOF()
166- {
167- return feof( this->fileHandle ) ? true : false;
168- }
169-
170- /**
171- * ファイルを閉じる
172- */
173- void close()
174- {
175- fclose( this->fileHandle );
176- delete this->converter;
177- delete [] this->unitBuffer;
178- delete [] this->buffer;
179- }
180-
181- private:
182- TextReader()
183- {
184- }
185-
186- /**
187- * マルチバイトの一文字分のデータをファイルから読み込む
188- * @param buffer 読み込んだデータの格納先
189- * @param length buffer のバイト数
190- * @param fileHandle 読み込み対象のファイル
191- * @return 読み込んだデータのバイト数
192- */
193- static int fillUnitBuffer( char *buffer, int length, FILE *fileHandle )
194- {
195- int ret = 0;
196- memset( buffer, 0, length * sizeof( char ) );
197- for( int i = 0; i < length; i++ ){
198- int c = fgetc( fileHandle );
199- if( c == EOF ){
200- return ret;
201- }
202- buffer[i] = (char)c;
203- ret++;
204- }
205- return ret;
206- }
207-
208- /**
209- * 指定したマルチバイトの一文字が、指定した制御文字を表すかどうかを調べる
210- * @param buffer マルチバイトの一文字
211- * @param length buffer のバイト数
212- * @param expected 期待値
213- * @return 一致したら ture を、そうでなければ false を返す
214- */
215- static bool isExpectedCode( char *buffer, int length, char expected )
216- {
217- if( length < 1 ){
218- return false;
219- }
220- int i;
221-
222- // LEを仮定
223- if( buffer[0] == expected ){
224- for( i = 1; i < length; i++ ){
225- if( buffer[i] != 0x00 ){
226- return false;
227- }
228- }
229- return true;
230- }
231-
232- // BEを仮定
233- if( buffer[length - 1] == expected ){
234- for( i = 0; i < length - 1; i++ ){
235- if( buffer[i] != 0x00 ){
236- return false;
237- }
238- }
239- return true;
240- }
241-
242- return false;
243- }
244-
245- /**
246- * マルチバイト文字列が、改行制御文字(キャリッジリターン, CR)を表すかどうかを調べます
247- * @param buf 調査対象のマルチバイト文字列のバッファ
248- * @param len バッファbufの長さ
249- * @param check_char チェックする制御文字コード
250- * @return バッファの文字列がLFを表すならtrue、そうでなければfalse
251- */
252- static bool isCR( char *buffer, int length )
253- {
254- return isExpectedCode( buffer, length, 0x0D );
255- }
256-
257- /**
258- * マルチバイト文字列が、改行制御文字(ラインフィード, LF)を表すかどうかを調べます
259- * @param buf 調査対象のマルチバイト文字列のバッファ
260- * @param len バッファbufの長さ
261- * @param check_char チェックする制御文字コード
262- * @return バッファの文字列がLFを表すならtrue、そうでなければfalse
263- */
264- static bool isLF( char *buffer, int length )
265- {
266- return isExpectedCode( buffer, length, 0x0A );
267- }
268- };
269-}
270-
271-#endif
272-
1+/*
2+ * TextReader.h
3+ * Copyright © 2012 kbinani
4+ *
5+ * This file is part of vConnect-STAND.
6+ *
7+ * vConnect-STAND is free software; you can redistribute it and/or
8+ * modify it under the terms of the GPL License.
9+ *
10+ * vConnect-STAND is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13+ */
14+#ifndef __TextReader_h__
15+#define __TextReader_h__
16+
17+#include <stdio.h>
18+#include "EncodingConverter.h"
19+
20+namespace vconnect
21+{
22+ /**
23+ * テキストファイルを読み込むためのクラス
24+ * @todo 1 行が BUFFER_SIZE を超えるテキストを読む場合動作がデタラメ
25+ */
26+ class TextReader
27+ {
28+ private:
29+ /**
30+ * 1行の最大文字数
31+ */
32+ static const int BUFFER_SIZE = 1024;
33+
34+ /**
35+ * テキストエンコーディングのコンバータ
36+ */
37+ EncodingConverter *converter;
38+
39+ /**
40+ * ファイルハンドル
41+ */
42+ FILE *fileHandle;
43+
44+ /**
45+ * 指定されたエンコーディングの読み込み単位バイト数
46+ * たとえば UTF8 なら 1 バイト、UTF16 なら 2 バイト単位で読み込む
47+ */
48+ int bytesPerWord;
49+
50+ /**
51+ * bytesPerWord バイト分のバッファー
52+ */
53+ char *unitBuffer;
54+
55+ /**
56+ * ファイルからデータを読み込むときに使うバッファー
57+ */
58+ char *buffer;
59+
60+ public:
61+ /**
62+ * テキストエンコーディングを指定して、テキストファイルを開く
63+ * @param path 開くファイルのパス
64+ * @param encoding テキストエンコーディング
65+ */
66+ TextReader( string path, string encoding )
67+ {
68+ this->converter = new EncodingConverter( encoding, EncodingConverter::getInternalEncoding() );
69+ this->fileHandle = fopen( path.c_str(), "rb" );
70+ this->bytesPerWord = EncodingConverter::getBytesPerWord( encoding );
71+ this->unitBuffer = new char[this->bytesPerWord];
72+
73+ int bufferBytes = this->bytesPerWord * BUFFER_SIZE;
74+ this->buffer = new char[bufferBytes];
75+ }
76+
77+ /**
78+ * デストラクタ
79+ */
80+ ~TextReader()
81+ {
82+ this->close();
83+ }
84+
85+ /**
86+ * テキストファイルから 1 行読み込む
87+ * @return 行データ
88+ */
89+ string readLine()
90+ {
91+ FILE *fp = this->fileHandle;
92+ int unit_buflen = this->bytesPerWord;
93+ int unit_bufbytes = sizeof( char ) * unit_buflen;
94+ int i;
95+ int bufbytes = this->bytesPerWord * BUFFER_SIZE;
96+
97+ string result = "";
98+ bool isEndOfLine = false;
99+ while( false == isEndOfLine ){
100+ memset( this->buffer, 0, bufbytes );
101+ int offset = -unit_buflen;
102+ for( i = 0; i < bufbytes - 1; i++ ){
103+ // このループ中でbuf[offset]からbuf[offset+buflen]までを埋めます
104+ offset += unit_buflen;
105+ int j;
106+
107+ // 1文字分読み込む
108+ int len = fillUnitBuffer( this->unitBuffer, unit_buflen, fp );
109+
110+ if( len != unit_buflen ){
111+ // EOFまで読んだ場合
112+ for( j = 0; j < unit_buflen; j++ ){
113+ this->buffer[j + offset] = '\0';
114+ }
115+ isEndOfLine = true;
116+ break;
117+ }else if( isCR( this->unitBuffer, unit_buflen ) ){
118+ // 読んだのがCRだった場合
119+ // 次の文字がLFかどうかを調べる
120+ len = fillUnitBuffer( this->unitBuffer, unit_buflen, fp );
121+ if( len == unit_buflen ){
122+ if( isLF( this->unitBuffer, unit_buflen ) ){
123+ // LFのようだ
124+ }else{
125+ // LFでないので、ファイルポインタを戻す
126+ fseek( fp, -unit_bufbytes, SEEK_CUR );
127+ }
128+ }
129+ isEndOfLine = true;
130+ break;
131+ }else if( isLF( this->unitBuffer, unit_buflen ) ){
132+ // 読んだのがLFだった場合
133+ // 次の文字がCRかどうかを調べる
134+ len = fillUnitBuffer( this->unitBuffer, unit_buflen, fp );
135+ if( len == unit_buflen ){
136+ if( isCR( this->unitBuffer, unit_buflen ) ){
137+ // CRのようだ
138+ // LF-CRという改行方法があるかどうかは知らないけれどサポートしとこう
139+ }else{
140+ // CRでないので、ファイルポインタを戻す
141+ fseek( fp, -unit_bufbytes, SEEK_CUR );
142+ }
143+ }
144+ isEndOfLine = true;
145+ break;
146+ }else{
147+ // 通常の処理
148+ for( j = 0; j < unit_buflen; j++ ){
149+ this->buffer[offset + j] = this->unitBuffer[j];
150+ }
151+ }
152+ }
153+
154+ string source = this->buffer;
155+ result += this->converter->convert( source );
156+ }
157+
158+ return result;
159+ }
160+
161+ /**
162+ * ファイル読み込みがファイル末尾に達したかどうか
163+ * @return ファイル末尾に達している場合 true を、そうでなければ false を返す。
164+ */
165+ bool isEOF()
166+ {
167+ return feof( this->fileHandle ) ? true : false;
168+ }
169+
170+ /**
171+ * ファイルを閉じる
172+ */
173+ void close()
174+ {
175+ fclose( this->fileHandle );
176+ delete this->converter;
177+ delete [] this->unitBuffer;
178+ delete [] this->buffer;
179+ }
180+
181+ private:
182+ TextReader()
183+ {
184+ }
185+
186+ /**
187+ * マルチバイトの一文字分のデータをファイルから読み込む
188+ * @param buffer 読み込んだデータの格納先
189+ * @param length buffer のバイト数
190+ * @param fileHandle 読み込み対象のファイル
191+ * @return 読み込んだデータのバイト数
192+ */
193+ static int fillUnitBuffer( char *buffer, int length, FILE *fileHandle )
194+ {
195+ int ret = 0;
196+ memset( buffer, 0, length * sizeof( char ) );
197+ for( int i = 0; i < length; i++ ){
198+ int c = fgetc( fileHandle );
199+ if( c == EOF ){
200+ return ret;
201+ }
202+ buffer[i] = (char)c;
203+ ret++;
204+ }
205+ return ret;
206+ }
207+
208+ /**
209+ * 指定したマルチバイトの一文字が、指定した制御文字を表すかどうかを調べる
210+ * @param buffer マルチバイトの一文字
211+ * @param length buffer のバイト数
212+ * @param expected 期待値
213+ * @return 一致したら ture を、そうでなければ false を返す
214+ */
215+ static bool isExpectedCode( char *buffer, int length, char expected )
216+ {
217+ if( length < 1 ){
218+ return false;
219+ }
220+ int i;
221+
222+ // LEを仮定
223+ if( buffer[0] == expected ){
224+ for( i = 1; i < length; i++ ){
225+ if( buffer[i] != 0x00 ){
226+ return false;
227+ }
228+ }
229+ return true;
230+ }
231+
232+ // BEを仮定
233+ if( buffer[length - 1] == expected ){
234+ for( i = 0; i < length - 1; i++ ){
235+ if( buffer[i] != 0x00 ){
236+ return false;
237+ }
238+ }
239+ return true;
240+ }
241+
242+ return false;
243+ }
244+
245+ /**
246+ * マルチバイト文字列が、改行制御文字(キャリッジリターン, CR)を表すかどうかを調べます
247+ * @param buf 調査対象のマルチバイト文字列のバッファ
248+ * @param len バッファbufの長さ
249+ * @param check_char チェックする制御文字コード
250+ * @return バッファの文字列がLFを表すならtrue、そうでなければfalse
251+ */
252+ static bool isCR( char *buffer, int length )
253+ {
254+ return isExpectedCode( buffer, length, 0x0D );
255+ }
256+
257+ /**
258+ * マルチバイト文字列が、改行制御文字(ラインフィード, LF)を表すかどうかを調べます
259+ * @param buf 調査対象のマルチバイト文字列のバッファ
260+ * @param len バッファbufの長さ
261+ * @param check_char チェックする制御文字コード
262+ * @return バッファの文字列がLFを表すならtrue、そうでなければfalse
263+ */
264+ static bool isLF( char *buffer, int length )
265+ {
266+ return isExpectedCode( buffer, length, 0x0A );
267+ }
268+ };
269+}
270+
271+#endif
272+
--- vConnect/trunk/stand2.0/stand/EncodingConverter.h (revision 1913)
+++ vConnect/trunk/stand2.0/stand/EncodingConverter.h (revision 1914)
@@ -1,323 +1,324 @@
1-#ifndef __EncodingConverter_h__
2-#define __EncodingConverter_h__
3-
4-#include <iconv.h>
5-
6-using namespace std;
7-
8-namespace vconnect
9-{
10- /**
11- * マルチバイト文字列のテキストエンコーディングを変換するためのコンバータ
12- */
13- class EncodingConverter
14- {
15- private:
16- /**
17- * システム内部のマルチバイト文字列が使用しているテキストエンコーディング名
18- */
19- string internalEncoding;
20-
21- /**
22- * libiconv のコンバータ
23- */
24- iconv_t converter;
25-
26- public:
27- /**
28- * 変換元と変換先のエンコーディングを指定し、コンバータを初期化する
29- * @param from 変換前のエンコーディング名
30- * @param to 変換後のエンコーディング名
31- */
32- EncodingConverter( string from, string to )
33- {
34- this->converter = iconv_open( to.c_str(), from.c_str() );
35- this->internalEncoding = getInternalEncoding();
36- }
37-
38- ~EncodingConverter()
39- {
40- iconv_close( this->converter );
41- }
42-
43- /**
44- * 文字列のテキストエンコーディングを変換する
45- * @param source 変換する文字列
46- * @return エンコーディングを変換した文字列
47- */
48- string convert( string source )
49- {
50- string result;
51- char *input = const_cast<char *>( source.c_str() );
52- size_t remainingInputBytes = source.size();
53-
54- char *buffer = new char[remainingInputBytes + 1];
55- char *output = buffer;
56- size_t remainingOutputBytes = remainingInputBytes;
57- size_t outputBytes = remainingInputBytes;
58-
59- while( remainingInputBytes > 0 ){
60- char *originalInput = input;
61- size_t n = iconv( this->converter, &input, &remainingInputBytes, &output, &remainingOutputBytes );
62- if( (n != (size_t) - 1 && remainingInputBytes == 0) || (errno == EINVAL) ){
63- remainingInputBytes = 0;
64- result.append( buffer, 0, outputBytes - remainingOutputBytes );
65- }else{
66- switch( errno ){
67- case E2BIG:{
68- result.append( buffer, 0, outputBytes - remainingOutputBytes );
69- output = buffer;
70- remainingOutputBytes = outputBytes;
71- break;
72- }
73- case EILSEQ:{
74- result.append( buffer, 0, outputBytes - remainingOutputBytes );
75- result.append( input, 0, 1 );
76- input++;
77- remainingInputBytes--;
78- output = buffer;
79- remainingOutputBytes = outputBytes;
80- break;
81- }
82- default:{
83- result.append( originalInput );
84- remainingInputBytes = 0;
85- break;
86- }
87- }
88- }
89- }
90- output = buffer;
91- remainingOutputBytes = outputBytes;
92- if( iconv( this->converter , NULL, NULL, &output, &remainingOutputBytes ) != (size_t) - 1 ){
93- result.append( buffer, 0, outputBytes - remainingOutputBytes );
94- }
95- delete [] buffer;
96- return result;
97- }
98-
99- /**
100- * char の内部のエンコーディングを調べる
101- * @return
102- */
103- static string getInternalEncoding()
104- {
105- unsigned int result = 0;
106- char *localeNameRaw = std::setlocale( LC_CTYPE, "" );
107-#ifdef __APPLE__
108- // Macは決め打ち
109- result = 1208;
110-#else
111- if( NULL != localeNameRaw ){
112- // localeName = "ja_JP.UTF-8" (openSUSE, g++)
113- // localeName = "Japanese_Japan.932" (Windows XP, g++)
114- string localeName = localeNameRaw;
115- int index = localeName.rfind( "." );
116- if( index != string::npos ){
117- string encodingName = localeName.substr( index + 1 );
118- // snum部分が数値に変換できるかどうかを調べる
119- if( encodingName.size() == 0 ){
120- result = 1208;
121- }else{
122- bool allnum = true;
123- for( int i = 0; i < encodingName.size(); i++ ){
124- char c = encodingName[i];
125- if( isdigit( c ) == 0 ){
126- allnum = false;
127- break;
128- }
129- }
130- if( allnum ){
131- int encodingNumber = atoi( encodingName.c_str() );
132- result = encodingNumber;
133- }else{
134- result = 1208;
135- }
136- }
137- }else{
138- result = 1208;
139- }
140- }else{
141- result = 1208;
142- }
143-#endif
144- return getCharsetFromCodepage( result );
145- }
146-
147- /**
148- * コードページの名称から、読込み時の読込単位(バイト)を調べます
149- * @return テキストファイルからの読み込み単位
150- */
151- static int getBytesPerWord( string encoding ){
152- encoding = toLower( encoding );
153- if( encoding.compare( "shift_jis" ) == 0 ){
154- return 1;
155- }else if( encoding.compare( "euc-jp" ) == 0 ){
156- return 1;
157- }else if( encoding.compare( "iso-2022-jp" ) == 0 ){
158- return 1;
159- }else if( encoding.compare( "utf-8" ) == 0 ){
160- return 1;
161- }else if( encoding.compare( "utf-16le" ) == 0 ){
162- return 2;
163- }else if( encoding.compare( "utf-16be" ) == 0 ){
164- return 2;
165- }else if( encoding.compare( "utf-16" ) == 0 ){
166- return 2;
167- }else if( encoding.compare( "utf-32le" ) == 0 ){
168- return 4;
169- }else if( encoding.compare( "utf-32be" ) == 0 ){
170- return 4;
171- }else if( encoding.compare( "utf-32" ) == 0 ){
172- return 4;
173- }else{
174- return 1;
175- }
176- }
177-
178- private:
179- EncodingConverter();
180-
181- /**
182- * 小文字に変換する
183- * @param text 変換元の文字列
184- * @return 小文字に変換後の文字列
185- */
186- static string toLower( string text )
187- {
188- int length = text.length();
189- int i;
190- for( i = 0; i < length; i++ ){
191- text[i] = tolower( text[i] );
192- }
193- return text;
194- }
195-
196- /**
197- * コードページ番号から、エンコーディング名を取得する
198- * @param codepage 調べるコードページ番号
199- * @return エンコーディング名
200- */
201- static string getCharsetFromCodepage( unsigned int codepage )
202- {
203- switch( codepage ){
204- case 932:{
205- return "Shift_JIS";
206- }
207- case 51932: {
208- return "euc-jp";
209- }
210- case 50220: {
211- return "iso-2022-jp";
212- }
213- case 1208:
214- case 1209: {
215- return "UTF-8";
216- }
217- case 1202:
218- case 1203: {
219- return "UTF-16LE";
220- }
221- case 1200:
222- case 1201: {
223- return "UTF-16BE";
224- }
225- case 1204:
226- case 1205: {
227- return "UTF-16";
228- }
229- case 1234:
230- case 1235: {
231- return "UTF-32LE";
232- }
233- case 1232:
234- case 1233: {
235- return "UTF-32BE";
236- }
237- case 1236:
238- case 1237: {
239- return "UTF-32";
240- }
241- }
242- return "";
243- }
244-
245- /**
246- * コードページの名称から、コードページ番号を取得する
247- * @param name コードページ名称
248- * @return コードページ番号
249- */
250- static unsigned int getCodepageFromCharset( string sname )
251- {
252- sname = toLower( sname );
253- if( sname.compare( "shift_jis") == 0 ){
254- return 932;
255- }else if( sname.compare( "euc-jp" ) == 0 ){
256- return 51932;
257- }else if( sname.compare( "iso-2022-jp" ) == 0 ){
258- return 50220;
259- }else if( sname.compare( "utf-8" ) == 0 || sname.compare( "utf8" ) == 0 ){
260- return 1208;
261- }else if( sname.compare( "utf-16le" ) == 0 || sname.compare( "utf16le" ) == 0 ){
262- return 1202;
263- }else if( sname.compare( "utf-16be" ) == 0 || sname.compare( "utf16be" ) == 0 ){
264- return 1200;
265- }else if( sname.compare( "utf-16" ) == 0 || sname.compare( "utf16" ) == 0 ){
266- return 1204;
267- }else if( sname.compare( "utf-32le" ) == 0 || sname.compare( "utf32le" ) == 0 ){
268- return 1234;
269- }else if( sname.compare( "utf-32be" ) == 0 || sname.compare( "utf32be" ) == 0 ){
270- return 1232;
271- }else if( sname.compare( "utf-32" ) == 0 || sname.compare( "utf32" ) == 0 ){
272- return 1236;
273- }else{
274- return 0;
275- }
276- }
277-
278- /**
279- * 有効なコンバータかどうかを調べる
280- * @param converter 調べる対象のコンバータ
281- * @return コンバータが有効であれば true を、そうでなければ false を返す
282- */
283- static bool isValidConverter( iconv_t converter )
284- {
285- iconv_t invalid = (iconv_t) - 1;
286- return (converter == invalid) ? false : true;
287- }
288-
289- /**
290- * 有効なエンコーディングかどうかを取得する
291- * @param codepage エンコーディング番号
292- * @return 有効なエンコーディングであれば true を、そうでなければ false を返す
293- */
294- static bool isValidEncoding( unsigned int codepage )
295- {
296- // まずUTF-8が有効かどうか
297- iconv_t cnv = iconv_open( "UTF-8", "UTF-8" );
298- if( false == isValidConverter( cnv ) ){
299- iconv_close( cnv );
300- return false;
301- }
302- iconv_close( cnv );
303-
304- string charset_name = getCharsetFromCodepage( codepage );
305- iconv_t cnv2 = iconv_open( "UTF-8", charset_name.c_str() );
306- if( false == isValidConverter( cnv2 ) ){
307- iconv_close( cnv2 );
308- return false;
309- }
310- iconv_close( cnv2 );
311-
312- iconv_t cnv3 = iconv_open( charset_name.c_str(), "UTF-8" );
313- if( false == isValidConverter( cnv3 ) ){
314- iconv_close( cnv3 );
315- return false;
316- }
317- iconv_close( cnv3 );
318- return true;
319- }
320- };
321-}
322-
323-#endif
1+#ifndef __EncodingConverter_h__
2+#define __EncodingConverter_h__
3+
4+#include <iconv.h>
5+
6+using namespace std;
7+
8+namespace vconnect
9+{
10+ /**
11+ * マルチバイト文字列のテキストエンコーディングを変換するためのコンバータ
12+ */
13+ class EncodingConverter
14+ {
15+ private:
16+ /**
17+ * システム内部のマルチバイト文字列が使用しているテキストエンコーディング名
18+ */
19+ string internalEncoding;
20+
21+ /**
22+ * libiconv のコンバータ
23+ */
24+ iconv_t converter;
25+
26+ public:
27+ /**
28+ * 変換元と変換先のエンコーディングを指定し、コンバータを初期化する
29+ * @param from 変換前のエンコーディング名
30+ * @param to 変換後のエンコーディング名
31+ */
32+ EncodingConverter( string from, string to )
33+ {
34+ this->converter = iconv_open( to.c_str(), from.c_str() );
35+ this->internalEncoding = getInternalEncoding();
36+ }
37+
38+ ~EncodingConverter()
39+ {
40+ iconv_close( this->converter );
41+ }
42+
43+ /**
44+ * 文字列のテキストエンコーディングを変換する
45+ * @param source 変換する文字列
46+ * @return エンコーディングを変換した文字列
47+ */
48+ string convert( string source )
49+ {
50+ string result;
51+ char *input = const_cast<char *>( source.c_str() );
52+ size_t remainingInputBytes = source.size();
53+
54+ char *buffer = new char[remainingInputBytes + 1];
55+ char *output = buffer;
56+ size_t remainingOutputBytes = remainingInputBytes;
57+ size_t outputBytes = remainingInputBytes;
58+
59+ while( remainingInputBytes > 0 ){
60+ char *originalInput = input;
61+ size_t n = iconv( this->converter, &input, &remainingInputBytes, &output, &remainingOutputBytes );
62+ if( (n != (size_t) - 1 && remainingInputBytes == 0) || (errno == EINVAL) ){
63+ remainingInputBytes = 0;
64+ result.append( buffer, 0, outputBytes - remainingOutputBytes );
65+ }else{
66+ switch( errno ){
67+ case E2BIG:{
68+ result.append( buffer, 0, outputBytes - remainingOutputBytes );
69+ output = buffer;
70+ remainingOutputBytes = outputBytes;
71+ break;
72+ }
73+ case EILSEQ:{
74+ result.append( buffer, 0, outputBytes - remainingOutputBytes );
75+ result.append( input, 0, 1 );
76+ input++;
77+ remainingInputBytes--;
78+ output = buffer;
79+ remainingOutputBytes = outputBytes;
80+ break;
81+ }
82+ default:{
83+ result.append( originalInput );
84+ remainingInputBytes = 0;
85+ break;
86+ }
87+ }
88+ }
89+ }
90+ output = buffer;
91+ remainingOutputBytes = outputBytes;
92+ if( iconv( this->converter , NULL, NULL, &output, &remainingOutputBytes ) != (size_t) - 1 ){
93+ result.append( buffer, 0, outputBytes - remainingOutputBytes );
94+ }
95+ delete [] buffer;
96+ return result;
97+ }
98+
99+ /**
100+ * char の内部のエンコーディングを調べる
101+ * @return
102+ */
103+ static string getInternalEncoding()
104+ {
105+ unsigned int result = 0;
106+ char *localeNameRaw = std::setlocale( LC_CTYPE, "" );
107+#ifdef __APPLE__
108+ // Macは決め打ち
109+ result = 1208;
110+#else
111+ if( NULL != localeNameRaw ){
112+ // localeName = "ja_JP.UTF-8" (openSUSE, g++)
113+ // localeName = "Japanese_Japan.932" (Windows XP, g++)
114+ string localeName = localeNameRaw;
115+ int index = localeName.rfind( "." );
116+ if( index != string::npos ){
117+ string encodingName = localeName.substr( index + 1 );
118+ // snum部分が数値に変換できるかどうかを調べる
119+ if( encodingName.size() == 0 ){
120+ result = 1208;
121+ }else{
122+ bool allnum = true;
123+ for( int i = 0; i < encodingName.size(); i++ ){
124+ char c = encodingName[i];
125+ if( isdigit( c ) == 0 ){
126+ allnum = false;
127+ break;
128+ }
129+ }
130+ if( allnum ){
131+ int encodingNumber = atoi( encodingName.c_str() );
132+ result = encodingNumber;
133+ }else{
134+ result = 1208;
135+ }
136+ }
137+ }else{
138+ result = 1208;
139+ }
140+ }else{
141+ result = 1208;
142+ }
143+#endif
144+ return getCharsetFromCodepage( result );
145+ }
146+
147+ /**
148+ * コードページの名称から、読込み時の読込単位(バイト)を調べます
149+ * @return テキストファイルからの読み込み単位
150+ */
151+ static int getBytesPerWord( string encoding )
152+ {
153+ encoding = toLower( encoding );
154+ if( encoding.compare( "shift_jis" ) == 0 ){
155+ return 1;
156+ }else if( encoding.compare( "euc-jp" ) == 0 ){
157+ return 1;
158+ }else if( encoding.compare( "iso-2022-jp" ) == 0 ){
159+ return 1;
160+ }else if( encoding.compare( "utf-8" ) == 0 ){
161+ return 1;
162+ }else if( encoding.compare( "utf-16le" ) == 0 ){
163+ return 2;
164+ }else if( encoding.compare( "utf-16be" ) == 0 ){
165+ return 2;
166+ }else if( encoding.compare( "utf-16" ) == 0 ){
167+ return 2;
168+ }else if( encoding.compare( "utf-32le" ) == 0 ){
169+ return 4;
170+ }else if( encoding.compare( "utf-32be" ) == 0 ){
171+ return 4;
172+ }else if( encoding.compare( "utf-32" ) == 0 ){
173+ return 4;
174+ }else{
175+ return 1;
176+ }
177+ }
178+
179+ private:
180+ EncodingConverter();
181+
182+ /**
183+ * 小文字に変換する
184+ * @param text 変換元の文字列
185+ * @return 小文字に変換後の文字列
186+ */
187+ static string toLower( string text )
188+ {
189+ int length = text.length();
190+ int i;
191+ for( i = 0; i < length; i++ ){
192+ text[i] = tolower( text[i] );
193+ }
194+ return text;
195+ }
196+
197+ /**
198+ * コードページ番号から、エンコーディング名を取得する
199+ * @param codepage 調べるコードページ番号
200+ * @return エンコーディング名
201+ */
202+ static string getCharsetFromCodepage( unsigned int codepage )
203+ {
204+ switch( codepage ){
205+ case 932:{
206+ return "Shift_JIS";
207+ }
208+ case 51932: {
209+ return "euc-jp";
210+ }
211+ case 50220: {
212+ return "iso-2022-jp";
213+ }
214+ case 1208:
215+ case 1209: {
216+ return "UTF-8";
217+ }
218+ case 1202:
219+ case 1203: {
220+ return "UTF-16LE";
221+ }
222+ case 1200:
223+ case 1201: {
224+ return "UTF-16BE";
225+ }
226+ case 1204:
227+ case 1205: {
228+ return "UTF-16";
229+ }
230+ case 1234:
231+ case 1235: {
232+ return "UTF-32LE";
233+ }
234+ case 1232:
235+ case 1233: {
236+ return "UTF-32BE";
237+ }
238+ case 1236:
239+ case 1237: {
240+ return "UTF-32";
241+ }
242+ }
243+ return "";
244+ }
245+
246+ /**
247+ * コードページの名称から、コードページ番号を取得する
248+ * @param name コードページ名称
249+ * @return コードページ番号
250+ */
251+ static unsigned int getCodepageFromCharset( string sname )
252+ {
253+ sname = toLower( sname );
254+ if( sname.compare( "shift_jis") == 0 ){
255+ return 932;
256+ }else if( sname.compare( "euc-jp" ) == 0 ){
257+ return 51932;
258+ }else if( sname.compare( "iso-2022-jp" ) == 0 ){
259+ return 50220;
260+ }else if( sname.compare( "utf-8" ) == 0 || sname.compare( "utf8" ) == 0 ){
261+ return 1208;
262+ }else if( sname.compare( "utf-16le" ) == 0 || sname.compare( "utf16le" ) == 0 ){
263+ return 1202;
264+ }else if( sname.compare( "utf-16be" ) == 0 || sname.compare( "utf16be" ) == 0 ){
265+ return 1200;
266+ }else if( sname.compare( "utf-16" ) == 0 || sname.compare( "utf16" ) == 0 ){
267+ return 1204;
268+ }else if( sname.compare( "utf-32le" ) == 0 || sname.compare( "utf32le" ) == 0 ){
269+ return 1234;
270+ }else if( sname.compare( "utf-32be" ) == 0 || sname.compare( "utf32be" ) == 0 ){
271+ return 1232;
272+ }else if( sname.compare( "utf-32" ) == 0 || sname.compare( "utf32" ) == 0 ){
273+ return 1236;
274+ }else{
275+ return 0;
276+ }
277+ }
278+
279+ /**
280+ * 有効なコンバータかどうかを調べる
281+ * @param converter 調べる対象のコンバータ
282+ * @return コンバータが有効であれば true を、そうでなければ false を返す
283+ */
284+ static bool isValidConverter( iconv_t converter )
285+ {
286+ iconv_t invalid = (iconv_t) - 1;
287+ return (converter == invalid) ? false : true;
288+ }
289+
290+ /**
291+ * 有効なエンコーディングかどうかを取得する
292+ * @param codepage エンコーディング番号
293+ * @return 有効なエンコーディングであれば true を、そうでなければ false を返す
294+ */
295+ static bool isValidEncoding( unsigned int codepage )
296+ {
297+ // まずUTF-8が有効かどうか
298+ iconv_t cnv = iconv_open( "UTF-8", "UTF-8" );
299+ if( false == isValidConverter( cnv ) ){
300+ iconv_close( cnv );
301+ return false;
302+ }
303+ iconv_close( cnv );
304+
305+ string charset_name = getCharsetFromCodepage( codepage );
306+ iconv_t cnv2 = iconv_open( "UTF-8", charset_name.c_str() );
307+ if( false == isValidConverter( cnv2 ) ){
308+ iconv_close( cnv2 );
309+ return false;
310+ }
311+ iconv_close( cnv2 );
312+
313+ iconv_t cnv3 = iconv_open( charset_name.c_str(), "UTF-8" );
314+ if( false == isValidConverter( cnv3 ) ){
315+ iconv_close( cnv3 );
316+ return false;
317+ }
318+ iconv_close( cnv3 );
319+ return true;
320+ }
321+ };
322+}
323+
324+#endif
--- vConnect/trunk/stand2.0/stand/TextWriter.h (revision 1913)
+++ vConnect/trunk/stand2.0/stand/TextWriter.h (revision 1914)
@@ -1,92 +1,92 @@
1-/*
2- * TextWriter.h
3- * Copyright © 2012 kbinani
4- *
5- * This file is part of vConnect-STAND.
6- *
7- * vConnect-STAND is free software; you can redistribute it and/or
8- * modify it under the terms of the GPL License.
9- *
10- * vConnect-STAND is distributed in the hope that it will be useful,
11- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13- */
14-#ifndef __TextWriter_h__
15-#define __TextWriter_h__
16-
17-#include "EncodingConverter.h"
18-
19-using namespace std;
20-
21-namespace vconnect
22-{
23-
24- /**
25- * テキストファイルへの書き込みを行うためのクラス
26- */
27- class TextWriter
28- {
29- private:
30- EncodingConverter *converter;
31- FILE *fileHandle;
32- string newLine;
33-
34- public:
35- /**
36- * テキストエンコーディング、ファイルパス、改行文字を指定してファイルを開く
37- * @param path ファイルパス
38- * @param encoding 書きこむテキストのエンコーディング
39- * @param newLine 改行文字列
40- */
41- TextWriter( string path, string encoding, string newLine )
42- {
43- this->fileHandle = fopen( path.c_str(), "wb" );
44- this->converter = new EncodingConverter( EncodingConverter::getInternalEncoding(), encoding );
45- this->newLine = newLine;
46- }
47-
48- /**
49- * デストラクタ
50- */
51- ~TextWriter()
52- {
53- this->close();
54- }
55-
56- /**
57- * バッファをフラッシュしファイルを閉じる
58- */
59- void close()
60- {
61- if( this->fileHandle ){
62- fflush( this->fileHandle );
63- fclose( this->fileHandle );
64- }
65- if( this->converter ){
66- delete this->converter;
67- }
68- this->fileHandle = NULL;
69- this->converter = NULL;
70- }
71-
72- /**
73- * 新しい行を書き込む
74- * @param line 書きこむ行データ
75- */
76- void writeLine( string line )
77- {
78- string converted;
79- converted = this->converter->convert( line );
80- converted += this->newLine;
81- fprintf( this->fileHandle, "%s", converted.c_str() );
82- }
83-
84- private:
85- TextWriter()
86- {
87- };
88- };
89-
90-}
91-
92-#endif
1+/*
2+ * TextWriter.h
3+ * Copyright © 2012 kbinani
4+ *
5+ * This file is part of vConnect-STAND.
6+ *
7+ * vConnect-STAND is free software; you can redistribute it and/or
8+ * modify it under the terms of the GPL License.
9+ *
10+ * vConnect-STAND is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13+ */
14+#ifndef __TextWriter_h__
15+#define __TextWriter_h__
16+
17+#include "EncodingConverter.h"
18+
19+using namespace std;
20+
21+namespace vconnect
22+{
23+
24+ /**
25+ * テキストファイルへの書き込みを行うためのクラス
26+ */
27+ class TextWriter
28+ {
29+ private:
30+ EncodingConverter *converter;
31+ FILE *fileHandle;
32+ string newLine;
33+
34+ public:
35+ /**
36+ * テキストエンコーディング、ファイルパス、改行文字を指定してファイルを開く
37+ * @param path ファイルパス
38+ * @param encoding 書きこむテキストのエンコーディング
39+ * @param newLine 改行文字列
40+ */
41+ TextWriter( string path, string encoding, string newLine )
42+ {
43+ this->fileHandle = fopen( path.c_str(), "wb" );
44+ this->converter = new EncodingConverter( EncodingConverter::getInternalEncoding(), encoding );
45+ this->newLine = newLine;
46+ }
47+
48+ /**
49+ * デストラクタ
50+ */
51+ ~TextWriter()
52+ {
53+ this->close();
54+ }
55+
56+ /**
57+ * バッファをフラッシュしファイルを閉じる
58+ */
59+ void close()
60+ {
61+ if( this->fileHandle ){
62+ fflush( this->fileHandle );
63+ fclose( this->fileHandle );
64+ }
65+ if( this->converter ){
66+ delete this->converter;
67+ }
68+ this->fileHandle = NULL;
69+ this->converter = NULL;
70+ }
71+
72+ /**
73+ * 新しい行を書き込む
74+ * @param line 書きこむ行データ
75+ */
76+ void writeLine( string line )
77+ {
78+ string converted;
79+ converted = this->converter->convert( line );
80+ converted += this->newLine;
81+ fprintf( this->fileHandle, "%s", converted.c_str() );
82+ }
83+
84+ private:
85+ TextWriter()
86+ {
87+ };
88+ };
89+
90+}
91+
92+#endif
旧リポジトリブラウザで表示