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 }

Generated on Tue Dec 13 14:47:55 2005 for guliverkli by  doxygen 1.4.5