Line data Source code
1 : /********************************************************************** 2 : * 3 : * Project: GML Reader 4 : * Purpose: Implementation of GMLPropertyDefn 5 : * Author: Frank Warmerdam, warmerdam@pobox.com 6 : * 7 : ********************************************************************** 8 : * Copyright (c) 2002, Frank Warmerdam 9 : * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com> 10 : * 11 : * SPDX-License-Identifier: MIT 12 : ****************************************************************************/ 13 : 14 : #include "cpl_port.h" 15 : #include "gmlfeature.h" 16 : 17 : #include <cstring> 18 : 19 : #include "cpl_conv.h" 20 : #include "cpl_string.h" 21 : 22 : /************************************************************************/ 23 : /* GMLPropertyDefn */ 24 : /************************************************************************/ 25 : 26 2855 : GMLPropertyDefn::GMLPropertyDefn(const char *pszName, const char *pszSrcElement) 27 2855 : : m_pszName(CPLStrdup(pszName)), 28 2855 : m_pszSrcElement(pszSrcElement ? CPLStrdup(pszSrcElement) : nullptr), 29 5710 : m_nSrcElementLen(pszSrcElement ? strlen(pszSrcElement) : 0) 30 : { 31 2855 : } 32 : 33 : /************************************************************************/ 34 : /* ~GMLPropertyDefn() */ 35 : /************************************************************************/ 36 : 37 2855 : GMLPropertyDefn::~GMLPropertyDefn() 38 : 39 : { 40 2855 : CPLFree(m_pszName); 41 2855 : CPLFree(m_pszSrcElement); 42 2855 : CPLFree(m_pszCondition); 43 2855 : } 44 : 45 : /************************************************************************/ 46 : /* SetSrcElement() */ 47 : /************************************************************************/ 48 : 49 200 : void GMLPropertyDefn::SetSrcElement(const char *pszSrcElement) 50 : 51 : { 52 200 : CPLFree(m_pszSrcElement); 53 200 : if (pszSrcElement != nullptr) 54 : { 55 200 : m_nSrcElementLen = strlen(pszSrcElement); 56 200 : m_pszSrcElement = CPLStrdup(pszSrcElement); 57 : } 58 : else 59 : { 60 0 : m_nSrcElementLen = 0; 61 0 : m_pszSrcElement = nullptr; 62 : } 63 200 : } 64 : 65 : /************************************************************************/ 66 : /* SetCondition() */ 67 : /************************************************************************/ 68 : 69 4 : void GMLPropertyDefn::SetCondition(const char *pszCondition) 70 : { 71 4 : CPLFree(m_pszCondition); 72 4 : m_pszCondition = 73 4 : pszCondition != nullptr ? CPLStrdup(pszCondition) : nullptr; 74 4 : } 75 : 76 : /************************************************************************/ 77 : /* AnalysePropertyValue() */ 78 : /* */ 79 : /* Examine the passed property value, and see if we need to */ 80 : /* make the field type more specific, or more general. */ 81 : /************************************************************************/ 82 : 83 3766 : void GMLPropertyDefn::AnalysePropertyValue(const GMLProperty *psGMLProperty, 84 : bool bSetWidth) 85 : 86 : { 87 : /* -------------------------------------------------------------------- */ 88 : /* Does the string consist entirely of numeric values? */ 89 : /* -------------------------------------------------------------------- */ 90 3766 : bool bIsReal = false; 91 : 92 7702 : for (int j = 0; j < psGMLProperty->nSubProperties; j++) 93 : { 94 3936 : if (j > 0) 95 : { 96 170 : if (m_eType == GMLPT_Integer) 97 : { 98 3 : m_eType = GMLPT_IntegerList; 99 : } 100 167 : else if (m_eType == GMLPT_Integer64) 101 : { 102 0 : m_eType = GMLPT_Integer64List; 103 : } 104 167 : else if (m_eType == GMLPT_Real) 105 : { 106 2 : m_eType = GMLPT_RealList; 107 : } 108 165 : else if (m_eType == GMLPT_String) 109 : { 110 36 : m_eType = GMLPT_StringList; 111 36 : m_nWidth = 0; 112 : } 113 129 : else if (m_eType == GMLPT_Boolean) 114 1 : m_eType = GMLPT_BooleanList; 115 : } 116 3936 : const char *pszValue = psGMLProperty->papszSubProperties[j]; 117 : /* -------------------------------------------------------------------- 118 : */ 119 : /* If it is a zero length string, just return. We can't deduce */ 120 : /* much from this. */ 121 : /* -------------------------------------------------------------------- 122 : */ 123 3936 : if (*pszValue == '\0') 124 12 : continue; 125 : 126 3924 : const CPLValueType valueType = CPLGetValueType(pszValue); 127 : 128 3924 : if (valueType == CPL_VALUE_STRING && m_eType != GMLPT_String && 129 674 : m_eType != GMLPT_StringList) 130 : { 131 296 : if ((m_eType == GMLPT_Untyped || m_eType == GMLPT_Boolean) && 132 291 : (strcmp(pszValue, "true") == 0 || 133 281 : strcmp(pszValue, "false") == 0)) 134 : { 135 18 : m_eType = GMLPT_Boolean; 136 : } 137 278 : else if (m_eType == GMLPT_BooleanList) 138 : { 139 4 : if (!(strcmp(pszValue, "true") == 0 || 140 2 : strcmp(pszValue, "false") == 0)) 141 0 : m_eType = GMLPT_StringList; 142 : } 143 274 : else if (m_eType == GMLPT_IntegerList || 144 274 : m_eType == GMLPT_Integer64List || 145 274 : m_eType == GMLPT_RealList) 146 : { 147 0 : m_eType = GMLPT_StringList; 148 : } 149 : else 150 : { 151 274 : m_eType = GMLPT_String; 152 : } 153 : } 154 : else 155 : { 156 3628 : bIsReal = valueType == CPL_VALUE_REAL; 157 : } 158 : 159 3924 : if (m_eType == GMLPT_String) 160 : { 161 2550 : if (bSetWidth) 162 : { 163 : // Grow the Width to the length of the string passed in. 164 2526 : const int nWidth = static_cast<int>(strlen(pszValue)); 165 2526 : if (m_nWidth < nWidth) 166 320 : SetWidth(nWidth); 167 : } 168 : } 169 1374 : else if (m_eType == GMLPT_Untyped || m_eType == GMLPT_Integer || 170 499 : m_eType == GMLPT_Integer64) 171 : { 172 877 : if (bIsReal) 173 26 : m_eType = GMLPT_Real; 174 851 : else if (m_eType != GMLPT_Integer64) 175 : { 176 849 : const GIntBig nVal = CPLAtoGIntBig(pszValue); 177 849 : if (!CPL_INT64_FITS_ON_INT32(nVal)) 178 1 : m_eType = GMLPT_Integer64; 179 : else 180 848 : m_eType = GMLPT_Integer; 181 877 : } 182 : } 183 497 : else if ((m_eType == GMLPT_IntegerList || 184 497 : m_eType == GMLPT_Integer64List) && 185 : bIsReal) 186 : { 187 0 : m_eType = GMLPT_RealList; 188 : } 189 497 : else if (m_eType == GMLPT_IntegerList && valueType == CPL_VALUE_INTEGER) 190 : { 191 12 : GIntBig nVal = CPLAtoGIntBig(pszValue); 192 12 : if (!CPL_INT64_FITS_ON_INT32(nVal)) 193 1 : m_eType = GMLPT_Integer64List; 194 : } 195 : } 196 3766 : } 197 : 198 : /************************************************************************/ 199 : /* GMLGeometryPropertyDefn */ 200 : /************************************************************************/ 201 : 202 864 : GMLGeometryPropertyDefn::GMLGeometryPropertyDefn( 203 : const char *pszName, const char *pszSrcElement, OGRwkbGeometryType nType, 204 : int nAttributeIndex, bool bNullable, 205 864 : const OGRGeomCoordinatePrecision &oCoordPrec) 206 855 : : m_pszName((pszName == nullptr || pszName[0] == '\0') 207 912 : ? CPLStrdup(pszSrcElement) 208 807 : : CPLStrdup(pszName)), 209 1728 : m_pszSrcElement(CPLStrdup(pszSrcElement)), m_nGeometryType(nType), 210 : m_nAttributeIndex(nAttributeIndex), m_bNullable(bNullable), 211 864 : m_oCoordPrecision(oCoordPrec) 212 : { 213 864 : } 214 : 215 : /************************************************************************/ 216 : /* ~GMLGeometryPropertyDefn */ 217 : /************************************************************************/ 218 : 219 864 : GMLGeometryPropertyDefn::~GMLGeometryPropertyDefn() 220 : { 221 864 : CPLFree(m_pszName); 222 864 : CPLFree(m_pszSrcElement); 223 864 : } 224 : 225 : /************************************************************************/ 226 : /* MergeSRSName() */ 227 : /************************************************************************/ 228 : 229 9 : void GMLGeometryPropertyDefn::MergeSRSName(const std::string &osSRSName) 230 : 231 : { 232 9 : if (!m_bSRSNameConsistent) 233 0 : return; 234 : 235 9 : if (m_osSRSName.empty()) 236 : { 237 7 : m_osSRSName = osSRSName; 238 : } 239 : else 240 : { 241 2 : m_bSRSNameConsistent = osSRSName == m_osSRSName; 242 2 : if (!m_bSRSNameConsistent) 243 : { 244 1 : m_osSRSName.clear(); 245 : } 246 : } 247 : }