?? stdio.cpp
字號:
* Append "t" or "b" for text and binary mode.
* "tu" forces the text-mode to Unicode; "ts" to Ansi.
*/
BOOL CXFileStream::Open(const TCHAR* pszPathName, const char* pszMode)
{
if (NULL != _h)
Close();
BOOL fTruncate = FALSE, fCreateIfNecessary = FALSE;
// Crack the 'mode' arg
_fReading = _fWriting = _fAppending = FALSE;
switch (*pszMode++)
{
case 'r':
_fReading = TRUE;
fCreateIfNecessary = FALSE;
break;
case 'w':
_fWriting = TRUE;
fTruncate = TRUE;
fCreateIfNecessary = TRUE;
break;
case 'a':
_fWriting = TRUE;
_fAppending = TRUE;
fTruncate = FALSE;
fCreateIfNecessary = TRUE;
break;
default:
return FALSE;
}
BOOL fForceUnicode = FALSE;
BOOL fForceANSI = FALSE;
BOOL fForceCooked = FALSE;
BOOL fForceRaw = FALSE;
while (*pszMode)
{
switch (*pszMode++)
{
case '+':
if (_fReading) // r
_fWriting = TRUE;
else if (_fWriting) // w, a
_fReading = TRUE;
break;
case 't':
if (fForceRaw)
return FALSE;
fForceCooked = TRUE;
break;
case 'u':
if (fForceANSI || fForceRaw)
return FALSE;
fForceCooked = TRUE;
fForceUnicode = TRUE;
break;
case 's':
if (fForceUnicode || fForceRaw)
return FALSE;
fForceCooked = TRUE;
fForceANSI = TRUE;
break;
case 'b':
if (fForceCooked)
return FALSE;
fForceRaw = TRUE;
break;
default:
return FALSE;
}
}
// Default read/write modes.
// Lets i/o to native textfiles (e.g. *.scm) succeed.
// Pocket Office uses ANSI textfiles! Go figure. Win95 braindamage?
_fCooked = fForceCooked || !fForceRaw; // if neither, default to cooked
_fUseUnicode = !(fForceANSI || !fForceUnicode); // if neither, default to ansi
DWORD dwAccess = 0L;
if (_fReading)
dwAccess |= GENERIC_READ;
if (_fWriting)
dwAccess |= GENERIC_WRITE;
DWORD dwShare = FILE_SHARE_READ;
if (!_fWriting)
dwShare |= FILE_SHARE_WRITE;
DWORD dwCreate = 0L;
if (!fCreateIfNecessary)
dwCreate = OPEN_EXISTING;
else if (fTruncate)
dwCreate = CREATE_ALWAYS;
else
dwCreate = OPEN_ALWAYS;
HANDLE h = ::CreateFile(pszPathName, dwAccess, dwShare, NULL, dwCreate, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == h)
return FALSE;
_h = h;
BOOL fFoundUnicodeBOM = FALSE;
if (_fCooked && _fReading)
{
// For read-only files, the presence or absence of the Unicode start sequence
// dictates Unicode-mode, rather than the mode flags.
WCHAR wch;
DWORD cbReadActual = 0L;
if (::ReadFile(_h, &wch, sizeof(wch), &cbReadActual, NULL)
&& (sizeof(wch) == cbReadActual)
&& (wch == 0xFEFF))
{
// Indeed, file is Unicode.
_fUseUnicode = TRUE;
fFoundUnicodeBOM = TRUE;
}
else
{
::SetFilePointer(_h, 0, NULL, FILE_BEGIN);
if (!_fWriting)
_fUseUnicode = FALSE;
}
}
if (_fCooked && _fWriting && _fUseUnicode && !fFoundUnicodeBOM)
{
// New cooked-output Unicode files need the Unicode BOM.
WCHAR wch = 0xFEFF;
DWORD cbWritten = 0L;
if (::WriteFile(_h, &wch, sizeof(wch), &cbWritten, NULL)
&& (sizeof(wch) == cbWritten))
{
// File successfully stamped as Unicode.
fFoundUnicodeBOM = TRUE;
}
else
{
::CloseHandle(_h);
_h = NULL;
return FALSE;
}
}
return TRUE;
}
FILE *fopen( const char *filename, const char *mode )
{
for (int i = 0; i < MAXOPENFILES; ++i)
{
if (!RgStdioFiles[i].fActive)
{
TCHAR szPath[260+1];
int cch = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, filename, -1,
szPath, sizeof(szPath)/sizeof(TCHAR));
if (0 == cch)
return NULL;
CXFileStream* pstream = new CXFileStream;
if (!pstream)
return NULL;
if (!pstream->Open(szPath, mode))
{
delete pstream;
return NULL;
}
RgStdioFiles[i].pstream = pstream;
RgStdioFiles[i].fActive = TRUE;
return &RgStdioFiles[i];
}
}
return NULL;
}
int fflush( FILE *stream )
{
if (IsInvalidFile(stream))
return -1;
stream->pstream->Flush();
return 0;
}
int fclose( FILE *stream )
{
if (IsInvalidFile(stream))
return -1;
if (stdin == stream || stdout == stream)
return -1;
((CXFileStream*)(stream->pstream))->Close();
delete stream->pstream;
stream->pstream = NULL;
stream->fActive = FALSE;
return 0;
}
size_t fread( void *buffer, size_t size, size_t count, FILE *stream )
{
if (IsInvalidFile(stream))
return -1;
unsigned cbActual;
stream->pstream->Read((BYTE*)buffer, size*count, &cbActual);
return (size_t)cbActual;
}
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream )
{
if (IsInvalidFile(stream))
return -1;
unsigned cbActual;
stream->pstream->Write((BYTE*)buffer, size*count, &cbActual);
return (size_t)cbActual;
}
int getc( FILE *stream )
{
if (IsInvalidFile(stream))
return -1;
unsigned char ch;
unsigned cbActual = 0;
stream->pstream->Read(&ch, 1, &cbActual);
if (cbActual != 1)
return EOF;
return (int)ch;
}
int putc( int c, FILE *stream )
{
if (IsInvalidFile(stream))
return -1;
unsigned char ch = (unsigned char)(unsigned int)c;
unsigned cbActual = 0;
stream->pstream->Write(&ch, 1, &cbActual);
if (cbActual != 1)
return EOF;
return (int)ch;
}
int ungetc( int c, FILE *stream )
{
if (IsInvalidFile(stream))
return -1;
if (EOF != c)
stream->pstream->Pushback((unsigned char)(unsigned int)c);
return c;
}
long ftell( FILE *stream )
{
if (IsInvalidFile(stream))
return -1;
return (long)(stream->pstream->Tell());
}
int fseek( FILE *stream, long offset, int origin )
{
if (IsInvalidFile(stream))
return -1;
if (!stream->pstream->Seek(offset, origin))
return -1; // error
return 0;
}
char *fgets( char *string, int n, FILE *stream )
{
if (IsInvalidFile(stream))
return NULL;
char* pch = string;
int cchRemaining = n-1;
CXStdioStream *const pstream = stream->pstream;
while (cchRemaining-- > 0)
{
unsigned char ch;
unsigned cbActual = 0;
pstream->Read(&ch, 1, &cbActual);
if (cbActual != 1)
{
*pch = 0;
return NULL;
}
*pch++ = ch;
if ('\n' == ch)
break;
}
*pch = 0;
return string;
}
int fputs( const char *string, FILE *stream )
{
if (IsInvalidFile(stream))
return -1;
const unsigned cbGiven = strlen(string);
unsigned cbActual = 0;
stream->pstream->Write((const BYTE*)string, cbGiven, &cbActual);
return (cbGiven == cbActual ? 1 : EOF);
}
static int _output(char* buffer, const char* format, va_list argptr)
{
int cchFormat = strlen(format);
TCHAR szFormat[128];
const int cchFormatMax = sizeof(szFormat)/sizeof(TCHAR)-1;
if (cchFormat > cchFormatMax)
return 0;
int i = mbstowcs(szFormat, format, cchFormatMax);
if (((size_t)-1) == ((size_t)i))
return 0;
if (cchFormatMax == i)
szFormat[cchFormatMax] = 0;
cchFormat = i;
// Patch format string to accommodate CE's Unicode sensibilities
// %s -> %S
// %c -> %C
BOOL fFmt; // set when within a format-specifier
for (i = 0, fFmt = FALSE; i < cchFormatMax && szFormat[i] != 0; ++i)
{
switch (szFormat[i])
{
case L'%':
fFmt = !fFmt;
break;
case L'0':
case L'1':
case L'2':
case L'3':
case L'4':
case L'5':
case L'6':
case L'7':
case L'8':
case L'9':
case L'.':
// Precision/width specifier: part of format
break;
case L'c':
if (fFmt)
{
szFormat[i] = L'C';
fFmt = FALSE;
}
break;
case L's':
if (fFmt)
{
szFormat[i] = L'S';
fFmt = FALSE;
}
break;
default:
if (fFmt)
fFmt = FALSE;
break;
}
}
// Put a fence on either side of output buffer to detect overflow.
//$ BUGBUG - no bounds checking on this small buffer.
// I wish that the CE RTL had _vnswprintf
volatile int nFence0 = 1;
TCHAR szOut[256];
volatile int nFence1 = 1;
const int cchOutMax = sizeof(szOut)/sizeof(TCHAR)-1;
// This version from the crt (as opposed to wvsprintf) handles %g
i = vswprintf(szOut, szFormat, argptr);
assert(nFence0 == 1 && nFence1 == 1);
if (nFence0 != 1 || nFence1 != 1)
return 0;
if (0 == i)
return 0;
if (cchOutMax == i)
szOut[cchOutMax] = 0;
// Now convert to mbcs.
//$ REVIEW - if xstdio had wide-char entry points,
// the fprintf version could zap this here into WriteW,
// saving a wcs-to-mbcs-to-wcs round trip
i = wcstombs(buffer, szOut, cchOutMax);
if (((size_t)-1) == ((size_t)i))
return 0;
if (cchOutMax == i)
buffer[cchOutMax] = 0;
return i;
}
int __cdecl sprintf( char *buffer, const char *format, ... )
{
va_list arglist;
va_start(arglist, format);
int i = _output(buffer, format, arglist);
va_end(arglist);
return i;
}
int __cdecl fprintf( FILE *stream, const char *format, ... )
{
if (IsInvalidFile(stream))
return 0;
char szTmp[256];
va_list arglist;
va_start(arglist, format);
int i = _output(szTmp, format, arglist);
va_end(arglist);
//$ REVIEW - would be good to short-circuit the wcs-mbcs-wcs loop
fputs(szTmp, stream);
return i;
}
int __cdecl printf( const char *format, ... )
{
if (IsInvalidFile(stdout))
return 0;
char szTmp[256];
va_list arglist;
va_start(arglist, format);
int i = _output(szTmp, format, arglist);
va_end(arglist);
//$ REVIEW - would be good to short-circuit the wcs-mbcs-wcs loop
fputs(szTmp, stdout);
return i;
}
int StdioCharReady( FILE *stream )
{
if (IsInvalidFile(stream))
return 0;
return (stream->pstream->CharReady());
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -