1 : /******************************************************************************
2 : * $Id: ogrdxf_diskio.cpp 18223 2009-12-09 01:15:31Z warmerdam $
3 : *
4 : * Project: DXF Translator
5 : * Purpose: Implements Disk IO and low level parsing portions of the
6 : * OGRDXFDataSource class
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "ogr_dxf.h"
32 : #include "cpl_conv.h"
33 : #include "cpl_string.h"
34 : #include "cpl_csv.h"
35 :
36 : CPL_CVSID("$Id: ogrdxf_diskio.cpp 18223 2009-12-09 01:15:31Z warmerdam $");
37 :
38 : /************************************************************************/
39 : /* ResetReadPointer() */
40 : /************************************************************************/
41 :
42 4 : void OGRDXFDataSource::ResetReadPointer( int iNewOffset )
43 :
44 : {
45 4 : nSrcBufferBytes = 0;
46 4 : iSrcBufferOffset = 0;
47 4 : iSrcBufferFileOffset = iNewOffset;
48 4 : nLastValueSize = 0;
49 :
50 4 : VSIFSeekL( fp, iNewOffset, SEEK_SET );
51 4 : }
52 :
53 : /************************************************************************/
54 : /* LoadDiskChunk() */
55 : /* */
56 : /* Load another block (512 bytes) of input from the source */
57 : /* file. */
58 : /************************************************************************/
59 :
60 29 : void OGRDXFDataSource::LoadDiskChunk()
61 :
62 : {
63 29 : CPLAssert( iSrcBufferOffset >= 0 );
64 :
65 29 : if( nSrcBufferBytes - iSrcBufferOffset > 511 )
66 0 : return;
67 :
68 29 : if( iSrcBufferOffset > 0 )
69 : {
70 26 : CPLAssert( nSrcBufferBytes <= 1024 );
71 26 : CPLAssert( iSrcBufferOffset <= nSrcBufferBytes );
72 :
73 : memmove( achSrcBuffer, achSrcBuffer + iSrcBufferOffset,
74 26 : nSrcBufferBytes - iSrcBufferOffset );
75 26 : iSrcBufferFileOffset += iSrcBufferOffset;
76 26 : nSrcBufferBytes -= iSrcBufferOffset;
77 26 : iSrcBufferOffset = 0;
78 : }
79 :
80 : nSrcBufferBytes += VSIFReadL( achSrcBuffer + nSrcBufferBytes,
81 29 : 1, 512, fp );
82 29 : achSrcBuffer[nSrcBufferBytes] = '\0';
83 :
84 29 : CPLAssert( nSrcBufferBytes <= 1024 );
85 29 : CPLAssert( iSrcBufferOffset <= nSrcBufferBytes );
86 : }
87 :
88 : /************************************************************************/
89 : /* ReadValue() */
90 : /* */
91 : /* Read one type code and value line pair from the DXF file. */
92 : /************************************************************************/
93 :
94 977 : int OGRDXFDataSource::ReadValue( char *pszValueBuf, int nValueBufSize )
95 :
96 : {
97 : /* -------------------------------------------------------------------- */
98 : /* Make sure we have lots of data in our buffer for one value. */
99 : /* -------------------------------------------------------------------- */
100 977 : if( nSrcBufferBytes - iSrcBufferOffset < 512 )
101 29 : LoadDiskChunk();
102 :
103 977 : if( nValueBufSize > 512 )
104 0 : nValueBufSize = 512;
105 :
106 : /* -------------------------------------------------------------------- */
107 : /* Capture the value code, and skip past it. */
108 : /* -------------------------------------------------------------------- */
109 977 : int iStartSrcBufferOffset = iSrcBufferOffset;
110 977 : int nValueCode = atoi(achSrcBuffer + iSrcBufferOffset);
111 :
112 : // proceed to newline.
113 10747 : while( achSrcBuffer[iSrcBufferOffset] != '\n'
114 2931 : && achSrcBuffer[iSrcBufferOffset] != '\r'
115 2931 : && achSrcBuffer[iSrcBufferOffset] != '\0' )
116 2931 : iSrcBufferOffset++;
117 :
118 : // skip past newline. CR, CRLF, or LFCR
119 2931 : if( (achSrcBuffer[iSrcBufferOffset] == '\r'
120 0 : && achSrcBuffer[iSrcBufferOffset+1] == '\n' )
121 977 : || (achSrcBuffer[iSrcBufferOffset] == '\n'
122 977 : && achSrcBuffer[iSrcBufferOffset+1] == '\r' ) )
123 0 : iSrcBufferOffset += 2;
124 : else
125 977 : iSrcBufferOffset += 1;
126 :
127 977 : if( achSrcBuffer[iSrcBufferOffset] == '\0' )
128 0 : return -1;
129 :
130 : /* -------------------------------------------------------------------- */
131 : /* Capture the value string. */
132 : /* -------------------------------------------------------------------- */
133 977 : int iEOL = iSrcBufferOffset;
134 :
135 : // proceed to newline.
136 25258 : while( achSrcBuffer[iEOL] != '\n'
137 7768 : && achSrcBuffer[iEOL] != '\r'
138 7768 : && achSrcBuffer[iEOL] != '\0' )
139 7768 : iEOL++;
140 :
141 977 : if( achSrcBuffer[iEOL] == '\0' )
142 0 : return -1;
143 :
144 977 : if( (iEOL - iSrcBufferOffset) > nValueBufSize-1 )
145 : {
146 : strncpy( pszValueBuf, achSrcBuffer + iSrcBufferOffset,
147 0 : nValueBufSize-1 );
148 0 : pszValueBuf[nValueBufSize-1] = '\0';
149 :
150 : CPLDebug( "DXF", "Long line truncated to %d characters.\n%s...",
151 : nValueBufSize-1,
152 0 : pszValueBuf );
153 : }
154 : else
155 : {
156 : strncpy( pszValueBuf, achSrcBuffer + iSrcBufferOffset,
157 977 : iEOL - iSrcBufferOffset );
158 977 : pszValueBuf[iEOL - iSrcBufferOffset] = '\0';
159 : }
160 :
161 977 : iSrcBufferOffset = iEOL;
162 :
163 : // skip past newline. CR, CRLF, or LFCR
164 2931 : if( (achSrcBuffer[iSrcBufferOffset] == '\r'
165 0 : && achSrcBuffer[iSrcBufferOffset+1] == '\n' )
166 977 : || (achSrcBuffer[iSrcBufferOffset] == '\n'
167 977 : && achSrcBuffer[iSrcBufferOffset+1] == '\r' ) )
168 0 : iSrcBufferOffset += 2;
169 : else
170 977 : iSrcBufferOffset += 1;
171 :
172 : /* -------------------------------------------------------------------- */
173 : /* Record how big this value was, so it can be unread safely. */
174 : /* -------------------------------------------------------------------- */
175 977 : nLastValueSize = iSrcBufferOffset - iStartSrcBufferOffset;
176 :
177 : /* -------------------------------------------------------------------- */
178 : /* Is this a comment? If so, tail recurse to get another line. */
179 : /* -------------------------------------------------------------------- */
180 977 : if( nValueCode == 999 )
181 1 : return ReadValue(pszValueBuf,nValueBufSize);
182 : else
183 976 : return nValueCode;
184 : }
185 :
186 : /************************************************************************/
187 : /* UnreadValue() */
188 : /* */
189 : /* Unread the last value read, accomplished by resetting the */
190 : /* read pointer. */
191 : /************************************************************************/
192 :
193 20 : void OGRDXFDataSource::UnreadValue()
194 :
195 : {
196 20 : CPLAssert( iSrcBufferOffset >= nLastValueSize );
197 20 : CPLAssert( nLastValueSize > 0 );
198 :
199 20 : iSrcBufferOffset -= nLastValueSize;
200 :
201 20 : nLastValueSize = 0;
202 20 : }
203 :
|