knowL: Knowledge Libraries
Loading...
Searching...
No Matches
Range.h
1#pragma once
2
3#include <Cyqlops/Crypto/Hash.h>
4
5#include "QuantityValue.h"
6
7namespace knowCore
8{
9 enum class RangeBoundType
10 {
11 Exclusive,
12 Inclusive,
13 Unset
14 };
15 namespace details
16 {
17 template<typename _T_>
19 template<>
21 {
23 static ReturnType isEqual(const Value& _lhs, const Value& _rhs)
24 {
25 return _lhs.compare(_rhs, knowCore::ComparisonOperator::Equal);
26 }
27 static ReturnType isStrictlyInferior(const Value& _lhs, const Value& _rhs)
28 {
29 return _lhs.compare(_rhs, knowCore::ComparisonOperator::Inferior);
30 }
31 };
32 template<typename _T_>
34 {
36 static ReturnType isEqual(const QuantityValue<_T_>& _lhs, const QuantityValue<_T_>& _rhs)
37 {
38 return _lhs == _rhs;
39 }
40 static ReturnType isStrictlyInferior(const QuantityValue<_T_>& _lhs, const QuantityValue<_T_>& _rhs)
41 {
42 return _lhs < _rhs;
43 }
44 };
45 template<>
47 {
48 using ReturnType = bool;
49 static ReturnType isEqual(const BigNumber& _lhs, const BigNumber& _rhs)
50 {
51 return _lhs == _rhs;
52 }
53 static ReturnType isStrictlyInferior(const BigNumber& _lhs, const BigNumber& _rhs)
54 {
55 return _lhs < _rhs;
56 }
57 };
58 }
63 template<typename _T_>
64 class Range
65 {
66 public:
67 Range() : m_lowerType(RangeBoundType::Unset), m_upperType(RangeBoundType::Unset) {}
68 Range(RangeBoundType _lower_type, const _T_& _lower, const _T_& _upper, RangeBoundType _upper_type) : m_lower(_lower), m_lowerType(_lower_type), m_upper(_upper), m_upperType(_upper_type) {}
69 ~Range() {}
70
71 bool operator==(const Range& _rhs) const;
72 _T_ lower() const { return m_lower; }
73 RangeBoundType lowerBoundType() const { return m_lowerType; }
74 _T_ upper() const { return m_upper; }
75 RangeBoundType upperBoundType() const { return m_upperType; }
76
80 typename details::RangeComparator<_T_>::ReturnType contains(const _T_& _v) const requires (std::is_same_v<typename details::RangeComparator<_T_>::ReturnType, bool>);
84 typename details::RangeComparator<_T_>::ReturnType contains(const _T_& _v) const requires (std::is_same_v<typename details::RangeComparator<_T_>::ReturnType, ReturnValue<bool>>);
85
93 ReturnValue<QJsonValue> toJsonValue(const SerialisationContexts& _contexts = defaultSerialisationContext()) const;
97 static ReturnValue<Range> fromJsonValue(const QJsonValue& _value, const DeserialisationContexts& _context = defaultDeserialisationContext());
101 ReturnValue<QCborValue> toCborValue(const SerialisationContexts& _contexts = defaultSerialisationContext()) const;
105 static ReturnValue<Range> fromCborValue(const QCborValue& _value, const DeserialisationContexts& _context = defaultDeserialisationContext());
109 ReturnValue<QString> toRdfLiteral(const SerialisationContexts& _contexts = defaultSerialisationContext()) const;
113 static ReturnValue<Range> fromRdfLiteral(const QString& _value, const DeserialisationContexts& _context = defaultDeserialisationContext());
118 private:
119 _T_ m_lower;
120 RangeBoundType m_lowerType;
121 _T_ m_upper;
122 RangeBoundType m_upperType;
123 };
124
125 template<typename _T_>
126 bool Range<_T_>::operator==(const Range& _rhs) const
127 {
128 return m_lowerType == _rhs.m_lowerType and m_upperType == _rhs.m_upperType and m_lower == _rhs.m_lower and m_upper == _rhs.m_upper;
129 }
130
131#define __KNOWCORE_DATATYPE_KEY QString("datatype")
132#define __KNOWCORE_VALUE_KEY QString("value")
133
134 namespace details
135 {
136 template<typename _T_>
138 {
139 };
140 template<>
142 { // TODO this should be generalized
143 static auto md5(const Value& _value)
144 {
145 return _value.md5();
146 }
147 static ReturnValue<QJsonValue> toJsonValue(const Value& _value, const SerialisationContexts& _contexts)
148 {
149 QJsonObject obj;
150 obj[__KNOWCORE_DATATYPE_KEY] = QString(_value.datatype());
151 KNOWCORE_RETURN_VALUE_TRY(value, _value.toJsonValue(_contexts));
152 obj[__KNOWCORE_VALUE_KEY] = value;
153 return kCrvSuccess(obj);
154 }
155 static ReturnValue<Value> fromJsonValue(const QJsonValue& _value, const DeserialisationContexts& _contexts)
156 {
157 QJsonObject obj = _value.toObject();
158 KNOWCORE_RETURN_VALUE_TRY(value, Value::fromJsonValue(obj[__KNOWCORE_DATATYPE_KEY].toString(), obj[__KNOWCORE_VALUE_KEY], _contexts));
159 return kCrvSuccess(value);
160 }
161 static ReturnValue<QCborValue> toCborValue(const Value& _value, const SerialisationContexts& _contexts)
162 {
163 QCborMap obj;
164 obj[__KNOWCORE_DATATYPE_KEY] = QString(_value.datatype());
165 KNOWCORE_RETURN_VALUE_TRY(value, _value.toCborValue(_contexts));
166 obj[__KNOWCORE_VALUE_KEY] = value;
167 return kCrvSuccess(obj);
168 }
169 static ReturnValue<Value> fromCborValue(const QCborValue& _value, const DeserialisationContexts& _contexts)
170 {
171 QCborMap obj = _value.toMap();
172 KNOWCORE_RETURN_VALUE_TRY(value, Value::fromCborValue(obj[__KNOWCORE_DATATYPE_KEY].toString(), obj[__KNOWCORE_VALUE_KEY], _contexts));
173 return kCrvSuccess(value);
174 }
175 static ReturnValue<QString> toRdfLiteral(const Value& _value, const SerialisationContexts& _contexts)
176 {
177 KNOWCORE_RETURN_VALUE_TRY(lit, _value.toRdfLiteral(_contexts));
178 return kCrvSuccess(clog_qt::qformat("<{}>({})", _value.datatype(), lit));
179 }
180 static ReturnValue<Value> fromRdfLiteral(const QString& _value, const DeserialisationContexts& _contexts)
181 {
182 QRegularExpressionMatch match = QRegularExpression("<(.*)>(.*)").match(_value);
183 if(match.hasMatch())
184 {
185 return Value::fromRdfLiteral(match.captured(0), match.captured(1), _contexts);
186 } else {
187 return kCrvError("Invalid range value literal.");
188 }
189 }
190 };
191 }
192
193 template<typename _T_>
195 {
196 QCryptographicHash hash(QCryptographicHash::Md5);
197 KNOWCORE_RETURN_VALUE_TRY(value_lower, details::RangeRDFLiteral<_T_>::md5(lower()));
198 KNOWCORE_RETURN_VALUE_TRY(value_upper, details::RangeRDFLiteral<_T_>::md5(upper()));
199 hash.addData(value_lower);
200 Cyqlops::Crypto::Hash::compute(hash, lowerBoundType());
201 hash.addData(value_upper);
202 Cyqlops::Crypto::Hash::compute(hash, upperBoundType());
203 // hash.addData(int(upperBoundType()));
204 return kCrvSuccess(hash.result());
205 }
206
207 template<typename _T_>
209 requires (std::is_same_v<typename details::RangeComparator<_T_>::ReturnType, ReturnValue<bool>>)
210 {
211 switch(lowerBoundType())
212 {
213 case RangeBoundType::Inclusive:
214 {
215 KNOWCORE_RETURN_VALUE_TRY(v, details::RangeComparator<_T_>::isEqual(_v, lower()));
216 if(v)
217 {
218 break;
219 }
220 Q_FALLTHROUGH();
221 }
222 case RangeBoundType::Exclusive:
223 {
224 KNOWCORE_RETURN_VALUE_TRY(v, details::RangeComparator<_T_>::isStrictlyInferior(_v, lower()));
225 if(v)
226 {
227 return kCrvSuccess(false);
228 }
229 }
230 case RangeBoundType::Unset:
231 break;
232 }
233 switch(upperBoundType())
234 {
235 case RangeBoundType::Inclusive:
236 {
237 KNOWCORE_RETURN_VALUE_TRY(v, details::RangeComparator<_T_>::isEqual(_v, upper()));
238 if(v)
239 {
240 break;
241 }
242 Q_FALLTHROUGH();
243 }
244 case RangeBoundType::Exclusive:
245 {
246 KNOWCORE_RETURN_VALUE_TRY(v, details::RangeComparator<_T_>::isStrictlyInferior(upper(), _v));
247 if(v)
248 {
249 return kCrvSuccess(false);
250 }
251 }
252 case RangeBoundType::Unset:
253 break;
254 }
255 return kCrvSuccess(true);
256 }
257
258 template<typename _T_>
260 requires (std::is_same_v<typename details::RangeComparator<_T_>::ReturnType, bool>)
261 {
262 switch(lowerBoundType())
263 {
264 case RangeBoundType::Inclusive:
265 {
267 {
268 break;
269 }
270 Q_FALLTHROUGH();
271 }
272 case RangeBoundType::Exclusive:
273 {
274 if(details::RangeComparator<_T_>::isStrictlyInferior(_v, lower()))
275 {
276 return kCrvSuccess(false);
277 }
278 }
279 case RangeBoundType::Unset:
280 break;
281 }
282 switch(upperBoundType())
283 {
284 case RangeBoundType::Inclusive:
285 {
286 if(details::RangeComparator<_T_>::isEqual(_v, upper()))
287 {
288 break;
289 }
290 Q_FALLTHROUGH();
291 }
292 case RangeBoundType::Exclusive:
293 {
294 if(details::RangeComparator<_T_>::isStrictlyInferior(upper(), _v))
295 {
296 return kCrvSuccess(false);
297 }
298 }
299 case RangeBoundType::Unset:
300 break;
301 }
302 return true;
303 }
304
305#define __KNOWCORE_LOWER_VALUE_KEY QString("lower_value")
306#define __KNOWCORE_LOWER_TYPE_KEY QString("lower_type")
307#define __KNOWCORE_UPPER_VALUE_KEY QString("upper_value")
308#define __KNOWCORE_UPPER_TYPE_KEY QString("upper_value")
309
310 template<typename _T_>
312 {
313 QJsonObject object;
314 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(object[__KNOWCORE_LOWER_VALUE_KEY], details::RangeRDFLiteral<_T_>::toJsonValue(lower(), _contexts));
315 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(object[__KNOWCORE_UPPER_VALUE_KEY], details::RangeRDFLiteral<_T_>::toJsonValue(upper(), _contexts));
316 object[__KNOWCORE_LOWER_TYPE_KEY] = (int)lowerBoundType();
317 object[__KNOWCORE_UPPER_TYPE_KEY] = (int)upperBoundType();
318 return kCrvSuccess(object);
319 }
320
321 template<typename _T_>
322 inline ReturnValue<Range<_T_>> Range<_T_>::fromJsonValue(const QJsonValue& _value, const DeserialisationContexts& _context)
323 {
324 if(_value.isObject())
325 {
326 QJsonObject object = _value.toObject();
327 KNOWCORE_RETURN_VALUE_TRY(lower, details::RangeRDFLiteral<_T_>::fromJsonValue(object.value(__KNOWCORE_LOWER_VALUE_KEY), _context));
328 KNOWCORE_RETURN_VALUE_TRY(upper, details::RangeRDFLiteral<_T_>::fromJsonValue(object.value(__KNOWCORE_UPPER_VALUE_KEY), _context));
329 RangeBoundType lowerType = RangeBoundType(object.value(__KNOWCORE_LOWER_TYPE_KEY).toInt());
330 RangeBoundType upperType = RangeBoundType(object.value(__KNOWCORE_UPPER_TYPE_KEY).toInt());
331 return kCrvSuccess<Range<_T_>>({lowerType, lower, upper, upperType});
332 } else {
333 return kCrvError("Expected object got {}", _value);
334 }
335 }
336
337 template<typename _T_>
339 {
340 QCborMap object;
341 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(object[__KNOWCORE_LOWER_VALUE_KEY], details::RangeRDFLiteral<_T_>::toCborValue(lower(), _contexts));
342 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(object[__KNOWCORE_UPPER_VALUE_KEY], details::RangeRDFLiteral<_T_>::toCborValue(upper(), _contexts));
343 object[__KNOWCORE_LOWER_TYPE_KEY] = (int)lowerBoundType();
344 object[__KNOWCORE_UPPER_TYPE_KEY] = (int)upperBoundType();
345 return kCrvSuccess(object);
346 }
347
348 template<typename _T_>
349 inline ReturnValue<Range<_T_>> Range<_T_>::fromCborValue(const QCborValue& _value, const DeserialisationContexts& _context)
350 {
351 if(_value.isMap())
352 {
353 QCborMap object = _value.toMap();
354 KNOWCORE_RETURN_VALUE_TRY(lower, details::RangeRDFLiteral<_T_>::fromCborValue(object.value(__KNOWCORE_LOWER_VALUE_KEY), _context));
355 KNOWCORE_RETURN_VALUE_TRY(upper, details::RangeRDFLiteral<_T_>::fromCborValue(object.value(__KNOWCORE_UPPER_VALUE_KEY), _context));
356 RangeBoundType lowerType = RangeBoundType(object.value(__KNOWCORE_LOWER_TYPE_KEY).toInteger());
357 RangeBoundType upperType = RangeBoundType(object.value(__KNOWCORE_UPPER_TYPE_KEY).toInteger());
358 return kCrvSuccess<Range<_T_>>({lowerType, lower, upper, upperType});
359 } else {
360 return kCrvError("Expected object got {}", _value);
361 }
362 }
363
364 template<typename _T_>
366 {
367 QString v;
368 switch(lowerBoundType())
369 {
370 case RangeBoundType::Exclusive:
371 case RangeBoundType::Unset:
372 v = "]]";
373 break;
374 case RangeBoundType::Inclusive:
375 v = "[[";
376 break;
377 }
378 QString str_lower, str_upper;
379 if(lowerBoundType() == RangeBoundType::Unset)
380 {
381 str_lower = "inf";
382 } else {
383 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(str_lower, details::RangeRDFLiteral<_T_>::toRdfLiteral(lower(), _contexts));
384 }
385 if(upperBoundType() == RangeBoundType::Unset)
386 {
387 str_upper = "inf";
388 } else {
389 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(str_upper, details::RangeRDFLiteral<_T_>::toRdfLiteral(upper(), _contexts));
390 }
391
392 v += str_lower + ", " + str_upper;
393
394 switch(upperBoundType())
395 {
396 case RangeBoundType::Exclusive:
397 case RangeBoundType::Unset:
398 v += "[[";
399 break;
400 case RangeBoundType::Inclusive:
401 v += "]]";
402 break;
403 }
404
405 return kCrvSuccess(v);
406 }
407
408 template<typename _T_>
409 inline ReturnValue<Range<_T_>> Range<_T_>::fromRdfLiteral(const QString& _value, const DeserialisationContexts& _context)
410 {
411 if(_value.size() < 5) return kCrvError("Invalid range RDF Literal: '{}'", _value);
412
413 QString lowerBoundString = _value.left(2);
414 QString upperBoundString = _value.right(2);
415 QStringList values = _value.mid(2, _value.size() - 4).split(",", KNOWCORE_QT_SKIP_EMPTY_PART);
416
417 RangeBoundType lowerBoundType;
418 if(lowerBoundString == "]]") lowerBoundType = RangeBoundType::Exclusive;
419 else if(lowerBoundString == "[[") lowerBoundType = RangeBoundType::Inclusive;
420 else return kCrvError("Invalid lower bound symbol: '{}'", lowerBoundString);
421
422 RangeBoundType upperBoundType;
423 if(upperBoundString == "[[") upperBoundType = RangeBoundType::Exclusive;
424 else if(upperBoundString == "]]") upperBoundType = RangeBoundType::Inclusive;
425 else return kCrvError("Invalid lower bound symbol: '{}'", lowerBoundString);
426
427 if(values.size() != 2) return kCrvError("Got wrong amount of values in: '{}' got {} expected 2", _value, values.size());
428
429 _T_ lower, upper;
430 if(values[0] == "inf")
431 {
432 lowerBoundType = RangeBoundType::Unset;
433 } else {
434 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(lower, details::RangeRDFLiteral<_T_>::fromRdfLiteral(values[0], _context));
435 }
436 if(values[1] == "inf")
437 {
438 upperBoundType = RangeBoundType::Unset;
439 } else {
440 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(upper, details::RangeRDFLiteral<_T_>::fromRdfLiteral(values[1], _context));
441 }
442
443 return kCrvSuccess<Range<_T_>>({lowerBoundType, lower, upper, upperBoundType});
444 }
445
446 template<typename _T_>
448 {
449 return toRdfLiteral();
450 }
451
452#undef __KNOWCORE_LOWER_VALUE_KEY
453#undef __KNOWCORE_LOWER_TYPE_KEY
454#undef __KNOWCORE_UPPER_VALUE_KEY
455#undef __KNOWCORE_UPPER_TYPE_KEY
456
457}
458
459#include "MetaType.h"
460KNOWCORE_DECLARE_FULL_METATYPE(knowCore, QuantityNumberRange)
461KNOWCORE_DECLARE_FULL_METATYPE(knowCore, NumberRange)
462KNOWCORE_DECLARE_FULL_METATYPE(knowCore, ValueRange)
463
464#include "Formatter.h"
465KNOWCORE_CORE_DECLARE_FORMATTER_ENUM(knowCore::RangeBoundType, Exclusive, Inclusive, Unset)
466
467template<typename _T_>
468struct fmt::formatter<knowCore::Range<_T_>> : public knowCore::printable_formatter<knowCore::Range<_T_>> {};
Class that can contains large numeric value.
Definition BigNumber.h:46
Definition MetaType.h:114
Definition MetaType.h:58
Definition QuantityValue.h:21
Definition Range.h:65
ReturnValue< QByteArray > md5() const
Definition Range.h:194
details::RangeComparator< _T_ >::ReturnType contains(const _T_ &_v) const
Definition Range.h:208
ReturnValue< QString > printable() const
Definition Range.h:447
ReturnValue< QJsonValue > toJsonValue(const SerialisationContexts &_contexts=defaultSerialisationContext()) const
Definition Range.h:311
static ReturnValue< Range > fromRdfLiteral(const QString &_value, const DeserialisationContexts &_context=defaultDeserialisationContext())
Definition Range.h:409
details::RangeComparator< _T_ >::ReturnType contains(const _T_ &_v) const
static ReturnValue< Range > fromJsonValue(const QJsonValue &_value, const DeserialisationContexts &_context=defaultDeserialisationContext())
Definition Range.h:322
ReturnValue< QCborValue > toCborValue(const SerialisationContexts &_contexts=defaultSerialisationContext()) const
Definition Range.h:338
static ReturnValue< Range > fromCborValue(const QCborValue &_value, const DeserialisationContexts &_context=defaultDeserialisationContext())
Definition Range.h:349
ReturnValue< QString > toRdfLiteral(const SerialisationContexts &_contexts=defaultSerialisationContext()) const
Definition Range.h:365
Definition ReturnValue.h:29
Definition MetaType.h:145
Definition Value.h:13
Uri datatype() const
Definition Value.cpp:199
ReturnValue< bool > compare(const Value &_value, ComparisonOperators _operators) const
Definition Value.cpp:299
Definition Formatter.h:20