/* * Copyright (C) 2003-2006 Gabest * http://www.gabest.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include #include #include "TextFile.h" CTextFile::CTextFile(enc e) { m_encoding = m_defaultencoding = e; m_offset = 0; } bool CTextFile::Open(LPCTSTR lpszFileName) { if(!__super::Open(lpszFileName, modeRead|typeBinary|shareDenyWrite)) return(false); m_encoding = m_defaultencoding; m_offset = 0; if(__super::GetLength() >= 2) { WORD w; if(sizeof(w) != Read(&w, sizeof(w))) return Close(), false; if(w == 0xfeff) { m_encoding = LE16; m_offset = 2; } else if(w == 0xfffe) { m_encoding = BE16; m_offset = 2; } else if(w == 0xbbef && __super::GetLength() >= 3) { BYTE b; if(sizeof(b) != Read(&b, sizeof(b))) return Close(), false; if(b == 0xbf) { m_encoding = UTF8; m_offset = 3; } } } if(m_encoding == m_defaultencoding) { __super::Close(); // CWebTextFile::Close() would delete the temp file if we called it... if(!__super::Open(lpszFileName, modeRead|typeText|shareDenyWrite)) return(false); } return(true); } bool CTextFile::Save(LPCTSTR lpszFileName, enc e) { if(!__super::Open(lpszFileName, modeCreate|modeWrite|shareDenyWrite|(e==ASCII?typeText:typeBinary))) return(false); if(e == UTF8) { BYTE b[3] = {0xef,0xbb,0xbf}; Write(b, sizeof(b)); } else if(e == LE16) { BYTE b[2] = {0xff,0xfe}; Write(b, sizeof(b)); } else if(e == BE16) { BYTE b[2] = {0xfe,0xff}; Write(b, sizeof(b)); } m_encoding = e; return true; } void CTextFile::SetEncoding(enc e) { m_encoding = e; } CTextFile::enc CTextFile::GetEncoding() { return m_encoding; } bool CTextFile::IsUnicode() { return m_encoding == UTF8 || m_encoding == LE16 || m_encoding == BE16; } // CFile CString CTextFile::GetFilePath() const { // to avoid a CException coming from CTime return m_strFileName; // __super::GetFilePath(); } // CStdioFile ULONGLONG CTextFile::GetPosition() const { return(CStdioFile::GetPosition() - m_offset); } ULONGLONG CTextFile::GetLength() const { return(CStdioFile::GetLength() - m_offset); } ULONGLONG CTextFile::Seek(LONGLONG lOff, UINT nFrom) { ULONGLONG pos = GetPosition(); ULONGLONG len = GetLength(); switch(nFrom) { default: case begin: lOff = lOff; break; case current: lOff = pos + lOff; break; case end: lOff = len - lOff; break; } lOff = max(min(lOff, len), 0) + m_offset; pos = CStdioFile::Seek(lOff, begin) - m_offset; return(pos); } void CTextFile::WriteString(LPCSTR lpsz/*CStringA str*/) { CStringA str(lpsz); if(m_encoding == ASCII) { __super::WriteString(AToT(str)); } else if(m_encoding == ANSI) { str.Replace("\n", "\r\n"); Write((LPCSTR)str, str.GetLength()); } else if(m_encoding == UTF8) { WriteString(AToW(str)); } else if(m_encoding == LE16) { WriteString(AToW(str)); } else if(m_encoding == BE16) { WriteString(AToW(str)); } } void CTextFile::WriteString(LPCWSTR lpsz/*CStringW str*/) { CStringW str(lpsz); if(m_encoding == ASCII) { __super::WriteString(WToT(str)); } else if(m_encoding == ANSI) { str.Replace(L"\n", L"\r\n"); CStringA stra = CStringA(CString(str)); // TODO: codepage Write((LPCSTR)stra, stra.GetLength()); } else if(m_encoding == UTF8) { str.Replace(L"\n", L"\r\n"); for(int i = 0; i < str.GetLength(); i++) { DWORD c = (WORD)str[i]; if(0 <= c && c < 0x80) // 0xxxxxxx { Write(&c, 1); } else if(0x80 <= c && c < 0x800) // 110xxxxx 10xxxxxx { c = 0xc080|((c<<2)&0x1f00)|(c&0x003f); Write((BYTE*)&c+1, 1); Write(&c, 1); } else if(0x800 <= c && c < 0xFFFF) // 1110xxxx 10xxxxxx 10xxxxxx { c = 0xe08080|((c<<4)&0x0f0000)|((c<<2)&0x3f00)|(c&0x003f); Write((BYTE*)&c+2, 1); Write((BYTE*)&c+1, 1); Write(&c, 1); } else { c = '?'; Write(&c, 1); } } } else if(m_encoding == LE16) { str.Replace(L"\n", L"\r\n"); Write((LPCWSTR)str, str.GetLength()*2); } else if(m_encoding == BE16) { str.Replace(L"\n", L"\r\n"); for(int i = 0; i < str.GetLength(); i++) str.SetAt(i, ((str[i]>>8)&0x00ff)|((str[i]<<8)&0xff00)); Write((LPCWSTR)str, str.GetLength()*2); } } BOOL CTextFile::ReadString(CStringA& str) { bool fEOF = true; str.Empty(); if(m_encoding == ASCII) { CString s; fEOF = !__super::ReadString(s); str = TToA(s); } else if(m_encoding == ANSI) { char c; while(Read(&c, sizeof(c)) == sizeof(c)) { fEOF = false; if(c == '\r') continue; if(c == '\n') break; str += c; } } else if(m_encoding == UTF8) { BYTE b; while(Read(&b, sizeof(b)) == sizeof(b)) { fEOF = false; char c = '?'; if(!(b&0x80)) // 0xxxxxxx { c = b&0x7f; } else if((b&0xe0) == 0xc0) // 110xxxxx 10xxxxxx { if(Read(&b, sizeof(b)) != sizeof(b)) break; } else if((b&0xf0) == 0xe0) // 1110xxxx 10xxxxxx 10xxxxxx { if(Read(&b, sizeof(b)) != sizeof(b)) break; if(Read(&b, sizeof(b)) != sizeof(b)) break; } if(c == '\r') continue; if(c == '\n') break; str += c; } } else if(m_encoding == LE16) { WORD w; while(Read(&w, sizeof(w)) == sizeof(w)) { fEOF = false; char c = '?'; if(!(w&0xff00)) c = w&0xff; if(c == '\r') continue; if(c == '\n') break; str += c; } } else if(m_encoding == BE16) { WORD w; while(Read(&w, sizeof(w)) == sizeof(w)) { fEOF = false; char c = '?'; if(!(w&0xff)) c = w>>8; if(c == '\r') continue; if(c == '\n') break; str += c; } } return(!fEOF); } BOOL CTextFile::ReadString(CStringW& str) { bool fEOF = true; str.Empty(); if(m_encoding == ASCII) { CString s; fEOF = !__super::ReadString(s); str = TToW(s); } else if(m_encoding == ANSI) { CStringA stra; char c; while(Read(&c, sizeof(c)) == sizeof(c)) { fEOF = false; if(c == '\r') continue; if(c == '\n') break; stra += c; } str = CStringW(CString(stra)); // TODO: codepage } else if(m_encoding == UTF8) { BYTE b; while(Read(&b, sizeof(b)) == sizeof(b)) { fEOF = false; WCHAR c = '?'; if(!(b&0x80)) // 0xxxxxxx { c = b&0x7f; } else if((b&0xe0) == 0xc0) // 110xxxxx 10xxxxxx { c = (b&0x1f)<<6; if(Read(&b, sizeof(b)) != sizeof(b)) break; c |= (b&0x3f); } else if((b&0xf0) == 0xe0) // 1110xxxx 10xxxxxx 10xxxxxx { c = (b&0x0f)<<12; if(Read(&b, sizeof(b)) != sizeof(b)) break; c |= (b&0x3f)<<6; if(Read(&b, sizeof(b)) != sizeof(b)) break; c |= (b&0x3f); } if(c == '\r') continue; if(c == '\n') break; str += c; } } else if(m_encoding == LE16) { WCHAR wc; while(Read(&wc, sizeof(wc)) == sizeof(wc)) { fEOF = false; if(wc == '\r') continue; if(wc == '\n') break; str += wc; } } else if(m_encoding == BE16) { WCHAR wc; while(Read(&wc, sizeof(wc)) == sizeof(wc)) { fEOF = false; wc = ((wc>>8)&0x00ff)|((wc<<8)&0xff00); if(wc == '\r') continue; if(wc == '\n') break; str += wc; } } return(!fEOF); } // // CWebTextFile // CWebTextFile::CWebTextFile(LONGLONG llMaxSize) : m_llMaxSize(llMaxSize) { } bool CWebTextFile::Open(LPCTSTR lpszFileName) { CString fn(lpszFileName); if(fn.Find(_T("http://")) != 0) return __super::Open(lpszFileName); try { CInternetSession is; CAutoPtr f(is.OpenURL(fn, 1, INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_EXISTING_CONNECT)); if(!f) return(false); TCHAR path[MAX_PATH]; GetTempPath(MAX_PATH, path); fn = path + fn.Mid(fn.ReverseFind('/')+1); int i = fn.Find(_T("?")); if(i > 0) fn = fn.Left(i); CFile temp; if(!temp.Open(fn, modeCreate|modeWrite|typeBinary|shareDenyWrite)) { f->Close(); return(false); } BYTE buff[1024]; int len, total = 0; while((len = f->Read(buff, 1024)) == 1024 && (m_llMaxSize < 0 || (total+=1024) < m_llMaxSize)) temp.Write(buff, len); if(len > 0) temp.Write(buff, len); m_tempfn = fn; f->Close(); // must close it because the desctructor doesn't seem to do it and we will get an exception when "is" is destroying } catch(CInternetException* ie) { ie->Delete(); return(false); } return __super::Open(m_tempfn); } bool CWebTextFile::Save(LPCTSTR lpszFileName, enc e) { // CWebTextFile is read-only... ASSERT(0); return(false); } void CWebTextFile::Close() { __super::Close(); if(!m_tempfn.IsEmpty()) { _tremove(m_tempfn); m_tempfn.Empty(); } } /////////////////////////////////////////////////////////////// CStringW AToW(CStringA str) { CStringW ret; for(int i = 0, j = str.GetLength(); i < j; i++) ret += (WCHAR)(BYTE)str[i]; return(ret); } CStringA WToA(CStringW str) { CStringA ret; for(int i = 0, j = str.GetLength(); i < j; i++) ret += (CHAR)(WORD)str[i]; return(ret); } CString AToT(CStringA str) { CString ret; for(int i = 0, j = str.GetLength(); i < j; i++) ret += (TCHAR)(BYTE)str[i]; return(ret); } CString WToT(CStringW str) { CString ret; for(int i = 0, j = str.GetLength(); i < j; i++) ret += (TCHAR)(WORD)str[i]; return(ret); } CStringA TToA(CString str) { CStringA ret; #ifdef UNICODE for(int i = 0, j = str.GetLength(); i < j; i++) ret += (CHAR)(BYTE)str[i]; #else ret = str; #endif return(ret); } CStringW TToW(CString str) { CStringW ret; #ifdef UNICODE ret = str; #else for(int i = 0, j = str.GetLength(); i < j; i++) ret += (WCHAR)(BYTE)str[i]; #endif return(ret); }