11/* ! @file */
22/*
3- Copyright (C) 2018-2022 , Sakura Editor Organization
3+ Copyright (C) 2018-2026 , Sakura Editor Organization
44
55 SPDX-License-Identifier: Zlib
66*/
77#include " StdAfx.h"
8- #include " CTextStream.h"
8+ #include " io/CTextStream.h"
9+
910#include " charset/CCodeFactory.h"
1011#include " charset/CShiftJis.h" // move from CCodeMediator.h 2010/6/14 Uchi
1112#include " charset/CUtf8.h" // move from CCodeMediator.h 2010/6/14 Uchi
1213#include " basis/CEol.h"
1314#include " util/file.h" // _IS_REL_PATH
1415#include " util/module.h"
1516
17+ namespace cxx {
18+
19+ std::wstring_view MultiByteToWideChar (UINT codePage, std::string_view source, std::wstring& buffer);
20+
21+ } // namespace cxx
22+
1623// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
1724// CTextInputStream //
1825// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
1926
2027CTextInputStream::CTextInputStream (const WCHAR * pszPath)
2128: CStream(pszPath,L" rb" )
2229{
23- m_bIsUtf8=false ;
24-
2530 if (Good ()){
2631 // BOM確認 -> m_bIsUtf8
2732 static const BYTE UTF8_BOM []={0xEF ,0xBB ,0xBF };
@@ -35,9 +40,6 @@ CTextInputStream::CTextInputStream(const WCHAR* pszPath)
3540 fseek (GetFp (),0 ,SEEK_SET );
3641 }
3742 }
38- else {
39- m_bIsUtf8 = false ;
40- }
4143}
4244
4345/*
@@ -52,32 +54,61 @@ CTextInputStream::~CTextInputStream()
5254{
5355}
5456
55- std::wstring CTextInputStream::ReadLineW ()
57+ /* !
58+ * @brief 1行読込。改行は削る
59+ */
60+ void CTextInputStream::ReadLineW (std::wstring& line)
5661{
5762 // $$ 非効率だけど今のところは許して。。
58- CNativeW line;
59- line.AllocStringBuffer (60 );
60- for (;;) {
61- int c=getc (GetFp ());
62- if (c==EOF )break ; // EOFで終了
63- if (c==' \r ' ){ c=getc (GetFp ()); if (c!=' \n ' )ungetc (c,GetFp ()); break ; } // "\r" または "\r\n" で終了
64- if (c==' \n ' )break ; // "\n" で終了
65- if ( line._GetMemory ()->capacity () < line._GetMemory ()->GetRawLength () + 10 ){
66- line._GetMemory ()->AllocBuffer ( line._GetMemory ()->GetRawLength () * 2 );
63+
64+ // 実は言う程「非効率」でもない。
65+ // ・ファイルデータ → 内部バッファ m_Buffer
66+ // ・内部バッファ m_Buffer → UNICODE文字列
67+
68+ // 現在のバッファ書込位置はイテレータで管理する
69+ auto it = m_Buffer.begin ();
70+ for (;; ++it) {
71+ int c = ::getc (GetFp ());
72+ // CRを検出したらCRLFかどうかチェックする
73+ if (' \r ' == c) {
74+ c = ::getc (GetFp ());
75+ if (' \n ' != c) {
76+ ::ungetc (c, GetFp());
77+ c = ' \r ' ;
78+ }
6779 }
68- line._GetMemory ()->AppendRawData (&c,sizeof (char ));
69- }
7080
71- // UTF-8 → UNICODE
72- if (m_bIsUtf8){
73- CUtf8::UTF8ToUnicode (*(line._GetMemory ()), &line);
74- }
75- // Shift_JIS → UNICODE
76- else {
77- CShiftJis::SJISToUnicode (*(line._GetMemory ()), &line);
81+ // CRLF, LF, CR, EOF で終了
82+ if (' \n ' == c || ' \r ' == c || EOF == c) break ; // EOFで終了
83+
84+ // バッファ末尾に到達したら拡張する
85+ if (it == m_Buffer.end ()) {
86+ const auto pos = std::distance (m_Buffer.begin (), it);
87+ m_Buffer.resize (m_Buffer.size () * 2 );
88+ it = m_Buffer.begin () + pos;
89+ }
90+
91+ // バッファに書き込む
92+ *it = static_cast <char >(c);
7893 }
7994
80- return std::wstring (line.GetStringPtr (), line.GetStringLength ()); // EOLまで。NUL文字も含める。
95+ // 変換に使うコードページを確定させる
96+ const auto codePage = m_bIsUtf8 ? CP_UTF8 : CP_SJIS ; // UTF-8ならCP_UTF8、そうでなければShift_JIS(CP932)とする
97+
98+ // 変換を実行する
99+ cxx::MultiByteToWideChar (codePage, std::string_view{ m_Buffer.begin (), it }, line);
100+ }
101+
102+ /* !
103+ * @brief 1行読込。改行は削る
104+ *
105+ * @note 既存コード互換のため残しておく。
106+ */
107+ std::wstring CTextInputStream::ReadLineW ()
108+ {
109+ std::wstring line;
110+ ReadLineW (line);
111+ return line;
81112}
82113
83114// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
0 commit comments