Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: SDTS Translator
4 : * Purpose: Various utility functions that apply to all SDTS profiles.
5 : * SDTSModId, and SDTSFeature methods.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam
10 : * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.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 "sdts_al.h"
32 : #include "cpl_string.h"
33 :
34 : #include <set>
35 :
36 : /************************************************************************/
37 : /* SDTSFeature() */
38 : /************************************************************************/
39 :
40 572 : SDTSFeature::SDTSFeature() : nAttributes(0), paoATID(nullptr)
41 : {
42 572 : }
43 :
44 : /************************************************************************/
45 : /* SDTSFeature::ApplyATID() */
46 : /************************************************************************/
47 :
48 12 : void SDTSFeature::ApplyATID(DDFField *poField)
49 :
50 : {
51 12 : DDFSubfieldDefn *poMODN = poField->GetFieldDefn()->FindSubfieldDefn("MODN");
52 12 : if (poMODN == nullptr)
53 : {
54 : // CPLAssert( false );
55 0 : return;
56 : }
57 :
58 12 : bool bUsualFormat = poMODN->GetWidth() == 4;
59 12 : const int nRepeatCount = poField->GetRepeatCount();
60 24 : for (int iRepeat = 0; iRepeat < nRepeatCount; iRepeat++)
61 : {
62 12 : paoATID = reinterpret_cast<SDTSModId *>(
63 12 : CPLRealloc(paoATID, sizeof(SDTSModId) * (nAttributes + 1)));
64 :
65 12 : SDTSModId *poModId = paoATID + nAttributes;
66 12 : *poModId = SDTSModId();
67 :
68 12 : if (bUsualFormat)
69 : {
70 : const char *pabyData =
71 12 : poField->GetSubfieldData(poMODN, nullptr, iRepeat);
72 12 : if (pabyData == nullptr || strlen(pabyData) < 5)
73 0 : return;
74 :
75 12 : memcpy(poModId->szModule, pabyData, 4);
76 12 : poModId->szModule[4] = '\0';
77 12 : poModId->nRecord = atoi(pabyData + 4);
78 12 : poModId->szOBRP[0] = '\0';
79 : }
80 : else
81 : {
82 0 : poModId->Set(poField);
83 : }
84 :
85 12 : nAttributes++;
86 : }
87 : }
88 :
89 : /************************************************************************/
90 : /* ~SDTSFeature() */
91 : /************************************************************************/
92 :
93 1144 : SDTSFeature::~SDTSFeature()
94 :
95 : {
96 572 : CPLFree(paoATID);
97 572 : paoATID = nullptr;
98 572 : }
99 :
100 : /************************************************************************/
101 : /* SDTSModId::Set() */
102 : /* */
103 : /* Set a module from a field. We depend on our pre-knowledge */
104 : /* of the data layout to fetch more efficiently. */
105 : /************************************************************************/
106 :
107 827 : int SDTSModId::Set(DDFField *poField)
108 :
109 : {
110 827 : const char *pachData = poField->GetData();
111 827 : DDFFieldDefn *poDefn = poField->GetFieldDefn();
112 :
113 1654 : if (poDefn->GetSubfieldCount() >= 2 &&
114 827 : poDefn->GetSubfield(0)->GetWidth() == 4)
115 : {
116 825 : if (strlen(pachData) < 5)
117 0 : return FALSE;
118 :
119 825 : memcpy(szModule, pachData, 4);
120 825 : szModule[4] = '\0';
121 :
122 825 : nRecord = atoi(pachData + 4);
123 : }
124 : else
125 : {
126 : DDFSubfieldDefn *poSF =
127 2 : poField->GetFieldDefn()->FindSubfieldDefn("MODN");
128 2 : if (poSF == nullptr)
129 0 : return FALSE;
130 : int nBytesRemaining;
131 2 : pachData = poField->GetSubfieldData(poSF, &nBytesRemaining);
132 2 : if (pachData == nullptr)
133 0 : return FALSE;
134 2 : snprintf(szModule, sizeof(szModule), "%s",
135 : poSF->ExtractStringData(pachData, nBytesRemaining, nullptr));
136 :
137 2 : poSF = poField->GetFieldDefn()->FindSubfieldDefn("RCID");
138 2 : if (poSF != nullptr)
139 : {
140 2 : pachData = poField->GetSubfieldData(poSF, &nBytesRemaining);
141 2 : if (pachData != nullptr)
142 2 : nRecord =
143 2 : poSF->ExtractIntData(pachData, nBytesRemaining, nullptr);
144 : }
145 : }
146 :
147 827 : if (poDefn->GetSubfieldCount() == 3)
148 : {
149 : DDFSubfieldDefn *poSF =
150 219 : poField->GetFieldDefn()->FindSubfieldDefn("OBRP");
151 219 : if (poSF != nullptr)
152 : {
153 : int nBytesRemaining;
154 219 : pachData = poField->GetSubfieldData(poSF, &nBytesRemaining);
155 219 : if (pachData != nullptr)
156 : {
157 219 : snprintf(szOBRP, sizeof(szOBRP), "%s",
158 : poSF->ExtractStringData(pachData, nBytesRemaining,
159 : nullptr));
160 : }
161 : }
162 : }
163 :
164 827 : return FALSE;
165 : }
166 :
167 : /************************************************************************/
168 : /* SDTSModId::GetName() */
169 : /************************************************************************/
170 :
171 0 : const char *SDTSModId::GetName()
172 :
173 : {
174 0 : snprintf(szName, sizeof(szName), "%s:%d", szModule, nRecord);
175 :
176 0 : return szName;
177 : }
178 :
179 : /************************************************************************/
180 : /* SDTSScanModuleReferences() */
181 : /* */
182 : /* Find all modules references by records in this module based */
183 : /* on a particular field name. That field must be in module */
184 : /* reference form (contain MODN/RCID subfields). */
185 : /************************************************************************/
186 :
187 5 : char **SDTSScanModuleReferences(DDFModule *poModule, const char *pszFName)
188 :
189 : {
190 : /* -------------------------------------------------------------------- */
191 : /* Identify the field, and subfield we are interested in. */
192 : /* -------------------------------------------------------------------- */
193 5 : DDFFieldDefn *poIDField = poModule->FindFieldDefn(pszFName);
194 :
195 5 : if (poIDField == nullptr)
196 2 : return nullptr;
197 :
198 3 : DDFSubfieldDefn *poMODN = poIDField->FindSubfieldDefn("MODN");
199 3 : if (poMODN == nullptr)
200 0 : return nullptr;
201 :
202 : /* -------------------------------------------------------------------- */
203 : /* Scan the file. */
204 : /* -------------------------------------------------------------------- */
205 3 : poModule->Rewind();
206 :
207 3 : DDFRecord *poRecord = nullptr;
208 6 : CPLStringList aosModnList;
209 6 : std::set<std::string> aoSetModNames;
210 153 : while ((poRecord = poModule->ReadRecord()) != nullptr)
211 : {
212 679 : for (int iField = 0; iField < poRecord->GetFieldCount(); iField++)
213 : {
214 529 : DDFField *poField = poRecord->GetField(iField);
215 :
216 529 : if (poField->GetFieldDefn() == poIDField)
217 : {
218 12 : for (int i = 0; i < poField->GetRepeatCount(); i++)
219 : {
220 : const char *pszModName =
221 6 : poField->GetSubfieldData(poMODN, nullptr, i);
222 :
223 6 : if (pszModName == nullptr || strlen(pszModName) < 4)
224 0 : continue;
225 :
226 : char szName[5];
227 6 : strncpy(szName, pszModName, 4);
228 6 : szName[4] = '\0';
229 :
230 6 : if (aoSetModNames.find(szName) == aoSetModNames.end())
231 : {
232 1 : aoSetModNames.insert(szName);
233 1 : aosModnList.AddString(szName);
234 : }
235 : }
236 : }
237 : }
238 : }
239 :
240 3 : poModule->Rewind();
241 :
242 3 : return aosModnList.StealList();
243 : }
|