|
|
/*+---------------------------------------------------------------------------
//
// mapio.c - mapped file i/o routines
//
// History:
// 9/4/97 DougP Create this header
allow and deal with input map files of zero length 11/20/97 DougP Move these routines from misc.c to here Add option to spec codepage //
// �1997 Microsoft Corporation
//----------------------------------------------------------------------------*/
#include <windows.h>
#include <assert.h>
#include "NLGlib.h"
//#ifdef WINCE
void Assert(x) { if (x) MessageBox(0,"assert","assert",MB_OK); } //#endif
BOOL WINAPI CloseMapFile(PMFILE pmf) { if (pmf==NULL) { return FALSE; }
// only unmap what existed - DougP
if (pmf->pvMap && !UnmapViewOfFile(pmf->pvMap)) { return FALSE; }
// ditto
if (pmf->hFileMap && !CloseHandle(pmf->hFileMap)) { return FALSE; }
if (!CloseHandle(pmf->hFile)) { return FALSE; }
NLGFreeMemory(pmf);
return TRUE; }
PMFILE WINAPI OpenMapFileWorker(const WCHAR * pwszFileName,BOOL fDstUnicode) { PMFILE pmf; const WCHAR * pwszExt;
if (!fNLGNewMemory(&pmf, sizeof(MFILE))) { goto Error; }
pmf->fDstUnicode = fDstUnicode;
#ifdef WINCE
pmf->hFile = CreateFileForMapping( #else
pmf->hFile = CMN_CreateFileW( #endif
pwszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (pmf->hFile == INVALID_HANDLE_VALUE) { goto Error; }
pmf->cbSize1 = GetFileSize(pmf->hFile, &pmf->cbSize2); if (pmf->cbSize1 == 0xFFFFFFFF) { CMN_OutputSystemErrW(L"Can't get size for", pwszFileName); CloseHandle(pmf->hFile); goto Error; } else if (pmf->cbSize1 == 0) { // can't map a zero length file so mark this appropriately
pmf->hFileMap = 0; pmf->pvMap = 0; pmf->fSrcUnicode = TRUE; } else { #ifdef WINCE
pmf->hFileMap = CreateFileMapping(pmf->hFile, NULL, PAGE_READONLY, 0, 0, NULL); #else
pmf->hFileMap = CreateFileMappingA(pmf->hFile, NULL, PAGE_READONLY, 0, 0, NULL); #endif
if (pmf->hFileMap == NULL) { CMN_OutputSystemErrW(L"Can't Map", pwszFileName); CloseHandle(pmf->hFile); goto Error; }
// Map the entire file starting at the first byte
//
pmf->pvMap = MapViewOfFile(pmf->hFileMap, FILE_MAP_READ, 0, 0, 0); if (pmf->pvMap == NULL) { CloseHandle(pmf->hFileMap); CloseHandle(pmf->hFile); goto Error; }
// HACK: Since IsTextUnicode returns false for sorted stem files, preset
// unicode status here based on utf file extension
pwszExt = pwszFileName; while (*pwszExt && *pwszExt != L'.' ) pwszExt++;
if (*pwszExt && !wcscmp(pwszExt, L".utf")) { pmf->fSrcUnicode = TRUE; } else if (pmf->cbSize1 >= 2 && *(WORD *)pmf->pvMap == 0xFEFF) { // Safe to assume that anything starting with a BOM is Unicode
pmf->fSrcUnicode = TRUE; } else { #ifdef WINCE
pmf->fSrcUnicode = TRUE; #else
pmf->fSrcUnicode = IsTextUnicode(pmf->pvMap, pmf->cbSize1, NULL); #endif
}
if (pmf->fSrcUnicode) { pmf->pwsz = (WCHAR *)pmf->pvMap; } else { pmf->psz = (PSTR)pmf->pvMap; } }
pmf->uCodePage = CP_ACP; // DWP - use default unless client specifies otherwise
return pmf;
Error: if (pmf) { NLGFreeMemory(pmf); } return NULL; }
#ifndef WINCE
PMFILE WINAPI OpenMapFileA(const char * pszFileName) { WCHAR * pwszFileName; DWORD cchFileNameLen; int iRet;
cchFileNameLen = lstrlenA(pszFileName) + 1; if (!fNLGNewMemory(&pwszFileName, cchFileNameLen * sizeof(WCHAR))) { return NULL; }
iRet = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszFileName, -1, pwszFileName, cchFileNameLen); if (iRet ==0) { NLGFreeMemory(pwszFileName); return NULL; }
return (OpenMapFileWorker(pwszFileName, FALSE)); }
#endif
BOOL WINAPI ResetMap(PMFILE pmf) { if (pmf == NULL) { return FALSE; }
if (pmf->fSrcUnicode) { pmf->pwsz = (WCHAR*)pmf->pvMap; if (*pmf->pwsz == 0xFEFF) { pmf->pwsz++; } } else { pmf->psz = (CHAR*)pmf->pvMap; }
return TRUE; }
// Same side effect as GetMapLine (incrememnt map pointer) but without returning contents
// in buffer. This is useful in situations where the line may be longer than the max cch and
// when the buffer isn't actually needed (counting lines, etc.)
//
BOOL WINAPI NextMapLine(PMFILE pmf) { DWORD cbOffset;
if (!pmf || !pmf->hFileMap) // check for zero length file
return FALSE;
if (pmf->fSrcUnicode) { WCHAR wch; cbOffset = (DWORD) ((PBYTE)pmf->pwsz - (PBYTE)pmf->pvMap);
// test for EOF
Assert (cbOffset <= pmf->cbSize1); if (cbOffset == pmf->cbSize1) return FALSE;
while (cbOffset < pmf->cbSize1) { cbOffset += sizeof(WCHAR); wch = *pmf->pwsz++;
// Break out if this is the newline or the control-Z
if (wch == 0x001A || wch == L'\n') break; } } else { CHAR ch; cbOffset = (DWORD) ((PBYTE)pmf->psz - (PBYTE)pmf->pvMap);
// test for EOF
Assert (cbOffset <= pmf->cbSize1); if (cbOffset == pmf->cbSize1) return FALSE;
while (cbOffset < pmf->cbSize1) { cbOffset += sizeof(CHAR); ch = *pmf->psz++;
// Break out if this is the newline or the control-Z
if (ch == 0x1A || ch == '\n') break; } }
return TRUE; }
PVOID WINAPI GetMapLine(PVOID pv0, DWORD cbMac, PMFILE pmf) { PVOID pv1; DWORD cbOffset, cbBuff;
Assert(pv0); // Make sure that the buffer is at least as big as the caller says it is.
// (If the buffer was allocated with the debug memory allocator, this access
// should cause an exception if pv0 isn't at least cbMac bytes long.
Assert(((char *)pv0)[cbMac-1] == ((char *)pv0)[cbMac-1]);
if (!pmf || !pmf->hFileMap) // check for zero length file
return NULL;
if (pmf->fSrcUnicode != pmf->fDstUnicode) { if (!fNLGNewMemory(&pv1, cbMac)) return NULL;
cbBuff = cbMac; } else { pv1 = pv0; }
if (pmf->fSrcUnicode) { WCHAR wch, *pwsz = pv1; cbOffset = (DWORD) ((PBYTE)pmf->pwsz - (PBYTE)pmf->pvMap);
// test for EOF
Assert (cbOffset <= pmf->cbSize1); if (cbOffset == pmf->cbSize1) goto Error;
// don't want deal with odd-sized buffers
if (cbMac % sizeof(WCHAR) != 0) cbMac -= (cbMac % sizeof(WCHAR));
// reserve space for terminating 0
//
Assert (cbMac > 0); cbMac -= sizeof(WCHAR);
while (cbOffset < pmf->cbSize1) { cbOffset += sizeof(WCHAR); wch = *pmf->pwsz++;
switch (wch) { case L'\r': case L'\n': // end of line
case 0xFEFF: // Unicode BOM
break; case 0x001A: // ctrl-Z
wch = L'\n'; // Replace it so that the last line can be read
break; default: *pwsz++ = wch; cbMac -= sizeof(WCHAR); }
// Break out if this is the newline or buffer is full
if (wch == L'\n' || cbMac <= 0) break; } *pwsz = L'\0'; } else { CHAR ch, *psz = pv1; cbOffset = (DWORD) ((PBYTE)pmf->psz - (PBYTE)pmf->pvMap);
// test for EOF
Assert (cbOffset <= pmf->cbSize1); if (cbOffset == pmf->cbSize1) goto Error;
// reserve space for terminating 0
//
Assert (cbMac > 0); cbMac -= sizeof(CHAR);
while (cbOffset < pmf->cbSize1) { cbOffset += sizeof(CHAR); ch = *pmf->psz++;
switch (ch) { case '\r': case '\n': // end of line
break; case 0x1A: // ctrl-Z
ch = '\n'; // Replace it so that the last line can be read
break; default: cbMac -= sizeof(CHAR); *psz++ = ch; }
// Break out if this is the newline or buffer is full
if (ch == '\n' || cbMac <= 0) break; } *psz = '\0'; }
if (pmf->fSrcUnicode != pmf->fDstUnicode) { DWORD cch = cbBuff; // our argument is a count of bytes
if (pmf->fDstUnicode) { // MultiByteToWideChar wants the size of the destination in wide characters
cch /= sizeof(WCHAR); cch = MultiByteToWideChar(pmf->uCodePage, MB_PRECOMPOSED,(PSTR)pv1,-1, (WCHAR *)pv0,cch); } else { cch = WideCharToMultiByte(pmf->uCodePage, 0, (WCHAR *)pv1, -1, (PSTR)pv0, cch, NULL, NULL); } if (cch == 0) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // Ignore truncation (for consistency with no-conversion cases)
//
if (pmf->fDstUnicode) { ((WCHAR *)pv0)[(cbBuff / sizeof(WCHAR)) - 1] = 0; } else { ((CHAR *)pv0)[cbBuff - 1] = 0; } } else { // not a truncation error
NLGFreeMemory(pv1); return NULL; } } NLGFreeMemory(pv1); }
return(pv0);
Error: if (pmf->fSrcUnicode != pmf->fDstUnicode) { NLGFreeMemory(pv1); } return NULL; }
|