mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-13 07:35:41 +08:00
Ref T338, utility functions / parsing
- nthIndexOf - measurement unit can be parsed case insensitive - CSimpleCommandParser::remainingStringAfter from n-th space - improved frequency parsing
This commit is contained in:
@@ -322,12 +322,9 @@ namespace BlackCore
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isNumber;
|
||||
const double frequencyMhz = receiver.toDouble(&isNumber);
|
||||
if (isNumber)
|
||||
CFrequency radioFrequency = CComSystem::parseComFrequency(receiver, CPqString::SeparatorsBestGuess);
|
||||
if (!radioFrequency.isNull())
|
||||
{
|
||||
CFrequency radioFrequency = CFrequency(frequencyMhz, CFrequencyUnit::MHz());
|
||||
CComSystem::roundToChannelSpacing(radioFrequency, CComSystem::ChannelSpacing8_33KHz);
|
||||
if (CComSystem::isValidCivilAviationFrequency(radioFrequency))
|
||||
{
|
||||
tm.setFrequency(radioFrequency);
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
*/
|
||||
|
||||
#include "blackmisc/aviation/comsystem.h"
|
||||
#include "blackmisc/dbus.h"
|
||||
#include "blackmisc/math/mathutils.h"
|
||||
#include "blackmisc/dbus.h"
|
||||
|
||||
#include <QDBusMetaType>
|
||||
#include <QtDebug>
|
||||
@@ -102,24 +102,28 @@ namespace BlackMisc
|
||||
bool CComSystem::isValidCivilAviationFrequency(const CFrequency &f)
|
||||
{
|
||||
if (f.isNull()) return false;
|
||||
double fr = f.valueRounded(BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz(), 3);
|
||||
return fr >= 118.0 && fr <= 136.975;
|
||||
|
||||
// comparsion in int avoids double compare issues
|
||||
const int fr = f.valueInteger(PhysicalQuantities::CFrequencyUnit::kHz());
|
||||
return fr >= 118000 && fr <= 136975;
|
||||
}
|
||||
|
||||
bool CComSystem::isValidMilitaryFrequency(const CFrequency &f)
|
||||
{
|
||||
if (f.isNull()) return false;
|
||||
double fr = f.valueRounded(BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz(), 3);
|
||||
return fr >= 220.0 && fr <= 399.95;
|
||||
const int fr = f.valueInteger(PhysicalQuantities::CFrequencyUnit::kHz());
|
||||
return fr >= 220000 && fr <= 399950;
|
||||
}
|
||||
|
||||
bool CComSystem::isValidComFrequency(const CFrequency &f)
|
||||
{
|
||||
if (f.isNull()) { return false; }
|
||||
return isValidCivilAviationFrequency(f) || isValidMilitaryFrequency(f);
|
||||
}
|
||||
|
||||
void CComSystem::roundToChannelSpacing(CFrequency &frequency, ChannelSpacing channelSpacing)
|
||||
{
|
||||
if (frequency.isNull()) { return; }
|
||||
const double channelSpacingKHz = CComSystem::channelSpacingToFrequencyKHz(channelSpacing);
|
||||
const double f = frequency.valueRounded(CFrequencyUnit::kHz(), 0);
|
||||
const quint32 d = static_cast<quint32>(f / channelSpacingKHz);
|
||||
@@ -133,6 +137,7 @@ namespace BlackMisc
|
||||
|
||||
bool CComSystem::isWithinChannelSpacing(const CFrequency &setFrequency, const CFrequency &compareFrequency, CComSystem::ChannelSpacing channelSpacing)
|
||||
{
|
||||
if (setFrequency.isNull()) { return false; }
|
||||
if (setFrequency == compareFrequency) return true; // shortcut for many of such comparisons
|
||||
double channelSpacingKHz = 0.5 * CComSystem::channelSpacingToFrequencyKHz(channelSpacing);
|
||||
double compareFrequencyKHz = compareFrequency.value(CFrequencyUnit::kHz());
|
||||
@@ -141,6 +146,38 @@ namespace BlackMisc
|
||||
(setFrequencyKHz + channelSpacingKHz > compareFrequencyKHz);
|
||||
}
|
||||
|
||||
CFrequency CComSystem::parseComFrequency(const QString &input, CPqString::SeparatorMode sep)
|
||||
{
|
||||
if (input.isEmpty()) { return CFrequency::null(); }
|
||||
CFrequency comFreq;
|
||||
if (isDigitsOnlyString(input))
|
||||
{
|
||||
const double f = input.toDouble();
|
||||
comFreq = CFrequency(f, f > 999 ? CFrequencyUnit::kHz() : CFrequencyUnit::MHz());
|
||||
}
|
||||
else
|
||||
{
|
||||
comFreq.parseFromString(input, sep);
|
||||
if (comFreq.isNull())
|
||||
{
|
||||
bool ok;
|
||||
const double f = CPqString::parseNumber(input, ok, sep);
|
||||
if (ok)
|
||||
{
|
||||
comFreq = CFrequency(f, f > 999 ? CFrequencyUnit::kHz() : CFrequencyUnit::MHz());
|
||||
}
|
||||
else
|
||||
{
|
||||
comFreq = CFrequency::null();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (comFreq.isNull()) { return CFrequency::null(); }
|
||||
roundToChannelSpacing(comFreq, ChannelSpacing8_33KHz);
|
||||
return isValidComFrequency(comFreq) ? comFreq : CFrequency::null();
|
||||
}
|
||||
|
||||
double CComSystem::channelSpacingToFrequencyKHz(ChannelSpacing channelSpacing)
|
||||
{
|
||||
switch (channelSpacing)
|
||||
|
||||
@@ -13,15 +13,16 @@
|
||||
#define BLACKMISC_AVIATION_COMSYSTEM_H
|
||||
|
||||
#include "blackmisc/aviation/modulator.h"
|
||||
#include "blackmisc/blackmiscexport.h"
|
||||
#include "blackmisc/dictionary.h"
|
||||
#include "blackmisc/json.h"
|
||||
#include "blackmisc/metaclass.h"
|
||||
#include "blackmisc/pq/constants.h"
|
||||
#include "blackmisc/pq/frequency.h"
|
||||
#include "blackmisc/pq/physicalquantity.h"
|
||||
#include "blackmisc/pq/units.h"
|
||||
#include "blackmisc/pq/pqstring.h"
|
||||
#include "blackmisc/blackmiscexport.h"
|
||||
#include "blackmisc/propertyindexvariantmap.h"
|
||||
#include "blackmisc/dictionary.h"
|
||||
#include "blackmisc/json.h"
|
||||
#include "blackmisc/variant.h"
|
||||
|
||||
#include <QHash>
|
||||
@@ -132,6 +133,9 @@ namespace BlackMisc
|
||||
const PhysicalQuantities::CFrequency &compareFrequency,
|
||||
ChannelSpacing channelSpacing);
|
||||
|
||||
//! Parses almost any shitty string to a valid COM frequency
|
||||
static PhysicalQuantities::CFrequency parseComFrequency(const QString &input, PhysicalQuantities::CPqString::SeparatorMode sep);
|
||||
|
||||
//! \copydoc BlackMisc::CValueObject::registerMetadata
|
||||
static void registerMetadata();
|
||||
|
||||
|
||||
@@ -354,26 +354,93 @@ namespace BlackMisc
|
||||
*/
|
||||
template <class U> static U unitFromSymbol(const QString &symbol, bool strict = true)
|
||||
{
|
||||
if (symbol.isEmpty()) return U::defaultUnit();
|
||||
for (const auto unit : U::allUnits())
|
||||
if (symbol.isEmpty()) { return U::defaultUnit(); }
|
||||
|
||||
static const bool cs = hasCaseSensitiveSymbols<U>();
|
||||
for (const auto &unit : U::allUnits())
|
||||
{
|
||||
if (unit.getSymbol() == symbol) { return unit; }
|
||||
if (strict && cs)
|
||||
{
|
||||
if (unit.getSymbol() == symbol) { return unit; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stringCompare(unit.getSymbol(), symbol, Qt::CaseInsensitive)) { return unit; }
|
||||
}
|
||||
}
|
||||
if (strict) qFatal("Illegal unit name");
|
||||
return U::defaultUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* All symbols
|
||||
*/
|
||||
template <class U> static const QStringList &allSymbols()
|
||||
{
|
||||
static const QStringList symbols = []
|
||||
{
|
||||
QStringList s;
|
||||
for (const auto &unit : U::allUnits())
|
||||
{
|
||||
s.push_back(unit.getSymbol());
|
||||
}
|
||||
return s;
|
||||
}();
|
||||
return symbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* All symbols case insensitive
|
||||
*/
|
||||
template <class U> static const QStringList &allSymbolsLowerCase()
|
||||
{
|
||||
static const QStringList symbols = []
|
||||
{
|
||||
QSet<QString> s;
|
||||
for (const QString &symbol : allSymbols<U>())
|
||||
{
|
||||
s.insert(symbol.toLower());
|
||||
}
|
||||
return s.toList();
|
||||
}();
|
||||
return symbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are symbols case sensitive?
|
||||
*/
|
||||
template <class U> static bool hasCaseSensitiveSymbols()
|
||||
{
|
||||
static const bool cs = []
|
||||
{
|
||||
return (allSymbolsLowerCase<U>().size() != allSymbols<U>().size());
|
||||
}();
|
||||
return cs;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Valid unit symbol?
|
||||
* \param symbol to be tested
|
||||
*/
|
||||
template <class U> static bool isValidUnitSymbol(const QString &symbol)
|
||||
{
|
||||
static const bool cs = hasCaseSensitiveSymbols<U>();
|
||||
return cs ?
|
||||
isValidUnitSymbol<U>(symbol, Qt::CaseSensitive) :
|
||||
isValidUnitSymbol<U>(symbol, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Valid unit symbol?
|
||||
* \param symbol to be tested
|
||||
* \param caseSensitivity check case sensitiv?
|
||||
*/
|
||||
template <class U> static bool isValidUnitSymbol(const QString &symbol, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive)
|
||||
template <class U> static bool isValidUnitSymbol(const QString &symbol, Qt::CaseSensitivity caseSensitivity)
|
||||
{
|
||||
if (symbol.isEmpty()) return false;
|
||||
for (const auto unit : U::allUnits())
|
||||
for (const auto &unit : U::allUnits())
|
||||
{
|
||||
if (QString::compare(unit.getSymbol(), symbol, caseSensitivity) == 0) { return true; }
|
||||
if (stringCompare(unit.getSymbol(), symbol, caseSensitivity)) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -58,9 +58,10 @@ namespace BlackMisc
|
||||
|
||||
QString CSimpleCommandParser::remainingStringAfter(int index) const
|
||||
{
|
||||
if (index < 0) { return m_originalLine.trimmed(); }
|
||||
if (index < 0) { return m_cleanedLine; }
|
||||
const QString p = this->part(index);
|
||||
int fi = m_originalLine.indexOf(p, 0, Qt::CaseInsensitive);
|
||||
const int from = index < 1 ? 0 : nthIndexOf(m_cleanedLine, ' ', index, Qt::CaseInsensitive);
|
||||
const int fi = m_cleanedLine.indexOf(p, from, Qt::CaseInsensitive);
|
||||
if (fi < 0) { return ""; }
|
||||
return m_originalLine.mid(fi).trimmed();
|
||||
}
|
||||
|
||||
@@ -395,6 +395,22 @@ namespace BlackMisc
|
||||
if (question.endsWith("?")) { return question; }
|
||||
return question % QStringLiteral("?");
|
||||
}
|
||||
|
||||
int nthIndexOf(const QString &string, QChar ch, int nth, Qt::CaseSensitivity cs)
|
||||
{
|
||||
if (nth < 1 || string.isEmpty() || nth > string.length()) { return -1; }
|
||||
|
||||
int from = 0;
|
||||
int ci = -1;
|
||||
for (int t = 0; t < nth; ++t)
|
||||
{
|
||||
ci = string.indexOf(ch, from, cs);
|
||||
if (ci < 0) { return -1; }
|
||||
from = ci + 1;
|
||||
if (from >= string.length()) { return -1; }
|
||||
}
|
||||
return ci;
|
||||
}
|
||||
} // ns
|
||||
|
||||
//! \endcond
|
||||
|
||||
@@ -59,6 +59,9 @@ namespace BlackMisc
|
||||
return static_cast<int>(std::distance(s.begin(), it));
|
||||
}
|
||||
|
||||
//! nth index of ch
|
||||
BLACKMISC_EXPORT int nthIndexOf(const QString &string, QChar ch, int nth = 1, Qt::CaseSensitivity cs = Qt::CaseInsensitive);
|
||||
|
||||
//! Split a string into multiple strings, using a predicate function to identify the split points.
|
||||
//! \warning The returned refs are only valid during the lifetime of the original string.
|
||||
template <class F> QList<QStringRef> splitStringRefs(const QString &s, F predicate)
|
||||
|
||||
Reference in New Issue
Block a user