<commit_before>/**
 * @file osx/drivenotifyosx.cpp
 * @brief Mega SDK various utilities and helper classes
 *
 * (c) 2013-2021 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#ifdef USE_DRIVE_NOTIFICATIONS

#include "mega/drivenotify.h"

#include <sys/param.h>

namespace mega {

// CFArrayRef objects need to be constructed from const C-style array.
// We watch for changes in the Volume Path Key.
static const CFStringRef watchArray[1] = {kDADiskDescriptionVolumePathKey};

// Convenience function since CoreFoundation/DiskArbitration traffic liberally in void* pointers
template<class T>
void* asVoidPtr(T* t) noexcept { return reinterpret_cast<void*>(t); }

// Copied from Disk Arbitration Framework documentation. In the `else` below they write:
// "// something is *really* wrong"
// so we throw an exception.
static std::string toString(CFURLRef fspath)
{
    char buf[MAXPATHLEN];
    if (CFURLGetFileSystemRepresentation(fspath, false, reinterpret_cast<UInt8*>(buf), sizeof(buf))) {
        return buf;
    }

    throw std::runtime_error("Unable to resolve path from filesystem URL");
}


// See note here regarding callback registration/unregistration:
// https://developer.apple.com/library/archive/documentation/DriversKernelHardware/Conceptual/DiskArbitrationProgGuide/ArbitrationBasics/ArbitrationBasics.html#//apple_ref/doc/uid/TP40009310-CH2-SW9
// MediaTypeCallbacks is an abstract base class which uses the Non-Virtual Interface Pattern
// to implement callbacks, which are static member functions, where the `void* context` is a pointer
// to a concrete derived class. Per the note above, we are registering the same callback (i.e., pointer to static method)
// with a different context (i.e., pointer to derived class cast to void*)

void MediaTypeCallbacks::registerCallbacks(DASessionRef session)
{
    DARegisterDiskAppearedCallback(
        session,
        matchingDict(),
        &MediaTypeCallbacks::onDiskAppeared,
        asVoidPtr(this));

    DARegisterDiskDisappearedCallback(
        session,
        matchingDict(),
        &MediaTypeCallbacks::onDiskDisappeared,
        asVoidPtr(this));

    registerAdditionalCallbacks(session);
}

void MediaTypeCallbacks::unregisterCallbacks(DASessionRef session)
{
    DAUnregisterCallback(session, asVoidPtr(&MediaTypeCallbacks::onDiskAppeared), asVoidPtr(this));
    DAUnregisterCallback(session, asVoidPtr(&MediaTypeCallbacks::onDiskDisappeared), asVoidPtr(this));

    DAUnregisterCallback(session, asVoidPtr(&MediaTypeCallbacks::onDiskDescriptionChanged), asVoidPtr(this));

    DAUnregisterApprovalCallback(session, asVoidPtr(&MediaTypeCallbacks::onUnmountApproval), asVoidPtr(this));
}

void MediaTypeCallbacks::addDrive(CFURLRef path, bool connected)
{
    DriveInfo di;
    di.mountPoint = toString(path);
    di.connected = connected;
    mParent->add(std::move(di));
}

void MediaTypeCallbacks::onDiskAppeared(DADiskRef disk, void* context)
{
    MediaTypeCallbacks& self = castSelf(context);

    UniqueCFRef<CFDictionaryRef> diskDescription = description(disk);

    if (!self.shouldNotify(diskDescription)) return;

    CFURLRef path = volumePath(diskDescription);

    if (path)
        self.addDrive(path, true);
    else
        self.handleNoPathAppeared(diskDescription);
}

void MediaTypeCallbacks::onDiskDisappeared(DADiskRef disk, void* context)
{
    MediaTypeCallbacks& self = castSelf(context);

    UniqueCFRef<CFDictionaryRef> diskDescription = description(disk);

    if (!self.shouldNotify(diskDescription)) return;
<commit_msg>if statement braces<commit_after>/**
 * @file osx/drivenotifyosx.cpp
 * @brief Mega SDK various utilities and helper classes
 *
 * (c) 2013-2021 by Mega Limited, Auckland, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#ifdef USE_DRIVE_NOTIFICATIONS

#include "mega/drivenotify.h"

#include <sys/param.h>

namespace mega {

// CFArrayRef objects need to be constructed from const C-style array.
// We watch for changes in the Volume Path Key.
static const CFStringRef watchArray[1] = {kDADiskDescriptionVolumePathKey};

// Convenience function since CoreFoundation/DiskArbitration traffic liberally in void* pointers
template<class T>
void* asVoidPtr(T* t) noexcept { return reinterpret_cast<void*>(t); }

// Copied from Disk Arbitration Framework documentation. In the `else` below they write:
// "// something is *really* wrong"
// so we throw an exception.
static std::string toString(CFURLRef fspath)
{
    char buf[MAXPATHLEN];
    if (CFURLGetFileSystemRepresentation(fspath, false, reinterpret_cast<UInt8*>(buf), sizeof(buf))) 
    {
        return buf;
    }

    throw std::runtime_error("Unable to resolve path from filesystem URL");
}


// See note here regarding callback registration/unregistration:
// https://developer.apple.com/library/archive/documentation/DriversKernelHardware/Conceptual/DiskArbitrationProgGuide/ArbitrationBasics/ArbitrationBasics.html#//apple_ref/doc/uid/TP40009310-CH2-SW9
// MediaTypeCallbacks is an abstract base class which uses the Non-Virtual Interface Pattern
// to implement callbacks, which are static member functions, where the `void* context` is a pointer
// to a concrete derived class. Per the note above, we are registering the same callback (i.e., pointer to static method)
// with a different context (i.e., pointer to derived class cast to void*)

void MediaTypeCallbacks::registerCallbacks(DASessionRef session)
{
    DARegisterDiskAppearedCallback(
        session,
        matchingDict(),
        &MediaTypeCallbacks::onDiskAppeared,
        asVoidPtr(this));

    DARegisterDiskDisappearedCallback(
        session,
        matchingDict(),
        &MediaTypeCallbacks::onDiskDisappeared,
        asVoidPtr(this));

    registerAdditionalCallbacks(session);
}

void MediaTypeCallbacks::unregisterCallbacks(DASessionRef session)
{
    DAUnregisterCallback(session, asVoidPtr(&MediaTypeCallbacks::onDiskAppeared), asVoidPtr(this));
    DAUnregisterCallback(session, asVoidPtr(&MediaTypeCallbacks::onDiskDisappeared), asVoidPtr(this));

    DAUnregisterCallback(session, asVoidPtr(&MediaTypeCallbacks::onDiskDescriptionChanged), asVoidPtr(this));

    DAUnregisterApprovalCallback(session, asVoidPtr(&MediaTypeCallbacks::onUnmountApproval), asVoidPtr(this));
}

void MediaTypeCallbacks::addDrive(CFURLRef path, bool connected)
{
    DriveInfo di;
    di.mountPoint = toString(path);
    di.connected = connected;
    mParent->add(std::move(di));
}

void MediaTypeCallbacks::onDiskAppeared(DADiskRef disk, void* context)
{
    MediaTypeCallbacks& self = castSelf(context);

    UniqueCFRef<CFDictionaryRef> diskDescription = description(disk);

    if (!self.shouldNotify(diskDescription)) return;

    CFURLRef path = volumePath(diskDescription);

    if (path) 
    {
        self.addDrive(path, true);
    }
    else
    {
        self.handleNoPathAppeared(diskDescription);
    }
}

void MediaTypeCallbacks::onDiskDisappeared(DADiskRef disk, void* context)
{
    MediaTypeCallbacks& self = castSelf(context);

    UniqueCFRef<CFDictionaryRef> diskDescription = description(disk);

    if (!self.shouldNotify(diskDescription)) return;

{'fraction_non_alphanumeric': 0.09246995339710572, 'fraction_numerical': 0.0051508462104488595, 'mean_word_length': 4.675017397355602, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 2, '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': '894174', 'n_tokens_mistral': 2394, 'n_tokens_neox': 2317, 'n_words': 676}