📄 e00read.c
字号:
}/********************************************************************** * _ReadNextSourceLine() * * Loads the next line from the source file in psInfo. * * psInfo->bEOF should be checked after this call. **********************************************************************/static void _ReadNextSourceLine(E00ReadPtr psInfo){ if (!psInfo->bEOF) { psInfo->iInBufPtr = 0; psInfo->szInBuf[0] = '\0'; /* Read either using fgets() or psInfo->pfnReadNextLine() * depending on the way the file was opened... */ if (psInfo->pfnReadNextLine == NULL) { if (VSIFGets(psInfo->szInBuf,E00_READ_BUF_SIZE,psInfo->fp) == NULL) { /* We reached EOF */ psInfo->bEOF = 1; } } else { const char *pszLine; pszLine = psInfo->pfnReadNextLine(psInfo->pRefData); if (pszLine) { strncpy(psInfo->szInBuf, pszLine, E00_READ_BUF_SIZE); } else { /* We reached EOF */ psInfo->bEOF = 1; } } if (!psInfo->bEOF) { /* A new line was succesfully read. Remove trailing '\n' if any. * (Note: For Unix systems, we also have to check for '\r') */ int nLen; nLen = strlen(psInfo->szInBuf); while(nLen > 0 && (psInfo->szInBuf[nLen-1] == '\n' || psInfo->szInBuf[nLen-1] == '\r' ) ) { nLen--; psInfo->szInBuf[nLen] = '\0'; } psInfo->nInputLineNo++; } }}/********************************************************************** * _GetNextSourceChar() * * Returns the next char from the source file input buffer... and * reload the input buffer when necessary... this function makes the * whole input file appear as one huge null-terminated string with * no line delimiters. * * Will return '\0' when EOF is reached. **********************************************************************/static char _GetNextSourceChar(E00ReadPtr psInfo){ char c = '\0'; if (!psInfo->bEOF) { if (psInfo->szInBuf[psInfo->iInBufPtr] == '\0') { _ReadNextSourceLine(psInfo); c = _GetNextSourceChar(psInfo); } else { c = psInfo->szInBuf[psInfo->iInBufPtr++]; } } return c;}/********************************************************************** * _UngetSourceChar() * * Reverse the effect of the previous call to _GetNextSourceChar() by * moving the input buffer pointer back 1 character. * * This function can be called only once per call to _GetNextSourceChar() * (i.e. you cannot unget more than one character) otherwise the pointer * could move before the beginning of the input buffer. **********************************************************************/static void _UngetSourceChar(E00ReadPtr psInfo){ if (psInfo->iInBufPtr > 0) psInfo->iInBufPtr--; else { /* This error can happen only if _UngetSourceChar() is called * twice in a row (which should never happen!). */ CPLError(CE_Failure, CPLE_AssertionFailed, "UNEXPECTED INTERNAL ERROR: _UngetSourceChar() " "failed while reading line %d.", psInfo->nInputLineNo); }}/********************************************************************** * _UncompressNextLine() * * Uncompress one line of input and return a reference to an internal * buffer containing the uncompressed output. **********************************************************************/static const char *_UncompressNextLine(E00ReadPtr psInfo){ char c; int bEOL = 0; /* Set to 1 when End of Line reached */ int iOutBufPtr = 0, i, n; int iDecimalPoint, bOddNumDigits, iCurDigit; char *pszExp; int bPreviousCodeWasNumeric = 0; while(!bEOL && (c=_GetNextSourceChar(psInfo)) != '\0') { if (c != '~') { /* Normal character... just copy it */ psInfo->szOutBuf[iOutBufPtr++] = c; bPreviousCodeWasNumeric = 0; } else /* c == '~' */ { /* ======================================================== * Found an encoded sequence. * =======================================================*/ c = _GetNextSourceChar(psInfo); /* -------------------------------------------------------- * Compression level 1: only spaces, '~' and '\n' are encoded * -------------------------------------------------------*/ if (c == ' ') { /* "~ " followed by number of spaces */ c = _GetNextSourceChar(psInfo); n = c - ' '; for(i=0; i<n; i++) psInfo->szOutBuf[iOutBufPtr++] = ' '; bPreviousCodeWasNumeric = 0; } else if (c == '}') { /* "~}" == '\n' */ bEOL = 1; bPreviousCodeWasNumeric = 0; } else if (bPreviousCodeWasNumeric) { /* If the previous code was numeric, then the only valid code * sequences are the ones above: "~ " and "~}". If we end up * here, it is because the number was followed by a '~' but * this '~' was not a code, it only marked the end of a * number that was not followed by any space. * * We should simply ignore the '~' and return the character * that follows it directly. */ psInfo->szOutBuf[iOutBufPtr++] = c; bPreviousCodeWasNumeric = 0; } else if (c == '~' || c == '-') { /* "~~" and "~-" are simple escape sequences for '~' and '-' */ psInfo->szOutBuf[iOutBufPtr++] = c; } /* -------------------------------------------------------- * Compression level 2: numeric values are encoded. * * All codes for this level are in the form "~ c0 c1 c2 ... cn" * where: * * ~ marks the beginning of a new code sequence * * c0 is a single character code defining the format * of the number (decimal position, exponent, * and even or odd number of digits) * * c1 c2 ... cn each of these characters represent a pair of * digits of the encoded value with '!' == 00 * values 92..99 are encoded on 2 chars that * must be added to each other * (i.e. 92 == }!, 93 == }", ...) * * The sequence ends with a ' ' or a '~' character * -------------------------------------------------------*/ else if (c >= '!' && c <= 'z') { /* The format code defines 3 characteristics of the final number: * - Presence of a decimal point and its position * - Presence of an exponent, and its sign * - Odd or even number of digits */ n = c - '!'; iDecimalPoint = n % 15; /* 0 = no decimal point */ bOddNumDigits = n / 45; /* 0 = even num.digits, 1 = odd */ n = n / 15; if ( n % 3 == 1 ) pszExp = "E+"; else if (n % 3 == 2 ) pszExp = "E-"; else pszExp = NULL; /* Decode the c1 c2 ... cn value and apply the format. * Read characters until we encounter a ' ' or a '~' */ iCurDigit = 0; while((c=_GetNextSourceChar(psInfo)) != '\0' && c != ' ' && c != '~') { n = c - '!'; if (n == 92 && (c=_GetNextSourceChar(psInfo)) != '\0') n += c - '!'; psInfo->szOutBuf[iOutBufPtr++] = '0' + n/10; if (++iCurDigit == iDecimalPoint) psInfo->szOutBuf[iOutBufPtr++] = '.'; psInfo->szOutBuf[iOutBufPtr++] = '0' + n%10; if (++iCurDigit == iDecimalPoint) psInfo->szOutBuf[iOutBufPtr++] = '.'; } if (c == '~' || c == ' ') { bPreviousCodeWasNumeric = 1; _UngetSourceChar(psInfo); } /* If odd number of digits, then flush the last one */ if (bOddNumDigits) iOutBufPtr--; /* Insert the exponent string before the 2 last digits * (we assume the exponent string is 2 chars. long) */ if (pszExp) { for(i=0; i<2;i++) { psInfo->szOutBuf[iOutBufPtr] = psInfo->szOutBuf[iOutBufPtr-2]; psInfo->szOutBuf[iOutBufPtr-2] = pszExp[i]; iOutBufPtr++; } } } else { /* Unsupported code sequence... this is a possibility * given the fact that this library was written by * reverse-engineering the format! * * Send an error to the user and abort. * * If this error ever happens, and you are convinced that * the input file is not corrupted, then please report it to * me at danmo@videotron.ca, quoting the section of the input * file that produced it, and I'll do my best to add support * for this code sequence. */ CPLError(CE_Failure, CPLE_NotSupported, "Unexpected code \"~%c\" encountered in line %d.", c, psInfo->nInputLineNo); /* Force the program to abort by simulating a EOF */ psInfo->bEOF = 1; bEOL = 1; } }/* if c == '~' */ /* E00 lines should NEVER be longer than 80 chars. if we passed * that limit, then the input file is likely corrupt. */ if (iOutBufPtr > 80) { CPLError(CE_Failure, CPLE_FileIO, "Uncompressed line longer than 80 chars. " "Input file possibly corrupt around line %d.", psInfo->nInputLineNo); /* Force the program to abort by simulating a EOF */ psInfo->bEOF = 1; bEOL = 1; } }/* while !EOL */ psInfo->szOutBuf[iOutBufPtr++] = '\0'; return psInfo->szOutBuf;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -