tryParseHeaderLine method

bool tryParseHeaderLine(
  1. String line, {
  2. bool lossy = false,
})

Try and parse the given line as one of the recognized lines in the header of a non-symbolic stack trace.

If lossy is true, then the parser assumes that some header lines may have been lost (e.g., due to log truncation) and recreates missing parts of the header from other parsed parts if possible.

Returns whether the line was recognized and parsed successfully.

Implementation

bool tryParseHeaderLine(String line, {bool lossy = false}) {
  if (line.contains(_headerStartLine)) {
    // This is the start of a new non-symbolic stack trace, so reset all the
    // stored information to be parsed anew.
    _os = null;
    _arch = null;
    _compressed = null;
    _simulated = null;
    _buildId = null;
    _isolateStart = null;
    _isolateDsoBase = null;
    _vmStart = null;
    _units = null;
    return true;
  }
  RegExpMatch? match;
  match = _osArchLineRE.firstMatch(line);
  if (match != null) {
    _os = match[1]!;
    _arch = match[2]!;
    _compressed = match[3]! == "yes";
    _simulated = match[4]! == "yes";
    if (lossy) {
      // Reset all stored information that is parsed after this point,
      // just in case we've missed earlier lines in this header.
      _buildId = null;
      _isolateStart = null;
      _isolateDsoBase = null;
      _vmStart = null;
      _units = null;
    }
    return true;
  }
  // Have to check for loading units first because they can include a
  // build ID, so the build ID RegExp matches them as well.
  match = _loadingUnitLineRE.firstMatch(line);
  if (match != null) {
    _units ??= <int, LoadingUnit>{};
    final id = int.parse(match[1]!);
    final buildId = match[2];
    final dsoBase = int.parse(match[3]!, radix: 16);
    final start = int.parse(match[4]!, radix: 16);
    _units![id] = LoadingUnit(id, dsoBase, start, buildId: buildId);
    if (lossy) {
      // Reset all stored information that is parsed after this point,
      // just in case we've missed earlier lines in this header.
      _isolateStart = null;
      _isolateDsoBase = null;
      _vmStart = null;
    }
    return true;
  }
  match = _buildIdRE.firstMatch(line);
  if (match != null) {
    _buildId = match[1]!;
    if (lossy) {
      // Reset all stored information that is parsed after this point,
      // just in case we've missed earlier lines in this header.
      _isolateStart = null;
      _isolateDsoBase = null;
      _vmStart = null;
      _units = null;
    }
    return true;
  }
  match = _isolateDsoBaseLineRE.firstMatch(line);
  if (match != null) {
    _isolateDsoBase = int.parse(match[1]!, radix: 16);
    if (lossy) {
      // Reset all stored information that is parsed after this point,
      // just in case we've missed earlier lines in this header.
      _isolateStart = null;
      _vmStart = null;
    }
    return true;
  }
  match = _instructionsLineRE.firstMatch(line);
  if (match != null) {
    _isolateStart = int.parse(match[1]!, radix: 16);
    _vmStart = int.parse(match[2]!, radix: 16);
    if (_units != null) {
      final rootUnit = _units![constants.rootLoadingUnitId];
      if (lossy && rootUnit == null) {
        // We missed the header entry for the root loading unit, but it can
        // be reconstructed from other header lines.
        _units![constants.rootLoadingUnitId] = LoadingUnit(
          constants.rootLoadingUnitId,
          _isolateDsoBase!,
          _isolateStart!,
          buildId: _buildId,
        );
      } else {
        assert(rootUnit != null);
        assert(_isolateStart == rootUnit!.start);
        assert(_isolateDsoBase == rootUnit!.dsoBase);
        assert(_buildId == null || _buildId == rootUnit!.buildId);
      }
    }
    return true;
  }
  return false;
}