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