Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements OGRGmtDataSource class.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "cpl_conv.h"
30 : #include "cpl_string.h"
31 : #include "ogr_gmt.h"
32 :
33 : /************************************************************************/
34 : /* OGRGmtDataSource() */
35 : /************************************************************************/
36 :
37 108 : OGRGmtDataSource::OGRGmtDataSource()
38 108 : : papoLayers(nullptr), nLayers(0), pszName(nullptr), bUpdate(false)
39 : {
40 108 : }
41 :
42 : /************************************************************************/
43 : /* ~OGRGmtDataSource() */
44 : /************************************************************************/
45 :
46 216 : OGRGmtDataSource::~OGRGmtDataSource()
47 :
48 : {
49 180 : for (int i = 0; i < nLayers; i++)
50 72 : delete papoLayers[i];
51 108 : CPLFree(papoLayers);
52 108 : CPLFree(pszName);
53 216 : }
54 :
55 : /************************************************************************/
56 : /* Open() */
57 : /************************************************************************/
58 :
59 107 : int OGRGmtDataSource::Open(const char *pszFilename, VSILFILE *fp,
60 : const OGRSpatialReference *poSRS, int bUpdateIn)
61 :
62 : {
63 107 : bUpdate = CPL_TO_BOOL(bUpdateIn);
64 :
65 : OGRGmtLayer *poLayer =
66 107 : new OGRGmtLayer(this, pszFilename, fp, poSRS, bUpdate);
67 107 : if (!poLayer->bValidFile)
68 : {
69 35 : delete poLayer;
70 35 : return FALSE;
71 : }
72 :
73 72 : papoLayers = static_cast<OGRGmtLayer **>(
74 72 : CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRGmtLayer *)));
75 72 : papoLayers[nLayers] = poLayer;
76 72 : nLayers++;
77 :
78 72 : CPLFree(pszName);
79 72 : pszName = CPLStrdup(pszFilename);
80 :
81 72 : return TRUE;
82 : }
83 :
84 : /************************************************************************/
85 : /* Create() */
86 : /* */
87 : /* Create a new datasource. This does not really do anything */
88 : /* currently but save the name. */
89 : /************************************************************************/
90 :
91 36 : int OGRGmtDataSource::Create(const char *pszDSName, char ** /* papszOptions */)
92 :
93 : {
94 36 : pszName = CPLStrdup(pszDSName);
95 :
96 36 : return TRUE;
97 : }
98 :
99 : /************************************************************************/
100 : /* ICreateLayer() */
101 : /************************************************************************/
102 :
103 : OGRLayer *
104 52 : OGRGmtDataSource::ICreateLayer(const char *pszLayerName,
105 : const OGRGeomFieldDefn *poGeomFieldDefn,
106 : CSLConstList /*papszOptions*/)
107 : {
108 52 : if (nLayers != 0)
109 16 : return nullptr;
110 :
111 36 : const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
112 : const auto poSRS =
113 36 : poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
114 :
115 : /* -------------------------------------------------------------------- */
116 : /* Establish the geometry type. Note this logic */
117 : /* -------------------------------------------------------------------- */
118 36 : const char *pszGeom = nullptr;
119 :
120 36 : switch (wkbFlatten(eType))
121 : {
122 5 : case wkbPoint:
123 5 : pszGeom = " @GPOINT";
124 5 : break;
125 4 : case wkbLineString:
126 4 : pszGeom = " @GLINESTRING";
127 4 : break;
128 5 : case wkbPolygon:
129 5 : pszGeom = " @GPOLYGON";
130 5 : break;
131 4 : case wkbMultiPoint:
132 4 : pszGeom = " @GMULTIPOINT";
133 4 : break;
134 4 : case wkbMultiLineString:
135 4 : pszGeom = " @GMULTILINESTRING";
136 4 : break;
137 4 : case wkbMultiPolygon:
138 4 : pszGeom = " @GMULTIPOLYGON";
139 4 : break;
140 10 : default:
141 10 : pszGeom = "";
142 10 : break;
143 : }
144 :
145 : /* -------------------------------------------------------------------- */
146 : /* If this is the first layer for this datasource, and if the */
147 : /* datasource name ends in .gmt we will override the provided */
148 : /* layer name with the name from the gmt. */
149 : /* -------------------------------------------------------------------- */
150 :
151 72 : CPLString osPath = CPLGetPath(pszName);
152 72 : CPLString osFilename(pszName);
153 36 : const char *pszFlags = "wb+";
154 :
155 36 : if (osFilename == "/dev/stdout")
156 0 : osFilename = "/vsistdout";
157 :
158 36 : if (STARTS_WITH(osFilename, "/vsistdout"))
159 1 : pszFlags = "wb";
160 35 : else if (!EQUAL(CPLGetExtension(pszName), "gmt"))
161 0 : osFilename = CPLFormFilename(osPath, pszLayerName, "gmt");
162 :
163 : /* -------------------------------------------------------------------- */
164 : /* Open the file. */
165 : /* -------------------------------------------------------------------- */
166 36 : VSILFILE *fp = VSIFOpenL(osFilename, pszFlags);
167 36 : if (fp == nullptr)
168 : {
169 1 : CPLError(CE_Failure, CPLE_OpenFailed, "open(%s) failed: %s",
170 1 : osFilename.c_str(), VSIStrerror(errno));
171 1 : return nullptr;
172 : }
173 :
174 : /* -------------------------------------------------------------------- */
175 : /* Write out header. */
176 : /* -------------------------------------------------------------------- */
177 35 : VSIFPrintfL(fp, "# @VGMT1.0%s\n", pszGeom);
178 35 : if (!STARTS_WITH(osFilename, "/vsistdout"))
179 : {
180 34 : VSIFPrintfL(fp, "# REGION_STUB "
181 : " \n");
182 : }
183 :
184 : /* -------------------------------------------------------------------- */
185 : /* Write the projection, if possible. */
186 : /* -------------------------------------------------------------------- */
187 35 : if (poSRS != nullptr)
188 : {
189 2 : if (poSRS->GetAuthorityName(nullptr) &&
190 1 : EQUAL(poSRS->GetAuthorityName(nullptr), "EPSG"))
191 : {
192 1 : VSIFPrintfL(fp, "# @Je%s\n", poSRS->GetAuthorityCode(nullptr));
193 : }
194 :
195 1 : char *pszValue = nullptr;
196 1 : if (poSRS->exportToProj4(&pszValue) == OGRERR_NONE)
197 : {
198 1 : VSIFPrintfL(fp, "# @Jp\"%s\"\n", pszValue);
199 : }
200 1 : CPLFree(pszValue);
201 1 : pszValue = nullptr;
202 :
203 1 : if (poSRS->exportToWkt(&pszValue) == OGRERR_NONE)
204 : {
205 : char *pszEscapedWkt =
206 1 : CPLEscapeString(pszValue, -1, CPLES_BackslashQuotable);
207 :
208 1 : VSIFPrintfL(fp, "# @Jw\"%s\"\n", pszEscapedWkt);
209 1 : CPLFree(pszEscapedWkt);
210 : }
211 1 : CPLFree(pszValue);
212 : }
213 :
214 : /* -------------------------------------------------------------------- */
215 : /* Return open layer handle. */
216 : /* -------------------------------------------------------------------- */
217 35 : if (Open(osFilename, fp, poSRS, TRUE))
218 : {
219 35 : auto poLayer = papoLayers[nLayers - 1];
220 35 : if (strcmp(pszGeom, "") != 0)
221 : {
222 25 : poLayer->GetLayerDefn()->SetGeomType(wkbFlatten(eType));
223 : }
224 35 : return poLayer;
225 : }
226 :
227 0 : VSIFCloseL(fp);
228 0 : return nullptr;
229 : }
230 :
231 : /************************************************************************/
232 : /* TestCapability() */
233 : /************************************************************************/
234 :
235 51 : int OGRGmtDataSource::TestCapability(const char *pszCap)
236 :
237 : {
238 51 : if (EQUAL(pszCap, ODsCCreateLayer))
239 33 : return TRUE;
240 18 : else if (EQUAL(pszCap, ODsCZGeometries))
241 0 : return TRUE;
242 :
243 18 : return FALSE;
244 : }
245 :
246 : /************************************************************************/
247 : /* GetLayer() */
248 : /************************************************************************/
249 :
250 6 : OGRLayer *OGRGmtDataSource::GetLayer(int iLayer)
251 :
252 : {
253 6 : if (iLayer < 0 || iLayer >= nLayers)
254 0 : return nullptr;
255 :
256 6 : return papoLayers[iLayer];
257 : }
|