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