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 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "cpl_conv.h"
14 : #include "cpl_string.h"
15 : #include "ogr_gmt.h"
16 :
17 : /************************************************************************/
18 : /* OGRGmtDataSource() */
19 : /************************************************************************/
20 :
21 108 : OGRGmtDataSource::OGRGmtDataSource()
22 108 : : papoLayers(nullptr), nLayers(0), bUpdate(false)
23 : {
24 108 : }
25 :
26 : /************************************************************************/
27 : /* ~OGRGmtDataSource() */
28 : /************************************************************************/
29 :
30 216 : OGRGmtDataSource::~OGRGmtDataSource()
31 :
32 : {
33 180 : for (int i = 0; i < nLayers; i++)
34 72 : delete papoLayers[i];
35 108 : CPLFree(papoLayers);
36 216 : }
37 :
38 : /************************************************************************/
39 : /* Open() */
40 : /************************************************************************/
41 :
42 107 : int OGRGmtDataSource::Open(const char *pszFilename, VSILFILE *fp,
43 : const OGRSpatialReference *poSRS, int bUpdateIn)
44 :
45 : {
46 107 : bUpdate = CPL_TO_BOOL(bUpdateIn);
47 :
48 : OGRGmtLayer *poLayer =
49 107 : new OGRGmtLayer(this, pszFilename, fp, poSRS, bUpdate);
50 107 : if (!poLayer->bValidFile)
51 : {
52 35 : delete poLayer;
53 35 : return FALSE;
54 : }
55 :
56 72 : papoLayers = static_cast<OGRGmtLayer **>(
57 72 : CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRGmtLayer *)));
58 72 : papoLayers[nLayers] = poLayer;
59 72 : nLayers++;
60 :
61 72 : return TRUE;
62 : }
63 :
64 : /************************************************************************/
65 : /* ICreateLayer() */
66 : /************************************************************************/
67 :
68 : OGRLayer *
69 52 : OGRGmtDataSource::ICreateLayer(const char *pszLayerName,
70 : const OGRGeomFieldDefn *poGeomFieldDefn,
71 : CSLConstList /*papszOptions*/)
72 : {
73 52 : if (nLayers != 0)
74 16 : return nullptr;
75 :
76 36 : const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
77 : const auto poSRS =
78 36 : poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
79 :
80 : /* -------------------------------------------------------------------- */
81 : /* Establish the geometry type. Note this logic */
82 : /* -------------------------------------------------------------------- */
83 36 : const char *pszGeom = nullptr;
84 :
85 36 : switch (wkbFlatten(eType))
86 : {
87 5 : case wkbPoint:
88 5 : pszGeom = " @GPOINT";
89 5 : break;
90 4 : case wkbLineString:
91 4 : pszGeom = " @GLINESTRING";
92 4 : break;
93 5 : case wkbPolygon:
94 5 : pszGeom = " @GPOLYGON";
95 5 : break;
96 4 : case wkbMultiPoint:
97 4 : pszGeom = " @GMULTIPOINT";
98 4 : break;
99 4 : case wkbMultiLineString:
100 4 : pszGeom = " @GMULTILINESTRING";
101 4 : break;
102 4 : case wkbMultiPolygon:
103 4 : pszGeom = " @GMULTIPOLYGON";
104 4 : break;
105 10 : default:
106 10 : pszGeom = "";
107 10 : break;
108 : }
109 :
110 : /* -------------------------------------------------------------------- */
111 : /* If this is the first layer for this datasource, and if the */
112 : /* datasource name ends in .gmt we will override the provided */
113 : /* layer name with the name from the gmt. */
114 : /* -------------------------------------------------------------------- */
115 :
116 72 : CPLString osPath = CPLGetPath(GetDescription());
117 72 : CPLString osFilename(GetDescription());
118 36 : const char *pszFlags = "wb+";
119 :
120 36 : if (osFilename == "/dev/stdout")
121 0 : osFilename = "/vsistdout";
122 :
123 36 : if (STARTS_WITH(osFilename, "/vsistdout"))
124 1 : pszFlags = "wb";
125 35 : else if (!EQUAL(CPLGetExtension(GetDescription()), "gmt"))
126 0 : osFilename = CPLFormFilename(osPath, pszLayerName, "gmt");
127 :
128 : /* -------------------------------------------------------------------- */
129 : /* Open the file. */
130 : /* -------------------------------------------------------------------- */
131 36 : VSILFILE *fp = VSIFOpenL(osFilename, pszFlags);
132 36 : if (fp == nullptr)
133 : {
134 1 : CPLError(CE_Failure, CPLE_OpenFailed, "open(%s) failed: %s",
135 1 : osFilename.c_str(), VSIStrerror(errno));
136 1 : return nullptr;
137 : }
138 :
139 : /* -------------------------------------------------------------------- */
140 : /* Write out header. */
141 : /* -------------------------------------------------------------------- */
142 35 : VSIFPrintfL(fp, "# @VGMT1.0%s\n", pszGeom);
143 35 : if (!STARTS_WITH(osFilename, "/vsistdout"))
144 : {
145 34 : VSIFPrintfL(fp, "# REGION_STUB "
146 : " \n");
147 : }
148 :
149 : /* -------------------------------------------------------------------- */
150 : /* Write the projection, if possible. */
151 : /* -------------------------------------------------------------------- */
152 35 : if (poSRS != nullptr)
153 : {
154 2 : if (poSRS->GetAuthorityName(nullptr) &&
155 1 : EQUAL(poSRS->GetAuthorityName(nullptr), "EPSG"))
156 : {
157 1 : VSIFPrintfL(fp, "# @Je%s\n", poSRS->GetAuthorityCode(nullptr));
158 : }
159 :
160 1 : char *pszValue = nullptr;
161 1 : if (poSRS->exportToProj4(&pszValue) == OGRERR_NONE)
162 : {
163 1 : VSIFPrintfL(fp, "# @Jp\"%s\"\n", pszValue);
164 : }
165 1 : CPLFree(pszValue);
166 1 : pszValue = nullptr;
167 :
168 1 : if (poSRS->exportToWkt(&pszValue) == OGRERR_NONE)
169 : {
170 : char *pszEscapedWkt =
171 1 : CPLEscapeString(pszValue, -1, CPLES_BackslashQuotable);
172 :
173 1 : VSIFPrintfL(fp, "# @Jw\"%s\"\n", pszEscapedWkt);
174 1 : CPLFree(pszEscapedWkt);
175 : }
176 1 : CPLFree(pszValue);
177 : }
178 :
179 : /* -------------------------------------------------------------------- */
180 : /* Return open layer handle. */
181 : /* -------------------------------------------------------------------- */
182 35 : if (Open(osFilename, fp, poSRS, TRUE))
183 : {
184 35 : auto poLayer = papoLayers[nLayers - 1];
185 35 : if (strcmp(pszGeom, "") != 0)
186 : {
187 25 : poLayer->GetLayerDefn()->SetGeomType(wkbFlatten(eType));
188 : }
189 35 : return poLayer;
190 : }
191 :
192 0 : VSIFCloseL(fp);
193 0 : return nullptr;
194 : }
195 :
196 : /************************************************************************/
197 : /* TestCapability() */
198 : /************************************************************************/
199 :
200 51 : int OGRGmtDataSource::TestCapability(const char *pszCap)
201 :
202 : {
203 51 : if (EQUAL(pszCap, ODsCCreateLayer))
204 33 : return TRUE;
205 18 : else if (EQUAL(pszCap, ODsCZGeometries))
206 0 : return TRUE;
207 :
208 18 : return FALSE;
209 : }
210 :
211 : /************************************************************************/
212 : /* GetLayer() */
213 : /************************************************************************/
214 :
215 6 : OGRLayer *OGRGmtDataSource::GetLayer(int iLayer)
216 :
217 : {
218 6 : if (iLayer < 0 || iLayer >= nLayers)
219 0 : return nullptr;
220 :
221 6 : return papoLayers[iLayer];
222 : }
|