- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# TextFile.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 #include "stdafx.h"
    00023 #include <atlbase.h>
    00024 #include <afxinet.h>
    00025 #include "TextFile.h"
    00026
    00027 CTextFile::CTextFile()
    00028 {
    00029         m_encoding = ASCII;
    00030         m_offset = 0;
    00031 }
    00032
    00033 bool CTextFile::Open(LPCTSTR lpszFileName)
    00034 {
    00035         if(!__super::Open(lpszFileName, modeRead|typeBinary|shareDenyWrite))
    00036                 return(false);
    00037
    00038         m_encoding = ASCII;
    00039         m_offset = 0;
    00040
    00041         if(__super::GetLength() >= 2)
    00042         {
    00043                 WORD w;
    00044                 if(sizeof(w) != Read(&w, sizeof(w)))
    00045                         return Close(), false;
    00046
    00047                 if(w == 0xfeff)
    00048                 {
    00049                         m_encoding = LE16;
    00050                         m_offset = 2;
    00051                 }
    00052                 else if(w == 0xfffe)
    00053                 {
    00054                         m_encoding = BE16;
    00055                         m_offset = 2;
    00056                 }
    00057                 else if(w == 0xbbef && __super::GetLength() >= 3)
    00058                 {
    00059                         BYTE b;
    00060                         if(sizeof(b) != Read(&b, sizeof(b)))
    00061                                 return Close(), false;
    00062
    00063                         if(b == 0xbf)
    00064                         {
    00065                                 m_encoding = UTF8;
    00066                                 m_offset = 3;
    00067                         }
    00068                 }
    00069         }
    00070
    00071         if(m_encoding == ASCII)
    00072         {
    00073                 __super::Close(); // CWebTextFile::Close() would delete the temp file if we called it...
    00074                 if(!__super::Open(lpszFileName, modeRead|typeText|shareDenyWrite))
    00075                         return(false);
    00076         }
    00077
    00078         return(true);
    00079 }
    00080
    00081 bool CTextFile::Save(LPCTSTR lpszFileName, enc e)
    00082 {
    00083         if(!__super::Open(lpszFileName, modeCreate|modeWrite|shareDenyWrite|(e==ASCII?typeText:typeBinary)))
    00084                 return(false);
    00085
    00086         if(e == UTF8)
    00087         {
    00088                 BYTE b[3] = {0xef,0xbb,0xbf};
    00089                 Write(b, sizeof(b));
    00090         }
    00091         else if(e == LE16)
    00092         {
    00093                 BYTE b[2] = {0xff,0xfe};
    00094                 Write(b, sizeof(b));
    00095         }
    00096         else if(e == BE16)
    00097         {
    00098                 BYTE b[2] = {0xfe,0xff};
    00099                 Write(b, sizeof(b));
    00100         }
    00101
    00102         m_encoding = e;
    00103
    00104         return(true);
    00105 }
    00106
    00107 CTextFile::enc CTextFile::GetEncoding()
    00108 {
    00109         return(m_encoding);
    00110 }
    00111
    00112 bool CTextFile::IsUnicode()
    00113 {
    00114         return(m_encoding == UTF8 || m_encoding == LE16 || m_encoding == BE16);
    00115 }
    00116
    00117 // CFile
    00118
    00119 CString CTextFile::GetFilePath() const
    00120 {
    00121         // to avoid a CException coming from CTime
    00122         return m_strFileName; // __super::GetFilePath();
    00123 }
    00124
    00125 // CStdioFile
    00126
    00127 ULONGLONG CTextFile::GetPosition() const
    00128 {
    00129         return(CStdioFile::GetPosition() - m_offset);
    00130 }
    00131
    00132 ULONGLONG CTextFile::GetLength() const
    00133 {
    00134         return(CStdioFile::GetLength() - m_offset);
    00135 }
    00136
    00137 ULONGLONG CTextFile::Seek(LONGLONG lOff, UINT nFrom)
    00138 {
    00139         ULONGLONG pos = GetPosition();
    00140         ULONGLONG len = GetLength();
    00141
    00142         switch(nFrom)
    00143         {
    00144         default:
    00145         case begin: lOff = lOff; break;
    00146         case current: lOff = pos + lOff; break;
    00147         case end: lOff = len - lOff; break;
    00148         }
    00149
    00150         lOff = max(min(lOff, len), 0) + m_offset;
    00151
    00152         pos = CStdioFile::Seek(lOff, begin) - m_offset;
    00153
    00154         return(pos);
    00155 }
    00156
    00157 void CTextFile::WriteString(LPCSTR lpsz/*CStringA str*/)
    00158 {
    00159         CStringA str(lpsz);
    00160
    00161         if(m_encoding == ASCII)
    00162         {
    00163                 __super::WriteString(AToT(str));
    00164         }
    00165         else if(m_encoding == UTF8)
    00166         {
    00167                 WriteString(AToW(str));
    00168         }
    00169         else if(m_encoding == LE16)
    00170         {
    00171                 WriteString(AToW(str));
    00172         }
    00173         else if(m_encoding == BE16)
    00174         {
    00175                 WriteString(AToW(str));
    00176         }
    00177 }
    00178
    00179 void CTextFile::WriteString(LPCWSTR lpsz/*CStringW str*/)
    00180 {
    00181         CStringW str(lpsz);
    00182
    00183         if(m_encoding == ASCII)
    00184         {
    00185                 __super::WriteString(WToT(str));
    00186         }
    00187         else if(m_encoding == UTF8)
    00188         {
    00189                 str.Replace(L"\n", L"\r\n");
    00190                 for(int i = 0; i < str.GetLength(); i++)
    00191                 {
    00192                         DWORD c = (WORD)str[i];
    00193
    00194                         if(0 <= c && c < 0x80) // 0xxxxxxx
    00195                         {
    00196                                 Write(&c, 1);
    00197                         }
    00198                         else if(0x80 <= c && c < 0x800) // 110xxxxx 10xxxxxx
    00199                         {
    00200                                 c = 0xc080|((c<<2)&0x1f00)|(c&0x003f);
    00201                                 Write((BYTE*)&c+1, 1);
    00202                                 Write(&c, 1);
    00203                         }
    00204                         else if(0x800 <= c && c < 0xFFFF) // 1110xxxx 10xxxxxx 10xxxxxx
    00205                         {
    00206                                 c = 0xe08080|((c<<4)&0x0f0000)|((c<<2)&0x3f00)|(c&0x003f);
    00207                                 Write((BYTE*)&c+2, 1);
    00208                                 Write((BYTE*)&c+1, 1);
    00209                                 Write(&c, 1);
    00210                         }
    00211                         else
    00212                         {
    00213                                 c = '?';
    00214                                 Write(&c, 1);
    00215                         }
    00216                 }
    00217         }
    00218         else if(m_encoding == LE16)
    00219         {
    00220                 str.Replace(L"\n", L"\r\n");
    00221                 Write((LPCWSTR)str, str.GetLength()*2);
    00222         }
    00223         else if(m_encoding == BE16)
    00224         {
    00225                 str.Replace(L"\n", L"\r\n");
    00226                 for(int i = 0; i < str.GetLength(); i++)
    00227                         str.SetAt(i, ((str[i]>>8)&0x00ff)|((str[i]<<8)&0xff00));
    00228                 Write((LPCWSTR)str, str.GetLength()*2);
    00229         }
    00230 }
    00231
    00232 BOOL CTextFile::ReadString(CStringA& str)
    00233 {
    00234         bool fEOF = true;
    00235
    00236         str.Empty();
    00237
    00238         if(m_encoding == ASCII)
    00239         {
    00240                 CString s;
    00241                 fEOF = !__super::ReadString(s);
    00242                 str = TToA(s);
    00243         }
    00244         else if(m_encoding == UTF8)
    00245         {
    00246                 BYTE b;
    00247                 while(Read(&b, sizeof(b)) == sizeof(b))
    00248                 {
    00249                         fEOF = false;
    00250                         char c = '?';
    00251                         if(!(b&0x80)) // 0xxxxxxx
    00252                         {
    00253                                 c = b&0x7f;
    00254                         }
    00255                         else if((b&0xe0) == 0xc0) // 110xxxxx 10xxxxxx
    00256                         {
    00257                                 if(Read(&b, sizeof(b)) != sizeof(b)) break;
    00258                         }
    00259                         else if((b&0xf0) == 0xe0) // 1110xxxx 10xxxxxx 10xxxxxx
    00260                         {
    00261                                 if(Read(&b, sizeof(b)) != sizeof(b)) break;
    00262                                 if(Read(&b, sizeof(b)) != sizeof(b)) break;
    00263                         }
    00264                         if(c == '\r') continue;
    00265                         if(c == '\n') break;
    00266                         str += c;
    00267                 }
    00268         }
    00269         else if(m_encoding == LE16)
    00270         {
    00271                 WORD w;
    00272                 while(Read(&w, sizeof(w)) == sizeof(w))
    00273                 {
    00274                         fEOF = false;
    00275                         char c = '?';
    00276                         if(!(w&0xff00)) c = w&0xff;
    00277                         if(c == '\r') continue;
    00278                         if(c == '\n') break;
    00279                         str += c;
    00280                 }
    00281         }
    00282         else if(m_encoding == BE16)
    00283         {
    00284                 WORD w;
    00285                 while(Read(&w, sizeof(w)) == sizeof(w))
    00286                 {
    00287                         fEOF = false;
    00288                         char c = '?';
    00289                         if(!(w&0xff)) c = w>>8;
    00290                         if(c == '\r') continue;
    00291                         if(c == '\n') break;
    00292                         str += c;
    00293                 }
    00294         }
    00295
    00296         return(!fEOF);
    00297 }
    00298
    00299 BOOL CTextFile::ReadString(CStringW& str)
    00300 {
    00301         bool fEOF = true;
    00302
    00303         str.Empty();
    00304
    00305         if(m_encoding == ASCII)
    00306         {
    00307                 CString s;
    00308                 fEOF = !__super::ReadString(s);
    00309                 str = TToW(s);
    00310         }
    00311         else if(m_encoding == UTF8)
    00312         {
    00313                 BYTE b;
    00314                 while(Read(&b, sizeof(b)) == sizeof(b))
    00315                 {
    00316                         fEOF = false;
    00317                         WCHAR c = '?';
    00318                         if(!(b&0x80)) // 0xxxxxxx
    00319                         {
    00320                                 c = b&0x7f;
    00321                         }
    00322                         else if((b&0xe0) == 0xc0) // 110xxxxx 10xxxxxx
    00323                         {
    00324                                 c = (b&0x1f)<<6;
    00325                                 if(Read(&b, sizeof(b)) != sizeof(b)) break;
    00326                                 c |= (b&0x3f);
    00327                         }
    00328                         else if((b&0xf0) == 0xe0) // 1110xxxx 10xxxxxx 10xxxxxx
    00329                         {
    00330                                 c = (b&0x0f)<<12;
    00331                                 if(Read(&b, sizeof(b)) != sizeof(b)) break;
    00332                                 c |= (b&0x3f)<<6;
    00333                                 if(Read(&b, sizeof(b)) != sizeof(b)) break;
    00334                                 c |= (b&0x3f);
    00335                         }
    00336                         if(c == '\r') continue;
    00337                         if(c == '\n') break;
    00338                         str += c;
    00339                 }
    00340         }
    00341         else if(m_encoding == LE16)
    00342         {
    00343                 WCHAR wc;
    00344                 while(Read(&wc, sizeof(wc)) == sizeof(wc))
    00345                 {
    00346                         fEOF = false;
    00347                         if(wc == '\r') continue;
    00348                         if(wc == '\n') break;
    00349                         str += wc;
    00350                 }
    00351         }
    00352         else if(m_encoding == BE16)
    00353         {
    00354                 WCHAR wc;
    00355                 while(Read(&wc, sizeof(wc)) == sizeof(wc))
    00356                 {
    00357                         fEOF = false;
    00358                         wc = ((wc>>8)&0x00ff)|((wc<<8)&0xff00);
    00359                         if(wc == '\r') continue;
    00360                         if(wc == '\n') break;
    00361                         str += wc;
    00362                 }
    00363         }
    00364
    00365         return(!fEOF);
    00366 }
    00367
    00368 //
    00369 // CWebTextFile
    00370 //
    00371
    00372 CWebTextFile::CWebTextFile(LONGLONG llMaxSize)
    00373         : m_llMaxSize(llMaxSize)
    00374 {
    00375 }
    00376
    00377 bool CWebTextFile::Open(LPCTSTR lpszFileName)
    00378 {
    00379         CString fn(lpszFileName);
    00380
    00381         if(fn.Find(_T("http://")) != 0)
    00382                 return __super::Open(lpszFileName);
    00383
    00384         try
    00385         {
    00386                 CInternetSession is;
    00387
    00388                 CAutoPtr<CStdioFile> f(is.OpenURL(fn, 1, INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_EXISTING_CONNECT));
    00389                 if(!f) return(false);
    00390
    00391                 TCHAR path[MAX_PATH];
    00392                 GetTempPath(MAX_PATH, path);
    00393
    00394                 fn = path + fn.Mid(fn.ReverseFind('/')+1);
    00395                 int i = fn.Find(_T("?"));
    00396                 if(i > 0) fn = fn.Left(i);
    00397                 CFile temp;
    00398                 if(!temp.Open(fn, modeCreate|modeWrite|typeBinary|shareDenyWrite))
    00399                 {
    00400                         f->Close();
    00401                         return(false);
    00402                 }
    00403
    00404                 BYTE buff[1024];
    00405                 int len, total = 0;
    00406                 while((len = f->Read(buff, 1024)) == 1024 && (m_llMaxSize < 0 || (total+=1024) < m_llMaxSize))
    00407                         temp.Write(buff, len);
    00408                 if(len > 0) temp.Write(buff, len);
    00409
    00410                 m_tempfn = fn;
    00411
    00412                 f->Close(); // must close it because the desctructor doesn't seem to do it and we will get an exception when "is" is destroying
    00413         }
    00414         catch(CInternetException* ie)
    00415         {
    00416                 ie->Delete();
    00417                 return(false);
    00418         }
    00419
    00420         return __super::Open(m_tempfn);
    00421 }
    00422
    00423 bool CWebTextFile::Save(LPCTSTR lpszFileName, enc e)
    00424 {
    00425         // CWebTextFile is read-only...
    00426         ASSERT(0);
    00427         return(false);
    00428 }
    00429
    00430 void CWebTextFile::Close()
    00431 {
    00432         __super::Close();
    00433
    00434         if(!m_tempfn.IsEmpty())
    00435         {
    00436                 _tremove(m_tempfn);
    00437                 m_tempfn.Empty();
    00438         }
    00439 }
    00440
    00442
    00443 CStringW AToW(CStringA str)
    00444 {
    00445         CStringW ret;
    00446         for(int i = 0, j = str.GetLength(); i < j; i++)
    00447                 ret += (WCHAR)(BYTE)str[i];
    00448         return(ret);
    00449 }
    00450
    00451 CStringA WToA(CStringW str)
    00452 {
    00453         CStringA ret;
    00454         for(int i = 0, j = str.GetLength(); i < j; i++)
    00455                 ret += (CHAR)(WORD)str[i];
    00456         return(ret);
    00457 }
    00458
    00459 CString AToT(CStringA str)
    00460 {
    00461         CString ret;
    00462         for(int i = 0, j = str.GetLength(); i < j; i++)
    00463                 ret += (TCHAR)(BYTE)str[i];
    00464         return(ret);
    00465 }
    00466
    00467 CString WToT(CStringW str)
    00468 {
    00469         CString ret;
    00470         for(int i = 0, j = str.GetLength(); i < j; i++)
    00471                 ret += (TCHAR)(WORD)str[i];
    00472         return(ret);
    00473 }
    00474
    00475 CStringA TToA(CString str)
    00476 {
    00477         CStringA ret;
    00478 #ifdef UNICODE
    00479         for(int i = 0, j = str.GetLength(); i < j; i++)
    00480                 ret += (CHAR)(BYTE)str[i];
    00481 #else
    00482         ret = str;
    00483 #endif
    00484         return(ret);
    00485 }
    00486
    00487 CStringW TToW(CString str)
    00488 {
    00489         CStringW ret;
    00490 #ifdef UNICODE
    00491         ret = str;
    00492 #else
    00493         for(int i = 0, j = str.GetLength(); i < j; i++)
    00494                 ret += (WCHAR)(BYTE)str[i];
    00495 #endif
    00496         return(ret);
    00497 }