📄 e00write.c
字号:
/********************************************************************** * $Id: e00write.c,v 1.1.1.1 2006/06/26 15:38:27 oconrad Exp $ * * Name: e00write.c * Project: Compressed E00 Read/Write library * Language: ANSI C * Purpose: Functions to write Compressed E00 files from a stream of * uncompressed lines. * Author: Daniel Morissette, danmo@videotron.ca * * $Log: e00write.c,v $ * Revision 1.1.1.1 2006/06/26 15:38:27 oconrad * no message * * Revision 1.1.1.1 2005/08/31 14:01:00 oconrad * no message * * Revision 1.1.1.1 2005/08/17 08:25:16 oconrad * no message * * Revision 1.1.1.1 2005/08/15 13:35:12 oconrad * no message * * Revision 1.1 2004/04/16 13:36:45 oconrad * no message * * Revision 1.5 1999/02/25 18:46:41 daniel * Now use CPL for Error handling, Memory allocation, and File access. * * Revision 1.4 1999/01/08 17:40:01 daniel * Added E00WriteCallbackOpen() * * Revision 1.3 1998/11/13 16:54:23 daniel * Check for '\r' and '\n' at end of input line while compressing, just * in case... * * Revision 1.2 1998/11/13 15:48:42 daniel * Simplified the generation of the compression codes for numbers * (use a logical rule instead of going case by case) * * Revision 1.1 1998/11/13 14:19:51 daniel * Initial revision * ********************************************************************** * Copyright (c) 1998, 1999, Daniel Morissette * * All rights reserved. This software may be copied or reproduced, in * all or in part, without the prior written consent of its author, * Daniel Morissette (danmo@videotron.ca). However, any material copied * or reproduced must bear the original copyright notice (above), this * original paragraph, and the original disclaimer (below). * * The entire risk as to the results and performance of the software, * supporting text and other information contained in this file * (collectively called the "Software") is with the user. Although * considerable efforts have been used in preparing the Software, the * author does not warrant the accuracy or completeness of the Software. * In no event will the author be liable for damages, including loss of * profits or consequential damages, arising out of the use of the * Software. * **********************************************************************/#include <stdlib.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <stdarg.h>#include "e00compr.h"static int _CompressLine(E00WritePtr psInfo, const char *pszLine);static int _WriteNextCompressedLine(E00WritePtr psInfo, int nMaxChars);static int _PrintfNextLine(E00WritePtr psInfo, const char *pszFmt, ...);/********************************************************************** * E00WriteOpen() * * Try to open output file, and alloc/initialize a new E00WritePtr * handle. * * nComprLevel must be one of: * E00_COMPR_NONE, E00_COMPR_PARTIAL or E00_COMPR_FULL * * Returns the new handle, or NULL if the file could not be opened. * E00WriteClose() will eventually have to be called to release * the resources used by the new handle. **********************************************************************/E00WritePtr E00WriteOpen(const char *pszFname, int nComprLevel){ E00WritePtr psInfo = NULL; FILE *fp; CPLErrorReset(); /* Open the file */ fp = VSIFOpen(pszFname, "wt"); if (fp == NULL) { CPLError(CE_Failure, CPLE_OpenFailed, "Failed to open %s: %s", pszFname, strerror(errno)); return NULL; } /* Allocate and initialize a E00ReadPtr handle. */ psInfo = (E00WritePtr)CPLCalloc(1, sizeof(struct _E00WriteInfo)); psInfo->fp = fp; psInfo->nComprLevel = nComprLevel; return psInfo;}/********************************************************************** * E00WriteCallbackOpen() * * This is an alternative to E00WriteOpen() for cases where you want to * do all the file management yourself. You open/close the file yourself * and provide a callback functions to write one line at a time to the * file. pRefData is your handle on the physical file and can * be whatever you want... it is not used by the library, it will be * passed directly to your callback function when it is called. * * The callback function must have the following C prototype: * * int myWriteNextLine(void *pRefData, const char *pszLine); * * Like printf() does, myWriteNextLine() should return a positive * value on success (the number of chars written) * or -1 if an error happened. * The value passed by the library in pszLine will not be terminated * by a '\n' character... it is assumed that the myWriteNextLine() * implementation will take care of terminating the line with a * '\n' if necessary. * * nComprLevel must be one of: * E00_COMPR_NONE, E00_COMPR_PARTIAL or E00_COMPR_FULL * * E00WriteCallbackOpen() returns a new E00ReadWritePtr handle. * E00WriteClose() will eventually have to be called to release * the resources used by the new handle. **********************************************************************/E00WritePtr E00WriteCallbackOpen(void *pRefData, int (*pfnWriteNextLine)(void *, const char *), int nComprLevel){ E00WritePtr psInfo = NULL; CPLErrorReset(); /* Make sure we received a valid function pointer */ if (pfnWriteNextLine == NULL) { CPLError(CE_Failure, CPLE_IllegalArg, "Invalid function pointer!"); return NULL; } /* Allocate and initialize a E00ReadPtr handle. */ psInfo = (E00WritePtr)CPLCalloc(1, sizeof(struct _E00WriteInfo)); psInfo->pRefData = pRefData; psInfo->pfnWriteNextLine = pfnWriteNextLine; psInfo->nComprLevel = nComprLevel; return psInfo;}/********************************************************************** * E00WriteClose() * * Close output file and release any memory used by the E00WritePtr. **********************************************************************/void E00WriteClose(E00WritePtr psInfo){ CPLErrorReset(); if (psInfo) { /* Flush output buffer before closing file. */ if (psInfo->iOutBufPtr > 0) _WriteNextCompressedLine(psInfo, 1); if (psInfo->fp) fclose(psInfo->fp); CPLFree(psInfo); }}/********************************************************************** * E00WriteNextLine() * * Take a line of what should be headed to a uncompressed E00 file, * convert it to the requested compression level, and write the * compressed result to the output file. * * Returns 0 if the line was processed succesfully, or an error number * (> 0) if an error happened. **********************************************************************/int E00WriteNextLine(E00WritePtr psInfo, const char *pszLine){ char *pszPtr; int nStatus = 0; CPLErrorReset(); if (psInfo && (psInfo->fp || psInfo->pfnWriteNextLine)) { psInfo->nSrcLineNo++; if (psInfo->nComprLevel == E00_COMPR_NONE) { /* Uncompressed file... write line directly. */ nStatus = _PrintfNextLine(psInfo, "%s", pszLine); } else if (psInfo->nSrcLineNo == 1) { /* Header line in a compressed file... write line * after replacing "EXP 0" with "EXP 1". */ if ((pszPtr = strstr(pszLine, " 0")) != NULL) { nStatus = _PrintfNextLine(psInfo, "EXP 1%s", pszPtr+2); } else { /* Write line directly... assume that it contains a valid * EXP prefix! */ nStatus = _PrintfNextLine(psInfo, "%s", pszLine); } } else { /* FULL or PARTIAL compression... compress the current line, * (output goes in psInfo->szOutBuf) */ nStatus = _CompressLine(psInfo, pszLine); while (nStatus == 0 && psInfo->iOutBufPtr >= 80) { /* Time to write the first 80 chars from the output buffer */ nStatus = _WriteNextCompressedLine(psInfo, 0); } } } else { /* This should never happen unless the lib is not properly used * or if an error happened in previous calls and was ignored by * the caller */ CPLError(CE_Failure, CPLE_IllegalArg, "Invalid E00WritePtr handle!"); nStatus = 203; } return nStatus;}/********************************************************************** * _CompressLine() * * Compress one line of input, and store the compressed copy at the * end of psInfo->pszOutBuf. * * Returns 0 if the line was compressed succesfully, or an error number * (> 0) if an error happened. **********************************************************************/static int _CompressLine(E00WritePtr psInfo, const char *pszLine){ int nStatus = 0; int nDigits, nExpSign, nDotPosition, iCurPos; int numTotalDigits, numExpDigits; char n, *pszCodePos; int nStartOutBufPtr; const char *pszStartSrcPtr; while(*pszLine != '\0' && *pszLine != '\n' && *pszLine != '\r') { /*------------------------------------------------------------- * By default, apply PARTIAL compression * Note that PARTIAL is a subset of FULL compression. *------------------------------------------------------------*/ if (*pszLine == '~') { /* The '~' char is encoded as "~~" */ strcpy( psInfo->szOutBuf+psInfo->iOutBufPtr, "~~"); psInfo->iOutBufPtr += 2; } else if (strncmp(pszLine, " ", 3) == 0) { /* A stream of at least 3 spaces. * Count number of spaces and replace with a "~ n" code */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -