1 : /******************************************************************************
2 : * $Id: ogrdxf_diskio.cpp 20278 2010-08-14 15:11:01Z warmerdam $
3 : *
4 : * Project: DXF Translator
5 : * Purpose: Implements low level DXF reading with caching and parsing of
6 : * of the code/value pairs.
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 20278 2010-08-14 15:11:01Z warmerdam $");
37 :
38 : /************************************************************************/
39 : /* OGRDXFReader() */
40 : /************************************************************************/
41 :
42 260 : OGRDXFReader::OGRDXFReader()
43 :
44 : {
45 260 : fp = NULL;
46 :
47 260 : iSrcBufferOffset = 0;
48 260 : nSrcBufferBytes = 0;
49 260 : iSrcBufferFileOffset = 0;
50 :
51 260 : nLastValueSize = 0;
52 260 : nLineNumber = 0;
53 260 : }
54 :
55 : /************************************************************************/
56 : /* ~OGRDXFReader() */
57 : /************************************************************************/
58 :
59 260 : OGRDXFReader::~OGRDXFReader()
60 :
61 : {
62 260 : }
63 :
64 : /************************************************************************/
65 : /* Initialize() */
66 : /************************************************************************/
67 :
68 44 : void OGRDXFReader::Initialize( VSILFILE *fp )
69 :
70 : {
71 44 : this->fp = fp;
72 44 : }
73 :
74 : /************************************************************************/
75 : /* ResetReadPointer() */
76 : /************************************************************************/
77 :
78 25 : void OGRDXFReader::ResetReadPointer( int iNewOffset )
79 :
80 : {
81 25 : nSrcBufferBytes = 0;
82 25 : iSrcBufferOffset = 0;
83 25 : iSrcBufferFileOffset = iNewOffset;
84 25 : nLastValueSize = 0;
85 25 : nLineNumber = 0;
86 :
87 25 : VSIFSeekL( fp, iNewOffset, SEEK_SET );
88 25 : }
89 :
90 : /************************************************************************/
91 : /* LoadDiskChunk() */
92 : /* */
93 : /* Load another block (512 bytes) of input from the source */
94 : /* file. */
95 : /************************************************************************/
96 :
97 2648 : void OGRDXFReader::LoadDiskChunk()
98 :
99 : {
100 2648 : CPLAssert( iSrcBufferOffset >= 0 );
101 :
102 2648 : if( nSrcBufferBytes - iSrcBufferOffset > 511 )
103 0 : return;
104 :
105 2648 : if( iSrcBufferOffset > 0 )
106 : {
107 2568 : CPLAssert( nSrcBufferBytes <= 1024 );
108 2568 : CPLAssert( iSrcBufferOffset <= nSrcBufferBytes );
109 :
110 : memmove( achSrcBuffer, achSrcBuffer + iSrcBufferOffset,
111 2568 : nSrcBufferBytes - iSrcBufferOffset );
112 2568 : iSrcBufferFileOffset += iSrcBufferOffset;
113 2568 : nSrcBufferBytes -= iSrcBufferOffset;
114 2568 : iSrcBufferOffset = 0;
115 : }
116 :
117 : nSrcBufferBytes += VSIFReadL( achSrcBuffer + nSrcBufferBytes,
118 2648 : 1, 512, fp );
119 2648 : achSrcBuffer[nSrcBufferBytes] = '\0';
120 :
121 2648 : CPLAssert( nSrcBufferBytes <= 1024 );
122 2648 : CPLAssert( iSrcBufferOffset <= nSrcBufferBytes );
123 : }
124 :
125 : /************************************************************************/
126 : /* ReadValue() */
127 : /* */
128 : /* Read one type code and value line pair from the DXF file. */
129 : /************************************************************************/
130 :
131 42307 : int OGRDXFReader::ReadValue( char *pszValueBuf, int nValueBufSize )
132 :
133 : {
134 : /* -------------------------------------------------------------------- */
135 : /* Make sure we have lots of data in our buffer for one value. */
136 : /* -------------------------------------------------------------------- */
137 42307 : if( nSrcBufferBytes - iSrcBufferOffset < 512 )
138 2648 : LoadDiskChunk();
139 :
140 42307 : if( nValueBufSize > 512 )
141 0 : nValueBufSize = 512;
142 :
143 : /* -------------------------------------------------------------------- */
144 : /* Capture the value code, and skip past it. */
145 : /* -------------------------------------------------------------------- */
146 42307 : int iStartSrcBufferOffset = iSrcBufferOffset;
147 42307 : int nValueCode = atoi(achSrcBuffer + iSrcBufferOffset);
148 :
149 42307 : nLineNumber ++;
150 :
151 : // proceed to newline.
152 467970 : while( achSrcBuffer[iSrcBufferOffset] != '\n'
153 128324 : && achSrcBuffer[iSrcBufferOffset] != '\r'
154 127530 : && achSrcBuffer[iSrcBufferOffset] != '\0' )
155 127502 : iSrcBufferOffset++;
156 :
157 42307 : if( achSrcBuffer[iSrcBufferOffset] == '\0' )
158 28 : return -1;
159 :
160 : // skip past newline. CR, CRLF, or LFCR
161 126837 : if( (achSrcBuffer[iSrcBufferOffset] == '\r'
162 794 : && achSrcBuffer[iSrcBufferOffset+1] == '\n' )
163 41485 : || (achSrcBuffer[iSrcBufferOffset] == '\n'
164 41485 : && achSrcBuffer[iSrcBufferOffset+1] == '\r' ) )
165 794 : iSrcBufferOffset += 2;
166 : else
167 41485 : iSrcBufferOffset += 1;
168 :
169 42279 : if( achSrcBuffer[iSrcBufferOffset] == '\0' )
170 0 : return -1;
171 :
172 : /* -------------------------------------------------------------------- */
173 : /* Capture the value string. */
174 : /* -------------------------------------------------------------------- */
175 42279 : int iEOL = iSrcBufferOffset;
176 :
177 42279 : nLineNumber ++;
178 :
179 : // proceed to newline.
180 931409 : while( achSrcBuffer[iEOL] != '\n'
181 282813 : && achSrcBuffer[iEOL] != '\r'
182 282019 : && achSrcBuffer[iEOL] != '\0' )
183 282019 : iEOL++;
184 :
185 42279 : if( achSrcBuffer[iEOL] == '\0' )
186 0 : return -1;
187 :
188 42279 : if( (iEOL - iSrcBufferOffset) > nValueBufSize-1 )
189 : {
190 : strncpy( pszValueBuf, achSrcBuffer + iSrcBufferOffset,
191 0 : nValueBufSize-1 );
192 0 : pszValueBuf[nValueBufSize-1] = '\0';
193 :
194 : CPLDebug( "DXF", "Long line truncated to %d characters.\n%s...",
195 : nValueBufSize-1,
196 0 : pszValueBuf );
197 : }
198 : else
199 : {
200 : strncpy( pszValueBuf, achSrcBuffer + iSrcBufferOffset,
201 42279 : iEOL - iSrcBufferOffset );
202 42279 : pszValueBuf[iEOL - iSrcBufferOffset] = '\0';
203 : }
204 :
205 42279 : iSrcBufferOffset = iEOL;
206 :
207 : // skip past newline. CR, CRLF, or LFCR
208 126837 : if( (achSrcBuffer[iSrcBufferOffset] == '\r'
209 794 : && achSrcBuffer[iSrcBufferOffset+1] == '\n' )
210 41485 : || (achSrcBuffer[iSrcBufferOffset] == '\n'
211 41485 : && achSrcBuffer[iSrcBufferOffset+1] == '\r' ) )
212 794 : iSrcBufferOffset += 2;
213 : else
214 41485 : iSrcBufferOffset += 1;
215 :
216 : /* -------------------------------------------------------------------- */
217 : /* Record how big this value was, so it can be unread safely. */
218 : /* -------------------------------------------------------------------- */
219 42279 : nLastValueSize = iSrcBufferOffset - iStartSrcBufferOffset;
220 :
221 : /* -------------------------------------------------------------------- */
222 : /* Is this a comment? If so, tail recurse to get another line. */
223 : /* -------------------------------------------------------------------- */
224 42279 : if( nValueCode == 999 )
225 3 : return ReadValue(pszValueBuf,nValueBufSize);
226 : else
227 42276 : return nValueCode;
228 : }
229 :
230 : /************************************************************************/
231 : /* UnreadValue() */
232 : /* */
233 : /* Unread the last value read, accomplished by resetting the */
234 : /* read pointer. */
235 : /************************************************************************/
236 :
237 287 : void OGRDXFReader::UnreadValue()
238 :
239 : {
240 287 : CPLAssert( iSrcBufferOffset >= nLastValueSize );
241 287 : CPLAssert( nLastValueSize > 0 );
242 :
243 287 : iSrcBufferOffset -= nLastValueSize;
244 :
245 287 : nLastValueSize = 0;
246 287 : }
247 :
|