docs: def scan(self, data, dlen=None):
          '''
          Scan a data block for matching signatures.
  
          @data - A string of data to scan.
          @dlen - If specified, signatures at offsets larger than dlen will be ignored.
  
          Returns a list of SignatureResult objects.
          '''
          results = []
          matched_offsets = set()
  
          # Since data can potentially be quite a large string, make it available to other
          # methods via a class attribute so that it doesn't need to be passed around to
          # different methods over and over again.
          self.data = data
  
          # If dlen wasn't specified, search all of self.data
          if dlen is None:
              dlen = len(data)
  
          for signature in self.signatures:
              # Use regex to search the data block for potential signature
              # matches (fast)
              for match in signature.regex.finditer(data):
                  # Take the offset of the start of the signature into account
                  offset = match.start() - signature.offset
  
                  # Signatures are ordered based on the length of their magic bytes (largest first).
                  # If this offset has already been matched to a previous signature, ignore it unless
                  # self.show_invalid has been specified. Also ignore obviously invalid offsets (<0)
                  # as well as those outside the specified self.data range (dlen).
                  if (offset not in matched_offsets or self.show_invalid) and offset >= 0 and offset < dlen:
                  # if offset >= 0 and offset < dlen:
                      # Analyze the data at this offset using the current
                      # signature rule
                      tags = self._analyze(signature, offset)
  
                      # Generate a SignatureResult object and append it to the results list if the
                      # signature is valid, or if invalid results were requested.
                      if (not tags['invalid'] or self.show_invalid) and not self._filtered(tags['description']):
                          # Only display results with the 'once' tag once.
                          if tags['once']:
                              if signature.title in self.display_once:
                                  continue
                              else:
                                  self.display_once.add(signature.title)
  
                          # Append the result to the results list
                          results.append(SignatureResult(**tags))
  
                          # Add this offset to the matched_offsets set, so that it can be ignored by
                          # subsequent loops.
                          matched_offsets.add(offset)
  
          # Sort results by offset
          results.sort(key=lambda x: x.offset, reverse=False)
  
          return results