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 55 : OGRILI2DataSource::OGRILI2DataSource() 28 55 : : pszName(nullptr), poImdReader(new ImdReader(2)), poReader(nullptr), 29 55 : nLayers(0), papoLayers(nullptr) 30 : { 31 55 : } 32 : 33 : /************************************************************************/ 34 : /* ~OGRILI2DataSource() */ 35 : /************************************************************************/ 36 : 37 110 : OGRILI2DataSource::~OGRILI2DataSource() 38 : 39 : { 40 55 : for (int i = 0; i < nLayers; i++) 41 : { 42 0 : delete papoLayers[i]; 43 : } 44 55 : CPLFree(papoLayers); 45 : 46 55 : DestroyILI2Reader(poReader); 47 55 : delete poImdReader; 48 55 : CPLFree(pszName); 49 110 : } 50 : 51 : /************************************************************************/ 52 : /* Open() */ 53 : /************************************************************************/ 54 : 55 55 : int OGRILI2DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn, 56 : int bTestOpen) 57 : 58 : { 59 110 : CPLString osBasename; 60 110 : CPLString osModelFilename; 61 : 62 55 : if (CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != nullptr) 63 : { 64 0 : osBasename = pszNewName; 65 0 : osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL"); 66 : } 67 : else 68 : { 69 55 : char **filenames = CSLTokenizeString2(pszNewName, ",", 0); 70 55 : int nCount = CSLCount(filenames); 71 55 : if (nCount == 0) 72 : { 73 0 : CSLDestroy(filenames); 74 0 : return FALSE; 75 : } 76 55 : osBasename = filenames[0]; 77 : 78 55 : if (nCount > 1) 79 51 : osModelFilename = filenames[1]; 80 : 81 55 : CSLDestroy(filenames); 82 : } 83 : 84 55 : pszName = CPLStrdup(osBasename); 85 : 86 : /* -------------------------------------------------------------------- */ 87 : /* Open the source file. */ 88 : /* -------------------------------------------------------------------- */ 89 55 : VSILFILE *fp = VSIFOpenL(pszName, "r"); 90 55 : if (fp == nullptr) 91 : { 92 52 : if (!bTestOpen) 93 0 : CPLError(CE_Failure, CPLE_OpenFailed, 94 : "Failed to open ILI2 file `%s'.", pszNewName); 95 : 96 52 : 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 3 : if (bTestOpen) 105 : { 106 : int nLen = 107 3 : static_cast<int>(VSIFReadL(szHeader, 1, sizeof(szHeader), fp)); 108 3 : if (nLen == sizeof(szHeader)) 109 3 : szHeader[sizeof(szHeader) - 1] = '\0'; 110 : else 111 0 : szHeader[nLen] = '\0'; 112 : 113 3 : if (szHeader[0] != '<' || 114 3 : strstr(szHeader, "interlis.ch/INTERLIS2") == nullptr) 115 : { 116 : // "www.interlis.ch/INTERLIS2.3" 117 0 : VSIFCloseL(fp); 118 0 : return FALSE; 119 : } 120 : } 121 : 122 : /* -------------------------------------------------------------------- */ 123 : /* We assume now that it is ILI2. Close and instantiate a */ 124 : /* ILI2Reader on it. */ 125 : /* -------------------------------------------------------------------- */ 126 3 : VSIFCloseL(fp); 127 : 128 3 : poReader = CreateILI2Reader(); 129 3 : if (poReader == nullptr) 130 : { 131 0 : CPLError(CE_Failure, CPLE_AppDefined, 132 : "File %s appears to be ILI2 but the ILI2 reader cannot\n" 133 : "be instantiated, likely because Xerces support was not\n" 134 : "configured in.", 135 : pszNewName); 136 0 : return FALSE; 137 : } 138 : 139 3 : if (!osModelFilename.empty()) 140 2 : poReader->ReadModel(this, poImdReader, osModelFilename); 141 : 142 3 : poReader->SetSourceFile(pszName); 143 : 144 3 : poReader->SaveClasses(pszName); 145 : 146 3 : listLayer = poReader->GetLayers(); 147 3 : list<OGRLayer *>::const_iterator layerIt; 148 41 : for (layerIt = listLayer.begin(); layerIt != listLayer.end(); ++layerIt) 149 : { 150 38 : (*layerIt)->ResetReading(); 151 : } 152 : 153 3 : return TRUE; 154 : } 155 : 156 : /************************************************************************/ 157 : /* TestCapability() */ 158 : /************************************************************************/ 159 : 160 0 : int OGRILI2DataSource::TestCapability(const char *pszCap) 161 : 162 : { 163 0 : if (EQUAL(pszCap, ODsCCurveGeometries)) 164 0 : return TRUE; 165 0 : else if (EQUAL(pszCap, ODsCZGeometries)) 166 0 : return TRUE; 167 : 168 0 : return FALSE; 169 : } 170 : 171 : /************************************************************************/ 172 : /* GetLayer() */ 173 : /************************************************************************/ 174 : 175 73 : OGRLayer *OGRILI2DataSource::GetLayer(int iLayer) 176 : 177 : { 178 73 : list<OGRLayer *>::const_iterator layerIt = listLayer.begin(); 179 73 : int i = 0; 180 706 : while (i < iLayer && layerIt != listLayer.end()) 181 : { 182 633 : ++i; 183 633 : ++layerIt; 184 : } 185 : 186 73 : if (i == iLayer && layerIt != listLayer.end()) 187 : { 188 73 : OGRILI2Layer *tmpLayer = reinterpret_cast<OGRILI2Layer *>(*layerIt); 189 73 : return tmpLayer; 190 : } 191 : 192 0 : return nullptr; 193 : }