Commit a618604

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2023-12-16 10:27:51
rewrite formatter decoding to be more stable and faster
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent 5391b8f
Changed files (2)
lib
model
export_import
test
model
lib/model/export_import/record_formatter.dart
@@ -40,11 +40,7 @@ class ScriptedFormatter implements Formatter {
   (RowDataFieldType, dynamic)? decode(String formattedRecord) {
     if (restoreAbleType == null) return null;
 
-    final valueRegex = RegExp(pattern.replaceAll(RegExp(r'\$(TIMESTAMP|COLOR|SYS|DIA|PUL|NOTE)'), '(?<value>.*)'),);
-    final match = valueRegex.firstMatch(formattedRecord);
-    if (match == null) return null;
-    var text = match.namedGroup('value');
-    if (text == null) return null;
+    final text = formattedRecord.substring(_padLeft!, formattedRecord.length - _padRight!);
 
     final value = (){switch(restoreAbleType!) {
       case RowDataFieldType.timestamp:
@@ -104,33 +100,63 @@ class ScriptedFormatter implements Formatter {
 
   @override
   String? get formatPattern => pattern;
-  
+
   bool _hasRestoreableType = false;
   RowDataFieldType? _restoreAbleType;
 
+  /// Count of characters to the left of the value to parse in [pattern].
+  ///
+  /// Guaranteed to be not null when [restoreAbleType] != null.
+  int? _padLeft;
+
+  /// Count of characters to the right of the value to parse in [pattern].
+  ///
+  /// Guaranteed to be not null when [restoreAbleType] != null.
+  int? _padRight;
+
+
   @override
   RowDataFieldType? get restoreAbleType {
     if (_hasRestoreableType == false) {
       final replaced = pattern.replaceFirst(RegExp(r'[^{},$]*\$(SYS|DIA|PUL)[^{},$]*'), '');
-      print('$pattern - $replaced - ${replaced.contains(RegExp(r'[^{},$]*\$(PUL|DIA|SYS)[^{},$]*'))}');
       if (pattern.contains(RegExp(r'[{},]'))) {
         _restoreAbleType = null;
-      } else if (pattern == r'$TIMESTAMP') { 
-        _restoreAbleType = RowDataFieldType.timestamp; 
-      } else if (pattern == r'$COLOR') { 
-        _restoreAbleType = RowDataFieldType.color; 
+      } else if (pattern == r'$TIMESTAMP') {
+        _restoreAbleType = RowDataFieldType.timestamp;
+      } else if (pattern == r'$COLOR') {
+        _restoreAbleType = RowDataFieldType.color;
       } else if (pattern == r'$NOTE') {
         _restoreAbleType = RowDataFieldType.notes;
       } else if (replaced.contains(RegExp(r'[^{},$]*\$(PUL|DIA|SYS)[^{},$]*'))) {
         _restoreAbleType = null;
       } else if (pattern.contains(RegExp(r'[^{},$]*\$(SYS)[^{},$]*'))) {
-        _restoreAbleType = RowDataFieldType.sys; 
+        _restoreAbleType = RowDataFieldType.sys;
       } else if (pattern.contains(RegExp(r'[^{},$]*\$(DIA)[^{},$]*'))) {
-        _restoreAbleType = RowDataFieldType.dia; 
+        _restoreAbleType = RowDataFieldType.dia;
       } else if (pattern.contains(RegExp(r'[^{},$]*\$(PUL)[^{},$]*'))) {
-        _restoreAbleType = RowDataFieldType.pul; 
+        _restoreAbleType = RowDataFieldType.pul;
       } else { _restoreAbleType = null; }
       _hasRestoreableType = true;
+
+      if (_restoreAbleType != null) {
+        int index = pattern.indexOf(RegExp(r'\$(SYS|DIA|PUL)'));
+        int len = 3;
+        if (index < 0) {
+          index = pattern.indexOf(RegExp(r'\$(NOTE)'));
+          len = 4;
+        }
+        if (index < 0) {
+          index = pattern.indexOf(RegExp(r'\$(COLOR)'));
+          len = 5;
+        }
+        if (index < 0) {
+          index = pattern.indexOf(RegExp(r'\$(TIMESTAMP)'));
+          len = 9;
+        }
+        assert(index >= 0);
+        _padLeft = index;
+        _padRight = pattern.length - (index + len + 1);
+      }
     }
     return _restoreAbleType;
   }
test/model/export_import/record_formatter_test.dart
@@ -82,8 +82,34 @@ void main() {
       expect(ScriptedFormatter(r'$PUL$SYS',).decode('123456'), null);
       expect(ScriptedFormatter(r'$SYS$SYS',).decode('123123'), null);
     });
-    // TODO: test amd fix:
-    // - 'Unterminated group' error
-    // - exports containing regex
+
+    test('should when ignore groups in format strings', () {
+      expect(ScriptedFormatter(r'($SYS)',).encode(mockRecord(sys: 123)), '(123)');
+      expect(ScriptedFormatter(r'($SYS',).encode(mockRecord(sys: 123)), '(123');
+      expect(ScriptedFormatter(r'($NOTE',).encode(mockRecord(note: 'test')), '(test');
+
+      expect(ScriptedFormatter(r'($SYS)',).restoreAbleType, RowDataFieldType.sys);
+      expect(ScriptedFormatter(r'($SYS',).restoreAbleType, RowDataFieldType.sys);
+      expect(ScriptedFormatter(r'($NOTE',).restoreAbleType, null);
+
+      expect(ScriptedFormatter(r'($SYS)',).decode('(123)'), (RowDataFieldType.sys, 123));
+      expect(ScriptedFormatter(r'($SYS',).decode('(123'), (RowDataFieldType.sys, 123));
+      expect(ScriptedFormatter(r'($NOTE',).decode('(test'), null);
+    });
   });
-}
\ No newline at end of file
+}
+
+BloodPressureRecord mockRecord({
+  DateTime? time,
+  int? sys,
+  int? dia,
+  int? pul,
+  String? note,
+  Color? pin,
+}) => BloodPressureRecord(
+    time ?? DateTime.now(),
+    sys,
+    dia,
+    pul,
+    note ?? '',
+    needlePin: pin == null ? null : MeasurementNeedlePin(pin));
\ No newline at end of file