Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: Interlis 2 Translator 4 : * Purpose: Implements OGRILI2DataSource class. 5 : * Author: Markus Schnider, Sourcepole AG 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG 9 : * Copyright (c) 2007-2008, Even Rouault <even dot rouault at spatialys.com> 10 : * 11 : * SPDX-License-Identifier: MIT 12 : ****************************************************************************/ 13 : 14 : #include "cpl_conv.h" 15 : #include "cpl_string.h" 16 : 17 : #include "ili2reader.h" 18 : 19 : #include "ogr_ili2.h" 20 : 21 : using namespace std; 22 : 23 : /************************************************************************/ 24 : /* OGRILI2DataSource() */ 25 : /************************************************************************/ 26 : 27 26069 : OGRILI2DataSource::OGRILI2DataSource() 28 26069 : : pszName(nullptr), poImdReader(new ImdReader(2)), poReader(nullptr), 29 26069 : nLayers(0), papoLayers(nullptr) 30 : { 31 26069 : } 32 : 33 : /************************************************************************/ 34 : /* ~OGRILI2DataSource() */ 35 : /************************************************************************/ 36 : 37 52138 : OGRILI2DataSource::~OGRILI2DataSource() 38 : 39 : { 40 26069 : for (int i = 0; i < nLayers; i++) 41 : { 42 0 : delete papoLayers[i]; 43 : } 44 26069 : CPLFree(papoLayers); 45 : 46 26069 : DestroyILI2Reader(poReader); 47 26069 : delete poImdReader; 48 26069 : CPLFree(pszName); 49 52138 : } 50 : 51 : /************************************************************************/ 52 : /* Open() */ 53 : /************************************************************************/ 54 : 55 26069 : int OGRILI2DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn, 56 : int bTestOpen) 57 : 58 : { 59 52138 : CPLString osBasename; 60 52138 : CPLString osModelFilename; 61 : 62 26069 : if (CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != nullptr) 63 : { 64 1 : osBasename = pszNewName; 65 1 : osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL"); 66 : } 67 : else 68 : { 69 26068 : char **filenames = CSLTokenizeString2(pszNewName, ",", 0); 70 26068 : int nCount = CSLCount(filenames); 71 26068 : if (nCount == 0) 72 : { 73 761 : CSLDestroy(filenames); 74 761 : return FALSE; 75 : } 76 25307 : osBasename = filenames[0]; 77 : 78 25307 : if (nCount > 1) 79 120 : osModelFilename = filenames[1]; 80 : 81 25307 : CSLDestroy(filenames); 82 : } 83 : 84 25308 : pszName = CPLStrdup(osBasename); 85 : 86 : /* -------------------------------------------------------------------- */ 87 : /* Open the source file. */ 88 : /* -------------------------------------------------------------------- */ 89 25308 : VSILFILE *fp = VSIFOpenL(pszName, "r"); 90 25308 : if (fp == nullptr) 91 : { 92 25304 : if (!bTestOpen) 93 0 : CPLError(CE_Failure, CPLE_OpenFailed, 94 : "Failed to open ILI2 file `%s'.", pszNewName); 95 : 96 25304 : return FALSE; 97 : } 98 : 99 : /* -------------------------------------------------------------------- */ 100 : /* If we aren't sure it is ILI2, load a header chunk and check */ 101 : /* for signs it is ILI2 */ 102 : /* -------------------------------------------------------------------- */ 103 : char szHeader[1000]; 104 4 : if (bTestOpen) 105 : { 106 : int nLen = 107 2 : static_cast<int>(VSIFReadL(szHeader, 1, sizeof(szHeader), fp)); 108 2 : if (nLen == sizeof(szHeader)) 109 2 : szHeader[sizeof(szHeader) - 1] = '\0'; 110 : else 111 0 : szHeader[nLen] = '\0'; 112 : 113 2 : if (szHeader[0] != '<' || 114 2 : (strstr(szHeader, "interlis.ch/INTERLIS2") == nullptr && 115 0 : strstr(szHeader, "//www.interlis.ch/xtf/") == nullptr)) 116 : { 117 : // "www.interlis.ch/INTERLIS2.3" 118 0 : VSIFCloseL(fp); 119 0 : return FALSE; 120 : } 121 : } 122 : 123 : /* -------------------------------------------------------------------- */ 124 : /* We assume now that it is ILI2. Close and instantiate a */ 125 : /* ILI2Reader on it. */ 126 : /* -------------------------------------------------------------------- */ 127 4 : VSIFCloseL(fp); 128 : 129 4 : poReader = CreateILI2Reader(); 130 4 : if (poReader == nullptr) 131 : { 132 0 : CPLError(CE_Failure, CPLE_AppDefined, 133 : "File %s appears to be ILI2 but the ILI2 reader cannot\n" 134 : "be instantiated, likely because Xerces support was not\n" 135 : "configured in.", 136 : pszNewName); 137 0 : return FALSE; 138 : } 139 : 140 4 : if (!osModelFilename.empty()) 141 3 : poReader->ReadModel(this, poImdReader, osModelFilename); 142 : 143 4 : poReader->SetSourceFile(pszName); 144 : 145 4 : poReader->SaveClasses(pszName); 146 : 147 49 : for (auto &poLayer : poReader->GetLayers()) 148 45 : poLayer->ResetReading(); 149 : 150 4 : return TRUE; 151 : } 152 : 153 : /************************************************************************/ 154 : /* TestCapability() */ 155 : /************************************************************************/ 156 : 157 0 : int OGRILI2DataSource::TestCapability(const char *pszCap) const 158 : 159 : { 160 0 : if (EQUAL(pszCap, ODsCCurveGeometries)) 161 0 : return TRUE; 162 0 : else if (EQUAL(pszCap, ODsCZGeometries)) 163 0 : return TRUE; 164 : 165 0 : return FALSE; 166 : } 167 : 168 : /************************************************************************/ 169 : /* GetLayer() */ 170 : /************************************************************************/ 171 : 172 78 : const OGRLayer *OGRILI2DataSource::GetLayer(int iLayer) const 173 : 174 : { 175 78 : int i = 0; 176 616 : for (auto &poLayer : poReader->GetLayers()) 177 : { 178 616 : if (i == iLayer) 179 : { 180 78 : return poLayer.get(); 181 : } 182 538 : ++i; 183 : } 184 0 : return nullptr; 185 : }