41 #include <libxml/parser.h> 42 #include <libxml/xmlschemas.h> 46 const char * pzSchema=
"\ 47 <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>\ 48 <xs:simpleType name='SIPrefixType'>\ 49 <xs:restriction base='xs:token'>\ 50 <xs:pattern value='[0-9]+(.[0-9]+){0,1}(G|M|K){0,1}'/>\ 53 <xs:simpleType name='SINRType'>\ 54 <xs:restriction base='xs:token'>\ 55 <xs:pattern value='[+-]?(0|[1-9][0-9]*)(.[0-9]{1,2})?'/>\ 58 <xs:simpleType name='PORType'>\ 59 <xs:restriction base='xs:token'>\ 60 <xs:pattern value='(0|[1-9][0-9]*)(.[0-9]{1,2})?'/>\ 63 <xs:element name='tdmabasemodel-pcr'>\ 66 <xs:element name='datarate' maxOccurs='unbounded'>\ 69 <xs:element name='entry' maxOccurs='unbounded'>\ 71 <xs:attribute name='sinr' type='SINRType' use='optional'/>\ 72 <xs:attribute name='por' type='PORType' use='optional'/>\ 76 <xs:attribute name='bps' type='SIPrefixType' use='required'/>\ 80 <xs:attribute name='packetsize' type='xs:unsignedShort' use='required'/>\ 85 std::string scaleFloatToInteger(
const std::string & sValue)
87 const int iScaleFactor{2};
88 std::string sTmpParameter{sValue};
91 std::string::size_type indexPoint = sTmpParameter.find(
".",0);
93 if(indexPoint != std::string::npos)
95 std::string::size_type numberOfDigitsAfterPoint =
96 sTmpParameter.size() - indexPoint - 1;
98 if(numberOfDigitsAfterPoint > iScaleFactor)
101 sTmpParameter.insert(sTmpParameter.size() - (numberOfDigitsAfterPoint - iScaleFactor),
107 sTmpParameter.append(iScaleFactor - numberOfDigitsAfterPoint,
'0');
111 sTmpParameter.erase(indexPoint,1);
116 sTmpParameter.append(iScaleFactor,
'0');
119 return sTmpParameter;
124 u64DefaultCurveDataRate_{},
125 modifierLengthBytes_{}{}
129 xmlDocPtr pSchemaDoc{xmlReadMemory(pzSchema,
131 "file:///tdmabasemodelpcr.xsd",
136 throw makeException<ConfigurationException>(
"unable to open schema");
139 xmlSchemaParserCtxtPtr pParserContext{xmlSchemaNewDocParserCtxt(pSchemaDoc)};
143 throw makeException<ConfigurationException>(
"bad schema context");
146 xmlSchemaPtr pSchema{xmlSchemaParse(pParserContext)};
150 throw makeException<ConfigurationException>(
"bad schema parser");
153 xmlSchemaValidCtxtPtr pSchemaValidCtxtPtr{xmlSchemaNewValidCtxt(pSchema)};
155 if(!pSchemaValidCtxtPtr)
157 throw makeException<ConfigurationException>(
"bad schema valid context");
160 xmlSchemaSetValidOptions(pSchemaValidCtxtPtr,XML_SCHEMA_VAL_VC_I_CREATE);
162 xmlDocPtr pDoc = xmlReadFile(sPCRFileName.c_str(),
nullptr,0);
164 if(xmlSchemaValidateDoc(pSchemaValidCtxtPtr, pDoc))
166 throw makeException<ConfigurationException>(
"invalid document: %s",
167 sPCRFileName.c_str());
170 xmlNodePtr pRoot = xmlDocGetRootElement(pDoc);
172 xmlChar * pPacketSize = xmlGetProp(pRoot,BAD_CAST
"packetsize");
176 xmlFree(pPacketSize);
178 for(xmlNodePtr pDataRateNode = pRoot->children;
179 pDataRateNode !=
nullptr;
180 pDataRateNode = pDataRateNode->next)
182 if(!xmlStrcmp(pDataRateNode->name, BAD_CAST
"datarate"))
184 xmlChar * pDataRatebps = xmlGetProp(pDataRateNode,BAD_CAST
"bps");
186 std::uint64_t u64DataRatebps =
189 xmlFree(pDataRatebps);
191 if(dataRateTable_.empty())
193 u64DefaultCurveDataRate_ = u64DataRatebps;
197 std::int32_t i32MinScaledSINR{std::numeric_limits<std::int32_t>::max()};
198 std::int32_t i32MaxScaledSINR{std::numeric_limits<std::int32_t>::lowest()};
200 for(xmlNodePtr pEntryNode = pDataRateNode->children;
201 pEntryNode !=
nullptr;
202 pEntryNode = pEntryNode->next)
204 if(!xmlStrcmp(pEntryNode->name, BAD_CAST
"entry"))
206 xmlChar * pSINR = xmlGetProp(pEntryNode,BAD_CAST
"sinr");
207 xmlChar * pPOR = xmlGetProp(pEntryNode,BAD_CAST
"por");
209 std::int32_t i32ScaledSINR =
213 curve.insert(std::make_pair(i32ScaledSINR,
218 throw makeException<ConfigurationException>(
"duplicate PCR SINR value for datarate: %zu sinr: %s in %s",
220 reinterpret_cast<const char *
>(pSINR),
221 sPCRFileName.c_str());
227 i32MinScaledSINR = std::min(i32ScaledSINR,i32MinScaledSINR);
228 i32MaxScaledSINR = std::max(i32ScaledSINR,i32MaxScaledSINR);
232 Curve interpolation{};
234 auto iter = curve.begin();
236 while(iter != curve.end())
238 auto x0 = iter->first;
239 auto y0 = iter->second;
243 if(iter != curve.end())
245 auto x1 = iter->first;
246 auto y1 = iter->second;
248 auto slope = (y1 - y0) / (x1 - x0);
250 for(
auto i = x0; i < x1; ++i)
252 interpolation.insert({i,y1 - (x1 - i) * slope});
257 curve.insert(interpolation.begin(),interpolation.end());
259 auto ret = dataRateTable_.insert(std::make_pair(u64DataRatebps,
260 std::make_tuple(i32MinScaledSINR,
266 throw makeException<ConfigurationException>(
"duplicate PCR datarate: %zu in %s",
268 sPCRFileName.c_str());
274 xmlFreeDoc(pSchemaDoc);
282 size_t packetLengthBytes)
284 auto iter = dataRateTable_.find(u64DataRatebps);
286 if(iter == dataRateTable_.end())
288 iter = dataRateTable_.find(u64DefaultCurveDataRate_);
291 std::int32_t i32MinScaledSINR = std::get<0>(iter->second);
292 std::int32_t i32MaxScaledSINR = std::get<1>(iter->second);
293 Curve & curve = std::get<2>(iter->second);
295 std::int32_t i32Scaled{
static_cast<std::int32_t
>(fSINR * 100)};
297 if(i32Scaled < i32MinScaledSINR)
302 if(i32Scaled > i32MaxScaledSINR)
307 auto curveIter = curve.find(i32Scaled);
309 if(curveIter != curve.end())
311 auto por = curveIter->second;
313 if(modifierLengthBytes_)
315 por = powf(por, packetLengthBytes / static_cast<float>(modifierLengthBytes_));
325 EMANE::Models::TDMA::PORManager::PORManager::dump()
329 for(
const auto & dataRateEntry : dataRateTable_)
333 for(
const auto & porEntry : std::get<2>(dataRateEntry.second))
335 entries.insert({porEntry.first / 100.0, porEntry.second});
338 ret.insert({dataRateEntry.first,entries});
void load(const std::string &sPCRFileName)
std::map< std::uint64_t, CurveDump > CurveDumps
std::map< float, float > CurveDump
std::uint16_t toUINT16(std::uint16_t u16Min=std::numeric_limits< std::uint16_t >::min(), std::uint16_t u16Max=std::numeric_limits< std::uint16_t >::max()) const
std::uint64_t toUINT64(std::uint64_t u64Min=std::numeric_limits< std::uint64_t >::min(), std::uint64_t u64Max=std::numeric_limits< std::uint64_t >::max()) const
float getPOR(std::uint64_t u64DataRate, float fSINR, size_t packetLengthBytes)
std::int32_t toINT32(std::int32_t i32Min=std::numeric_limits< std::int32_t >::min(), std::int32_t i32Max=std::numeric_limits< std::int32_t >::max()) const
Parameter conversion class with range checks.