<commit_before>
import Foundation

public class NotificationListener : Listener {

  public let name: Notification.Name

  var _observer: NSObjectProtocol!

  override func _startListening() {

    _observer = NotificationCenter.default.addObserver(forName: self.name, object: nil, queue: nil, using: {
      [unowned self] (notif: Notification) in

      // `getHash(notif.object as AnyObject)` returns
      // '0' when `notif.object` equals nil. Listen to all 
      // objects emitting `name` when listening on nil, mirroring
      // functionality in NSNotificationCenter.
      if self._targetID != "0" {
        if let target: AnyObject = notif.object as AnyObject? {
          if self._targetID != getHash(target) {
            return
          }
        } 
      }

      self._trigger(notif.userInfo)
    })

    // Add self to global cache.
    var targets = NotificationListenerCache[name] ?? [:]
    var listeners = targets[_targetID] ?? [:]
    listeners[getHash(self)] = once ? StrongPointer(self) : WeakPointer(self)
    targets[_targetID] = listeners
    NotificationListenerCache[name] = targets
  }

  override func _stopListening() {

    NotificationCenter.default.removeObserver(_observer)

    // Remove self from global cache.
    var targets = NotificationListenerCache[self.name]!
    var listeners = targets[_targetID]!
    listeners[getHash(self)] = nil
    targets[_targetID] = listeners.nilIfEmpty
    NotificationListenerCache[self.name] = targets.nilIfEmpty
  }

  init (_ name: Notification.Name, _ target: AnyObject!, _ once: Bool, _ handler: @escaping (NSDictionary) -> Void) {
    self.name = name
    super.init(target, once) {
      handler(($0 as? NSDictionary) ?? [:])
    }
  }
}

// 1 - Listener.name
// 2 - getHash(Listener.target)
// 3 - getHash(Listener)
// 4 - DynamicPointer<Listener>
var NotificationListenerCache = [AnyHashable: [String: [String: DynamicPointer<Listener>]] ]()
<commit_msg>Avoid triggering a targeted NotificationListener when notif.object == nil<commit_after>
import Foundation

public class NotificationListener : Listener {

  public let name: Notification.Name

  var _observer: NSObjectProtocol!

  override func _startListening() {

    _observer = NotificationCenter.default.addObserver(forName: self.name, object: nil, queue: nil, using: {
      [unowned self] (notif: Notification) in

      // `getHash(notif.object as AnyObject)` returns
      // '0' when `notif.object` equals nil. Listen to all 
      // objects emitting `name` when listening on nil, mirroring
      // functionality in NSNotificationCenter.
      if self._targetID != "0" {
        if let target: AnyObject = notif.object as AnyObject? {
          if self._targetID != getHash(target) {
            return
          }
       } else {
         return
       }
     }

      self._trigger(notif.userInfo)
    })

    // Add self to global cache.
    var targets = NotificationListenerCache[name] ?? [:]
    var listeners = targets[_targetID] ?? [:]
    listeners[getHash(self)] = once ? StrongPointer(self) : WeakPointer(self)
    targets[_targetID] = listeners
    NotificationListenerCache[name] = targets
  }

  override func _stopListening() {

    NotificationCenter.default.removeObserver(_observer)

    // Remove self from global cache.
    var targets = NotificationListenerCache[self.name]!
    var listeners = targets[_targetID]!
    listeners[getHash(self)] = nil
    targets[_targetID] = listeners.nilIfEmpty
    NotificationListenerCache[self.name] = targets.nilIfEmpty
  }

  init (_ name: Notification.Name, _ target: AnyObject!, _ once: Bool, _ handler: @escaping (NSDictionary) -> Void) {
    self.name = name
    super.init(target, once) {
      handler(($0 as? NSDictionary) ?? [:])
    }
  }
}

// 1 - Listener.name
// 2 - getHash(Listener.target)
// 3 - getHash(Listener)
// 4 - DynamicPointer<Listener>
var NotificationListenerCache = [AnyHashable: [String: [String: DynamicPointer<Listener>]] ]()

{'fraction_non_alphanumeric': 0.11318376607007814, 'fraction_numerical': 0.0035291152004033274, 'mean_word_length': 3.198941798941799, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2989362', 'n_tokens_mistral': 1203, 'n_tokens_neox': 1123, 'n_words': 289}