parse static method

UPdfCMap parse(
  1. Uint8List bytes, {
  2. bool vertical = false,
})

Implementation

static UPdfCMap parse(Uint8List bytes, {bool vertical = false}) {
  final List<UPdfCodespace> codespaces = <UPdfCodespace>[];
  final Map<int, int> singles = <int, int>{};
  final List<UPdfCidRange> ranges = <UPdfCidRange>[];
  final UDocCursor cursor = UDocCursor(bytes);
  final List<Object?> stack = <Object?>[];
  int guard = 0;
  while (!cursor.isEmpty && guard < 2000000) {
    guard++;
    UPdfSyntax.skipWhitespace(cursor);
    if (cursor.isEmpty) break;
    final int byte = cursor.peek;
    if (byte == 0x3C && cursor.peekAt(1) != 0x3C) {
      stack.add(UPdfSyntax.readHexString(cursor));
      continue;
    }
    if (byte == 0x2F || byte == 0x5B || byte == 0x28 || (byte == 0x3C && cursor.peekAt(1) == 0x3C) || UPdfSyntax.isDigit(byte) || byte == 0x2D || byte == 0x2E) {
      stack.add(UPdfSyntax.parseObject(cursor));
      continue;
    }
    final String keyword = UPdfSyntax.readKeyword(cursor);
    if (keyword.isEmpty) {
      cursor.skip(1);
      continue;
    }
    switch (keyword) {
      case "endcodespacerange":
        for (int i = 0; i + 1 < stack.length; i += 2) {
          final Object? low = stack[i];
          final Object? high = stack[i + 1];
          if (low is UPdfString && high is UPdfString) codespaces.add(UPdfCodespace(low.bytes.length, _toInt(low.bytes), _toInt(high.bytes)));
        }
        stack.clear();
        break;
      case "endcidrange":
      case "endbfrange":
        for (int i = 0; i + 2 < stack.length; i += 3) {
          final Object? low = stack[i];
          final Object? high = stack[i + 1];
          final Object? value = stack[i + 2];
          if (low is! UPdfString || high is! UPdfString) continue;
          if (value is num) {
            ranges.add(UPdfCidRange(_toInt(low.bytes), _toInt(high.bytes), value.toInt()));
          } else if (value is UPdfString) {
            ranges.add(UPdfCidRange(_toInt(low.bytes), _toInt(high.bytes), _toInt(value.bytes)));
          } else if (value is List<Object?>) {
            final int start = _toInt(low.bytes);
            for (int j = 0; j < value.length; j++) {
              final Object? entry = value[j];
              if (entry is UPdfString) singles[start + j] = _toInt(entry.bytes);
            }
          }
        }
        stack.clear();
        break;
      case "endcidchar":
      case "endbfchar":
        for (int i = 0; i + 1 < stack.length; i += 2) {
          final Object? code = stack[i];
          final Object? value = stack[i + 1];
          if (code is! UPdfString) continue;
          if (value is num) {
            singles[_toInt(code.bytes)] = value.toInt();
          } else if (value is UPdfString) {
            singles[_toInt(code.bytes)] = _toInt(value.bytes);
          }
        }
        stack.clear();
        break;
      case "begincodespacerange":
      case "begincidrange":
      case "beginbfrange":
      case "begincidchar":
      case "beginbfchar":
        stack.clear();
        break;
      default:
        if (stack.length > 3000) stack.clear();
        break;
    }
  }
  if (codespaces.isEmpty) codespaces.add(const UPdfCodespace(2, 0, 0xFFFF));
  return UPdfCMap(codespaces: codespaces, singles: singles, ranges: ranges, vertical: vertical);
}