kDB: Knowledge DataBase
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 {
22 using ReturnType = cres_qresult<bool>;
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 {
35 using ReturnType = cres_qresult<bool>;
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,
41 const QuantityValue<_T_>& _rhs)
42 {
43 return _lhs < _rhs;
44 }
45 };
46 template<>
48 {
49 using ReturnType = bool;
50 static ReturnType isEqual(const BigNumber& _lhs, const BigNumber& _rhs)
51 {
52 return _lhs == _rhs;
53 }
54 static ReturnType isStrictlyInferior(const BigNumber& _lhs, const BigNumber& _rhs)
55 {
56 return _lhs < _rhs;
57 }
58 };
59 } // namespace details
64 template<typename _T_>
65 class Range
66 {
67 public:
68 Range() : m_lowerType(RangeBoundType::Unset), m_upperType(RangeBoundType::Unset) {}
69 Range(RangeBoundType _lower_type, const _T_& _lower, const _T_& _upper,
70 RangeBoundType _upper_type)
71 : m_lower(_lower), m_lowerType(_lower_type), m_upper(_upper), m_upperType(_upper_type)
72 {
73 }
74 ~Range() {}
75
76 bool operator==(const Range& _rhs) const;
77 _T_ lower() const { return m_lower; }
78 RangeBoundType lowerBoundType() const { return m_lowerType; }
79 _T_ upper() const { return m_upper; }
80 RangeBoundType upperBoundType() const { return m_upperType; }
81
85 typename details::RangeComparator<_T_>::ReturnType contains(const _T_& _v) const
86 requires(std::is_same_v<typename details::RangeComparator<_T_>::ReturnType, bool>);
91 requires(
92 std::is_same_v<typename details::RangeComparator<_T_>::ReturnType, cres_qresult<bool>>);
93
97 cres_qresult<QByteArray> md5() const;
101 cres_qresult<QJsonValue> toJsonValue(const SerialisationContexts& _contexts
102 = defaultSerialisationContext()) const;
106 static cres_qresult<Range> fromJsonValue(const QJsonValue& _value,
107 const DeserialisationContexts& _context
108 = defaultDeserialisationContext());
112 cres_qresult<QCborValue> toCborValue(const SerialisationContexts& _contexts
113 = defaultSerialisationContext()) const;
117 static cres_qresult<Range> fromCborValue(const QCborValue& _value,
118 const DeserialisationContexts& _context
119 = defaultDeserialisationContext());
123 cres_qresult<QString> toRdfLiteral(const SerialisationContexts& _contexts
124 = defaultSerialisationContext()) const;
128 static cres_qresult<Range> fromRdfLiteral(const QString& _value,
129 const DeserialisationContexts& _context
130 = defaultDeserialisationContext());
134 cres_qresult<QString> printable() const;
135 private:
136 _T_ m_lower;
137 RangeBoundType m_lowerType;
138 _T_ m_upper;
139 RangeBoundType m_upperType;
140 };
141
142 template<typename _T_>
143 bool Range<_T_>::operator==(const Range& _rhs) const
144 {
145 return m_lowerType == _rhs.m_lowerType and m_upperType == _rhs.m_upperType
146 and m_lower == _rhs.m_lower and m_upper == _rhs.m_upper;
147 }
148
149#define __KNOWCORE_DATATYPE_KEY QString("datatype")
150#define __KNOWCORE_VALUE_KEY QString("value")
151
152 namespace details
153 {
154 template<typename _T_>
156 {
157 };
158 template<>
160 { // TODO this should be generalized
161 static auto md5(const Value& _value) { return _value.md5(); }
162 static cres_qresult<QJsonValue> toJsonValue(const Value& _value,
163 const SerialisationContexts& _contexts)
164 {
165 QJsonObject obj;
166 obj[__KNOWCORE_DATATYPE_KEY] = QString(_value.datatype());
167 cres_try(QJsonValue value, _value.toJsonValue(_contexts));
168 obj[__KNOWCORE_VALUE_KEY] = value;
169 return cres_success(obj);
170 }
171 static cres_qresult<Value> fromJsonValue(const QJsonValue& _value,
172 const DeserialisationContexts& _contexts)
173 {
174 QJsonObject obj = _value.toObject();
175 cres_try(Value value, Value::fromJsonValue(obj[__KNOWCORE_DATATYPE_KEY].toString(),
176 obj[__KNOWCORE_VALUE_KEY], _contexts));
177 return cres_success(value);
178 }
179 static cres_qresult<QCborValue> toCborValue(const Value& _value,
180 const SerialisationContexts& _contexts)
181 {
182 QCborMap obj;
183 obj[__KNOWCORE_DATATYPE_KEY] = QString(_value.datatype());
184 cres_try(QCborValue value, _value.toCborValue(_contexts));
185 obj[__KNOWCORE_VALUE_KEY] = value;
186 return cres_success(obj);
187 }
188 static cres_qresult<Value> fromCborValue(const QCborValue& _value,
189 const DeserialisationContexts& _contexts)
190 {
191 QCborMap obj = _value.toMap();
192 cres_try(Value value, Value::fromCborValue(obj[__KNOWCORE_DATATYPE_KEY].toString(),
193 obj[__KNOWCORE_VALUE_KEY], _contexts));
194 return cres_success(value);
195 }
196 static cres_qresult<QString> toRdfLiteral(const Value& _value,
197 const SerialisationContexts& _contexts)
198 {
199 cres_try(QString lit, _value.toRdfLiteral(_contexts));
200 return cres_success(clog_qt::qformat("<{}>({})", _value.datatype(), lit));
201 }
202 static cres_qresult<Value> fromRdfLiteral(const QString& _value,
203 const DeserialisationContexts& _contexts)
204 {
205 QRegularExpressionMatch match = QRegularExpression("<(.*)>(.*)").match(_value);
206 if(match.hasMatch())
207 {
208 return Value::fromRdfLiteral(match.captured(1), match.captured(2), _contexts);
209 }
210 else
211 {
212 return cres_failure("Invalid range value literal.");
213 }
214 }
215 };
216 } // namespace details
217
218 template<typename _T_>
219 inline cres_qresult<QByteArray> Range<_T_>::md5() const
220 {
221 QCryptographicHash hash(QCryptographicHash::Md5);
222 cres_try(QByteArray value_lower, details::RangeRDFLiteral<_T_>::md5(lower()));
223 cres_try(QByteArray value_upper, details::RangeRDFLiteral<_T_>::md5(upper()));
224 hash.addData(value_lower);
225 Cyqlops::Crypto::Hash::compute(hash, lowerBoundType());
226 hash.addData(value_upper);
227 Cyqlops::Crypto::Hash::compute(hash, upperBoundType());
228 // hash.addData(int(upperBoundType()));
229 return cres_success(hash.result());
230 }
231
232 template<typename _T_>
234 requires(std::is_same_v<typename details::RangeComparator<_T_>::ReturnType, cres_qresult<bool>>)
235 {
236 switch(lowerBoundType())
237 {
238 case RangeBoundType::Inclusive:
239 {
240 cres_try(bool v, details::RangeComparator<_T_>::isEqual(_v, lower()));
241 if(v)
242 {
243 break;
244 }
245 Q_FALLTHROUGH();
246 }
247 case RangeBoundType::Exclusive:
248 {
249 cres_try(bool v, details::RangeComparator<_T_>::isStrictlyInferior(_v, lower()));
250 if(v)
251 {
252 return cres_success(false);
253 }
254 }
255 case RangeBoundType::Unset:
256 break;
257 }
258 switch(upperBoundType())
259 {
260 case RangeBoundType::Inclusive:
261 {
262 cres_try(bool v, details::RangeComparator<_T_>::isEqual(_v, upper()));
263 if(v)
264 {
265 break;
266 }
267 Q_FALLTHROUGH();
268 }
269 case RangeBoundType::Exclusive:
270 {
271 cres_try(bool v, details::RangeComparator<_T_>::isStrictlyInferior(upper(), _v));
272 if(v)
273 {
274 return cres_success(false);
275 }
276 }
277 case RangeBoundType::Unset:
278 break;
279 }
280 return cres_success(true);
281 }
282
283 template<typename _T_>
285 requires(std::is_same_v<typename details::RangeComparator<_T_>::ReturnType, bool>)
286 {
287 switch(lowerBoundType())
288 {
289 case RangeBoundType::Inclusive:
290 {
292 {
293 break;
294 }
295 Q_FALLTHROUGH();
296 }
297 case RangeBoundType::Exclusive:
298 {
299 if(details::RangeComparator<_T_>::isStrictlyInferior(_v, lower()))
300 {
301 return cres_success(false);
302 }
303 }
304 case RangeBoundType::Unset:
305 break;
306 }
307 switch(upperBoundType())
308 {
309 case RangeBoundType::Inclusive:
310 {
311 if(details::RangeComparator<_T_>::isEqual(_v, upper()))
312 {
313 break;
314 }
315 Q_FALLTHROUGH();
316 }
317 case RangeBoundType::Exclusive:
318 {
319 if(details::RangeComparator<_T_>::isStrictlyInferior(upper(), _v))
320 {
321 return cres_success(false);
322 }
323 }
324 case RangeBoundType::Unset:
325 break;
326 }
327 return true;
328 }
329
330#define __KNOWCORE_LOWER_VALUE_KEY QString("lower_value")
331#define __KNOWCORE_LOWER_TYPE_KEY QString("lower_type")
332#define __KNOWCORE_UPPER_VALUE_KEY QString("upper_value")
333#define __KNOWCORE_UPPER_TYPE_KEY QString("upper_value")
334
335 template<typename _T_>
336 inline cres_qresult<QJsonValue>
338 {
339 QJsonObject object;
340 cres_try(object[__KNOWCORE_LOWER_VALUE_KEY],
342 cres_try(object[__KNOWCORE_UPPER_VALUE_KEY],
344 object[__KNOWCORE_LOWER_TYPE_KEY] = (int)lowerBoundType();
345 object[__KNOWCORE_UPPER_TYPE_KEY] = (int)upperBoundType();
346 return cres_success(object);
347 }
348
349 template<typename _T_>
350 inline cres_qresult<Range<_T_>> Range<_T_>::fromJsonValue(const QJsonValue& _value,
351 const DeserialisationContexts& _context)
352 {
353 if(_value.isObject())
354 {
355 QJsonObject object = _value.toObject();
357 object.value(__KNOWCORE_LOWER_VALUE_KEY), _context));
359 object.value(__KNOWCORE_UPPER_VALUE_KEY), _context));
360 RangeBoundType lowerType = RangeBoundType(object.value(__KNOWCORE_LOWER_TYPE_KEY).toInt());
361 RangeBoundType upperType = RangeBoundType(object.value(__KNOWCORE_UPPER_TYPE_KEY).toInt());
362 return cres_success<Range<_T_>>({lowerType, lower, upper, upperType});
363 }
364 else
365 {
366 return cres_failure("Expected object got {}", _value);
367 }
368 }
369
370 template<typename _T_>
371 inline cres_qresult<QCborValue>
373 {
374 QCborMap object;
375 cres_try(object[__KNOWCORE_LOWER_VALUE_KEY],
377 cres_try(object[__KNOWCORE_UPPER_VALUE_KEY],
379 object[__KNOWCORE_LOWER_TYPE_KEY] = (int)lowerBoundType();
380 object[__KNOWCORE_UPPER_TYPE_KEY] = (int)upperBoundType();
381 return cres_success(object);
382 }
383
384 template<typename _T_>
385 inline cres_qresult<Range<_T_>> Range<_T_>::fromCborValue(const QCborValue& _value,
386 const DeserialisationContexts& _context)
387 {
388 if(_value.isMap())
389 {
390 QCborMap object = _value.toMap();
392 object.value(__KNOWCORE_LOWER_VALUE_KEY), _context));
394 object.value(__KNOWCORE_UPPER_VALUE_KEY), _context));
395 RangeBoundType lowerType
396 = RangeBoundType(object.value(__KNOWCORE_LOWER_TYPE_KEY).toInteger());
397 RangeBoundType upperType
398 = RangeBoundType(object.value(__KNOWCORE_UPPER_TYPE_KEY).toInteger());
399 return cres_success<Range<_T_>>({lowerType, lower, upper, upperType});
400 }
401 else
402 {
403 return cres_failure("Expected object got {}", _value);
404 }
405 }
406
407 template<typename _T_>
408 inline cres_qresult<QString>
410 {
411 QString v;
412 switch(lowerBoundType())
413 {
414 case RangeBoundType::Exclusive:
415 case RangeBoundType::Unset:
416 v = "]]";
417 break;
418 case RangeBoundType::Inclusive:
419 v = "[[";
420 break;
421 }
422 QString str_lower, str_upper;
423 if(lowerBoundType() == RangeBoundType::Unset)
424 {
425 str_lower = "inf";
426 }
427 else
428 {
429 cres_try(str_lower, details::RangeRDFLiteral<_T_>::toRdfLiteral(lower(), _contexts));
430 }
431 if(upperBoundType() == RangeBoundType::Unset)
432 {
433 str_upper = "inf";
434 }
435 else
436 {
437 cres_try(str_upper, details::RangeRDFLiteral<_T_>::toRdfLiteral(upper(), _contexts));
438 }
439
440 v += str_lower + ", " + str_upper;
441
442 switch(upperBoundType())
443 {
444 case RangeBoundType::Exclusive:
445 case RangeBoundType::Unset:
446 v += "[[";
447 break;
448 case RangeBoundType::Inclusive:
449 v += "]]";
450 break;
451 }
452
453 return cres_success(v);
454 }
455
456 template<typename _T_>
457 inline cres_qresult<Range<_T_>>
458 Range<_T_>::fromRdfLiteral(const QString& _value, const DeserialisationContexts& _context)
459 {
460 if(_value.size() < 5)
461 return cres_failure("Invalid range RDF Literal: '{}'", _value);
462
463 QString lowerBoundString = _value.left(2);
464 QString upperBoundString = _value.right(2);
465 QStringList values = _value.mid(2, _value.size() - 4).split(",", KNOWCORE_QT_SKIP_EMPTY_PART);
466
467 RangeBoundType lowerBoundType;
468 if(lowerBoundString == "]]")
469 lowerBoundType = RangeBoundType::Exclusive;
470 else if(lowerBoundString == "[[")
471 lowerBoundType = RangeBoundType::Inclusive;
472 else
473 return cres_failure("Invalid lower bound symbol: '{}'", lowerBoundString);
474
475 RangeBoundType upperBoundType;
476 if(upperBoundString == "[[")
477 upperBoundType = RangeBoundType::Exclusive;
478 else if(upperBoundString == "]]")
479 upperBoundType = RangeBoundType::Inclusive;
480 else
481 return cres_failure("Invalid lower bound symbol: '{}'", lowerBoundString);
482
483 if(values.size() != 2)
484 return cres_failure("Got wrong amount of values in: '{}' got {} expected 2", _value,
485 values.size());
486
487 _T_ lower, upper;
488 if(values[0] == "inf")
489 {
490 lowerBoundType = RangeBoundType::Unset;
491 }
492 else
493 {
494 cres_try(lower, details::RangeRDFLiteral<_T_>::fromRdfLiteral(values[0], _context));
495 }
496 if(values[1] == "inf")
497 {
498 upperBoundType = RangeBoundType::Unset;
499 }
500 else
501 {
502 cres_try(upper, details::RangeRDFLiteral<_T_>::fromRdfLiteral(values[1], _context));
503 }
504
505 return cres_success<Range<_T_>>({lowerBoundType, lower, upper, upperBoundType});
506 }
507
508 template<typename _T_>
509 inline cres_qresult<QString> Range<_T_>::printable() const
510 {
511 return toRdfLiteral();
512 }
513
514#undef __KNOWCORE_LOWER_VALUE_KEY
515#undef __KNOWCORE_LOWER_TYPE_KEY
516#undef __KNOWCORE_UPPER_VALUE_KEY
517#undef __KNOWCORE_UPPER_TYPE_KEY
518
519} // namespace knowCore
520
521#include "MetaType.h"
522KNOWCORE_DECLARE_FULL_METATYPE(knowCore, QuantityNumberRange);
523KNOWCORE_DECLARE_FULL_METATYPE(knowCore, NumberRange);
524KNOWCORE_DECLARE_FULL_METATYPE(knowCore, ValueRange);
525
526#include "Formatter.h"
527clog_format_declare_enum_formatter(knowCore::RangeBoundType, Exclusive, Inclusive, Unset);
528
529template<typename _T_>
530struct std::formatter<knowCore::Range<_T_>>
531 : public knowCore::printable_formatter<knowCore::Range<_T_>>
532{
533};
Class that can contains large numeric value.
Definition BigNumber.h:51
Definition MetaType.h:126
Definition MetaType.h:66
Definition QuantityValue.h:22
Definition Range.h:66
cres_qresult< QString > printable() const
Definition Range.h:509
details::RangeComparator< _T_ >::ReturnType contains(const _T_ &_v) const
Definition Range.h:233
details::RangeComparator< _T_ >::ReturnType contains(const _T_ &_v) const
static cres_qresult< Range > fromRdfLiteral(const QString &_value, const DeserialisationContexts &_context=defaultDeserialisationContext())
Definition Range.h:458
static cres_qresult< Range > fromJsonValue(const QJsonValue &_value, const DeserialisationContexts &_context=defaultDeserialisationContext())
Definition Range.h:350
cres_qresult< QString > toRdfLiteral(const SerialisationContexts &_contexts=defaultSerialisationContext()) const
Definition Range.h:409
cres_qresult< QByteArray > md5() const
Definition Range.h:219
cres_qresult< QJsonValue > toJsonValue(const SerialisationContexts &_contexts=defaultSerialisationContext()) const
Definition Range.h:337
static cres_qresult< Range > fromCborValue(const QCborValue &_value, const DeserialisationContexts &_context=defaultDeserialisationContext())
Definition Range.h:385
cres_qresult< QCborValue > toCborValue(const SerialisationContexts &_contexts=defaultSerialisationContext()) const
Definition Range.h:372
Definition MetaType.h:159
Definition Value.h:21
Uri datatype() const
Definition Value.cpp:230
cres_qresult< bool > compare(const Value &_value, ComparisonOperators _operators) const
Definition Value.cpp:316
Definition Formatter.h:12