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 9 : void OGRDXFDataSource::ResetReadPointer( int iNewOffset )
43 :
44 : {
45 9 : nSrcBufferBytes = 0;
46 9 : iSrcBufferOffset = 0;
47 9 : iSrcBufferFileOffset = iNewOffset;
48 9 : nLastValueSize = 0;
49 :
50 9 : VSIFSeekL( fp, iNewOffset, SEEK_SET );
51 9 : }
52 :
53 : /************************************************************************/
54 : /* LoadDiskChunk() */
55 : /* */
56 : /* Load another block (512 bytes) of input from the source */
57 : /* file. */
58 : /************************************************************************/
59 :
60 143 : void OGRDXFDataSource::LoadDiskChunk()
61 :
62 : {
63 143 : CPLAssert( iSrcBufferOffset >= 0 );
64 :
65 143 : if( nSrcBufferBytes - iSrcBufferOffset > 511 )
66 0 : return;
67 :
68 143 : if( iSrcBufferOffset > 0 )
69 : {
70 129 : CPLAssert( nSrcBufferBytes <= 1024 );
71 129 : CPLAssert( iSrcBufferOffset <= nSrcBufferBytes );
72 :
73 : memmove( achSrcBuffer, achSrcBuffer + iSrcBufferOffset,
74 129 : nSrcBufferBytes - iSrcBufferOffset );
75 129 : iSrcBufferFileOffset += iSrcBufferOffset;
76 129 : nSrcBufferBytes -= iSrcBufferOffset;
77 129 : iSrcBufferOffset = 0;
78 : }
79 :
80 : nSrcBufferBytes += VSIFReadL( achSrcBuffer + nSrcBufferBytes,
81 143 : 1, 512, fp );
82 143 : achSrcBuffer[nSrcBufferBytes] = '\0';
83 :
84 143 : CPLAssert( nSrcBufferBytes <= 1024 );
85 143 : 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 2583 : 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 2583 : if( nSrcBufferBytes - iSrcBufferOffset < 512 )
101 143 : LoadDiskChunk();
102 :
103 2583 : if( nValueBufSize > 512 )
104 0 : nValueBufSize = 512;
105 :
106 : /* -------------------------------------------------------------------- */
107 : /* Capture the value code, and skip past it. */
108 : /* -------------------------------------------------------------------- */
109 2583 : int iStartSrcBufferOffset = iSrcBufferOffset;
110 2583 : int nValueCode = atoi(achSrcBuffer + iSrcBufferOffset);
111 :
112 : // proceed to newline.
113 12916 : while( achSrcBuffer[iSrcBufferOffset] != '\n'
114 : && achSrcBuffer[iSrcBufferOffset] != '\r'
115 : && achSrcBuffer[iSrcBufferOffset] != '\0' )
116 7750 : iSrcBufferOffset++;
117 :
118 : // skip past newline. CR, CRLF, or LFCR
119 3376 : if( (achSrcBuffer[iSrcBufferOffset] == '\r'
120 : && achSrcBuffer[iSrcBufferOffset+1] == '\n' )
121 : || (achSrcBuffer[iSrcBufferOffset] == '\n'
122 : && achSrcBuffer[iSrcBufferOffset+1] == '\r' ) )
123 793 : iSrcBufferOffset += 2;
124 : else
125 1790 : iSrcBufferOffset += 1;
126 :
127 2583 : if( achSrcBuffer[iSrcBufferOffset] == '\0' )
128 0 : return -1;
129 :
130 : /* -------------------------------------------------------------------- */
131 : /* Capture the value string. */
132 : /* -------------------------------------------------------------------- */
133 2583 : int iEOL = iSrcBufferOffset;
134 :
135 : // proceed to newline.
136 24385 : while( achSrcBuffer[iEOL] != '\n'
137 : && achSrcBuffer[iEOL] != '\r'
138 : && achSrcBuffer[iEOL] != '\0' )
139 19219 : iEOL++;
140 :
141 2583 : if( achSrcBuffer[iEOL] == '\0' )
142 0 : return -1;
143 :
144 2583 : 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 2583 : iEOL - iSrcBufferOffset );
158 2583 : pszValueBuf[iEOL - iSrcBufferOffset] = '\0';
159 : }
160 :
161 2583 : iSrcBufferOffset = iEOL;
162 :
163 : // skip past newline. CR, CRLF, or LFCR
164 3376 : if( (achSrcBuffer[iSrcBufferOffset] == '\r'
165 : && achSrcBuffer[iSrcBufferOffset+1] == '\n' )
166 : || (achSrcBuffer[iSrcBufferOffset] == '\n'
167 : && achSrcBuffer[iSrcBufferOffset+1] == '\r' ) )
168 793 : iSrcBufferOffset += 2;
169 : else
170 1790 : iSrcBufferOffset += 1;
171 :
172 : /* -------------------------------------------------------------------- */
173 : /* Record how big this value was, so it can be unread safely. */
174 : /* -------------------------------------------------------------------- */
175 2583 : nLastValueSize = iSrcBufferOffset - iStartSrcBufferOffset;
176 :
177 : /* -------------------------------------------------------------------- */
178 : /* Is this a comment? If so, tail recurse to get another line. */
179 : /* -------------------------------------------------------------------- */
180 2583 : if( nValueCode == 999 )
181 1 : return ReadValue(pszValueBuf,nValueBufSize);
182 : else
183 2582 : return nValueCode;
184 : }
185 :
186 : /************************************************************************/
187 : /* UnreadValue() */
188 : /* */
189 : /* Unread the last value read, accomplished by resetting the */
190 : /* read pointer. */
191 : /************************************************************************/
192 :
193 33 : void OGRDXFDataSource::UnreadValue()
194 :
195 : {
196 33 : CPLAssert( iSrcBufferOffset >= nLastValueSize );
197 33 : CPLAssert( nLastValueSize > 0 );
198 :
199 33 : iSrcBufferOffset -= nLastValueSize;
200 :
201 33 : nLastValueSize = 0;
202 33 : }
203 :
|