/*!
    Constructs a file handler and registers it with Qt. Once created this
    handler's create() function will be called (along with all the other
    handlers) for any paths used. The most recently created handler that
    recognizes the given path (i.e. that returns a QAbstractFileEngine) is
    used for the new path.

    \sa create()
 */
QAbstractFileEngineHandler::QAbstractFileEngineHandler()
{
    QMutexLocker locker(fileEngineHandlerMutex());
    if (!fileEngineHandlers)
        fileEngineHandlers = new QList<QAbstractFileEngineHandler *>;
    fileEngineHandlers->prepend(this);
}
/*!
    Destroys the file handler. This will automatically unregister the handler
    from Qt.
 */
QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
{
    QWriteLocker locker(fileEngineHandlerMutex());
    // Remove this handler from the handler list only if the list is valid.
    if (!qt_abstractfileenginehandlerlist_shutDown)
        fileEngineHandlers()->removeAll(this);
}
/*!
    Destroys the file handler. This will automatically unregister the handler
    from Qt.
 */
QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
{
    QWriteLocker locker(fileEngineHandlerMutex());
    // Remove this handler from the handler list only if the list is valid.
    if (!qt_abstractfileenginehandlerlist_shutDown) {
        QAbstractFileEngineHandlerList *handlers = fileEngineHandlers();
        handlers->removeOne(this);
        if (handlers->isEmpty())
            qt_file_engine_handlers_in_use = false;
    }
}
/*!
    Creates and returns a QAbstractFileEngine suitable for processing \a
    fileName.

    You should not need to call this function; use QFile, QFileInfo or QDir
    directly instead.

    \sa QAbstractFileEngineHandler
*/
QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
{
    QMutexLocker locker(fileEngineHandlerMutex());
    if (!fileEngineHandlers)
        fileEngineHandlers = new QList<QAbstractFileEngineHandler *>;

    // check for registered handlers that can load the file
    for (int i = 0; i < fileEngineHandlers->size(); i++) {
        if (QAbstractFileEngine *ret = fileEngineHandlers->at(i)->create(fileName))
            return ret;
    }

    // fall back to regular file engine
    return new QFSFileEngine(fileName);
}
/*
   \internal

   Handles calls to custom file engine handlers.
*/
QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path)
{
    QAbstractFileEngine *engine = 0;

    if (qt_file_engine_handlers_in_use) {
        QReadLocker locker(fileEngineHandlerMutex());

        // check for registered handlers that can load the file
        QAbstractFileEngineHandlerList *handlers = fileEngineHandlers();
        for (int i = 0; i < handlers->size(); i++) {
            if ((engine = handlers->at(i)->create(path)))
                break;
        }
    }

    return engine;
}
/*!
    Creates and returns a QAbstractFileEngine suitable for processing \a
    fileName.

    You should not need to call this function; use QFile, QFileInfo or
    QDir directly instead.

    If you reimplemnt this function, it should only return file
    engines that knows how to handle \a fileName; otherwise, it should
    return 0.

    \sa QAbstractFileEngineHandler
*/
QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
{
    {
        QReadLocker locker(fileEngineHandlerMutex());

        // check for registered handlers that can load the file
        for (int i = 0; i < fileEngineHandlers()->size(); i++) {
            if (QAbstractFileEngine *ret = fileEngineHandlers()->at(i)->create(fileName))
                return ret;
        }
    }

#ifdef QT_BUILD_CORE_LIB
    if (!fileName.startsWith(QLatin1Char('/'))) {
        int prefixSeparator = fileName.indexOf(QLatin1Char(':'));
        if (prefixSeparator > 1) {
            QString prefix = fileName.left(prefixSeparator);
            QString fileNameWithoutPrefix = fileName.mid(prefixSeparator + 1).prepend(QLatin1Char('/'));
            const QStringList &paths = QDir::searchPaths(prefix);
            for (int i = 0; i < paths.count(); i++) {
                QString path = paths.at(i);
                path.append(fileNameWithoutPrefix);
                QAbstractFileEngine *engine = create(path);
                if (engine && (engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) {
                    return engine;
                }
                delete engine;
            }
        }
    }
#endif

#ifdef QT_NO_FSFILEENGINE
    return 0;
#else
    // fall back to regular file engine
    return new QFSFileEngine(fileName);
#endif
}
/*!
    Destroys the file handler. This will automatically unregister the handler
    from Qt.
 */
QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
{
    QMutexLocker locker(fileEngineHandlerMutex());
    fileEngineHandlers->removeAll(this);
}
/*!
    Constructs a file handler and registers it with Qt. Once created this
    handler's create() function will be called (along with all the other
    handlers) for any paths used. The most recently created handler that
    recognizes the given path (i.e. that returns a QAbstractFileEngine) is
    used for the new path.

    \sa create()
 */
QAbstractFileEngineHandler::QAbstractFileEngineHandler()
{
    QWriteLocker locker(fileEngineHandlerMutex());
    qt_file_engine_handlers_in_use = true;
    fileEngineHandlers()->prepend(this);
}
 ~QAbstractFileEngineHandlerList()
 {
     QWriteLocker locker(fileEngineHandlerMutex());
     qt_abstractfileenginehandlerlist_shutDown = true;
 }
/*!
    Constructs a file handler and registers it with Qt. Once created this
    handler's create() function will be called (along with all the other
    handlers) for any paths used. The most recently created handler that
    recognizes the given path (i.e. that returns a QAbstractFileEngine) is
    used for the new path.

    \sa create()
 */
QAbstractFileEngineHandler::QAbstractFileEngineHandler()
{
    QWriteLocker locker(fileEngineHandlerMutex());
    fileEngineHandlers()->prepend(this);
}