37 #include <libxml/parser.h>    40                                       const std::string sSubRootName,
    41                                       double dMissingValue):
    42   dMissingValue_{dMissingValue}
    44   xmlParserCtxtPtr pContext{xmlNewParserCtxt()};
    51   xmlDocPtr pDoc{xmlCtxtReadFile(pContext,sAntennaPatternURI.c_str(),
nullptr,XML_PARSE_DTDVALID)};
    56       xmlFreeParserCtxt(pContext);
    57       throw makeException<AntennaProfileException>(
"Unable to read %s",sAntennaPatternURI.c_str());
    60   if(pContext->valid == 
false)
    63       xmlFreeParserCtxt(pContext);
    64       throw makeException<AntennaProfileException>(
"Validation failure %s",sAntennaPatternURI.c_str());
    67   xmlNodePtr pRoot{xmlDocGetRootElement(pDoc)};
    72       xmlFreeParserCtxt(pContext);
    73       throw makeException<AntennaProfileException>(
"Invalid document root %s",
    74                                                    sAntennaPatternURI.c_str());
    78   for(xmlNodePtr pNode = pRoot->children; pNode; pNode = pNode->next)
    80       if(pNode->type == XML_ELEMENT_NODE)
    82           if(!xmlStrcmp(pNode->name,BAD_CAST sSubRootName.c_str()))
    84               std::int16_t i16ElevationRangeMax{};
    86               for(xmlNodePtr pElevationNode = pNode->children;
    88                   pElevationNode = pElevationNode->next)
    90                   if(pElevationNode->type == XML_ELEMENT_NODE)
    92                       if(!xmlStrcmp(pElevationNode->name,BAD_CAST 
"elevation"))
    94                           xmlChar * pMin{xmlGetProp(pElevationNode,BAD_CAST 
"min")};
    96                           std::int16_t i16ElevationMin =
   101                           xmlChar * pMax{xmlGetProp(pElevationNode,BAD_CAST 
"max")};
   103                           std::int16_t i16ElevationMax =
   108                           if(i16ElevationMin > i16ElevationMax)
   110                               throw makeException<AntennaProfileException>(
"Bad entry %s: elevation [%hd,%hd] min > max",
   111                                                                            sAntennaPatternURI.c_str(),
   116                           if(i16ElevationRangeMax >= i16ElevationMin && !elevationBearingGainMap_.empty())
   118                               throw makeException<AntennaProfileException>(
"Bad entry %s: elevation [%hd,%hd] may may be"   119                                                                            " out of order or overlap with a previous elevation",
   120                                                                            sAntennaPatternURI.c_str(),
   126                               i16ElevationRangeMax = i16ElevationMax;
   129                           BearingGainMap * pBearingGainMap{
new BearingGainMap};
   131                           bearings_.push_back(std::unique_ptr<BearingGainMap>(pBearingGainMap));
   133                           std::int16_t i16BearingRangeMax{};
   135                           for(xmlNodePtr pBearingNode = pElevationNode->children;
   137                               pBearingNode = pBearingNode->next)
   139                               if(pBearingNode->type == XML_ELEMENT_NODE)
   141                                   if(!xmlStrcmp(pBearingNode->name,BAD_CAST 
"bearing"))
   143                                      xmlChar * pMin{xmlGetProp(pBearingNode,BAD_CAST 
"min")};
   145                                      std::int16_t i16BearingMin =
   150                                      xmlChar * pMax{xmlGetProp(pBearingNode,BAD_CAST 
"max")};
   152                                      std::int16_t i16BearingMax =
   157                                      if(i16BearingMin > i16BearingMax)
   159                                          throw makeException<AntennaProfileException>(
"Bad entry %s: elevation [%hd,%hd] bearing [%hd,%hd] min > max",
   160                                                                                       sAntennaPatternURI.c_str(),
   167                                      if(i16BearingRangeMax >= i16BearingMin && !pBearingGainMap->empty())
   169                                          throw makeException<AntennaProfileException>(
"Bad entry %s: elevation [%hd,%hd] bearing [%hd,%hd]"   170                                                                                       " may be out of order or overlap with a previous bearing",
   171                                                                                       sAntennaPatternURI.c_str(),
   179                                          i16BearingRangeMax = i16BearingMax;
   182                                      for(xmlNodePtr pGainNode = pBearingNode->children;
   184                                          pGainNode = pGainNode->next)
   186                                          if(pGainNode->type == XML_ELEMENT_NODE)
   188                                              if(!xmlStrcmp(pGainNode->name,BAD_CAST 
"gain"))
   190                                                  xmlChar * pGain{xmlGetProp(pGainNode,BAD_CAST 
"value")};
   197                                                  if(pBearingGainMap->find(i16BearingMin-1) == pBearingGainMap->end())
   199                                                      (*pBearingGainMap)[i16BearingMin-1] = dMissingValue_;
   202                                                  (*pBearingGainMap)[i16BearingMax] = dGain;
   210                           if(elevationBearingGainMap_.find(i16ElevationMin-1) == elevationBearingGainMap_.end())
   212                               elevationBearingGainMap_[i16ElevationMin-1] = 
nullptr;
   215                           elevationBearingGainMap_[i16ElevationMax] = pBearingGainMap;
   224   xmlFreeParserCtxt(pContext);
   229   double dGain{dMissingValue_};
   237   const auto iter = elevationBearingGainMap_.lower_bound(iElevation);
   239   if(iter != elevationBearingGainMap_.end())
   243           const auto bearingIter = iter->second->lower_bound(iBearing);
   245           if(bearingIter != iter->second->end())
   247               dGain = bearingIter->second;
 
double toDouble(double dMin=std::numeric_limits< double >::lowest(), double dMax=std::numeric_limits< double >::max()) const
double getGain(std::int16_t iBearing, std::int16_t iElevation) const
std::int16_t toINT16(std::int16_t i16Min=std::numeric_limits< std::int16_t >::min(), std::int16_t i16Max=std::numeric_limits< std::int16_t >::max()) const
AntennaPattern(const std::string &sAntennaPatternURI, const std::string sSubRootName, double dMissingValue)
Parameter conversion class with range checks.