LCOV - code coverage report
Current view: top level - storage - FileSystemModule.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 104 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "FileSystemModule.h"
       8             : 
       9             : #include "sqlite3.h"
      10             : #include "nsString.h"
      11             : #include "nsISimpleEnumerator.h"
      12             : #include "nsIFile.h"
      13             : 
      14             : namespace {
      15             : 
      16             : struct VirtualTableCursorBase
      17             : {
      18           0 :   VirtualTableCursorBase()
      19           0 :   {
      20           0 :     memset(&mBase, 0, sizeof(mBase));
      21           0 :   }
      22             : 
      23             :   sqlite3_vtab_cursor mBase;
      24             : };
      25             : 
      26           0 : struct VirtualTableCursor : public VirtualTableCursorBase
      27             : {
      28             : public:
      29           0 :   VirtualTableCursor()
      30           0 :   : mRowId(-1)
      31             :   {
      32           0 :     mCurrentFileName.SetIsVoid(true);
      33           0 :   }
      34             : 
      35           0 :   const nsString& DirectoryPath() const
      36             :   {
      37           0 :     return mDirectoryPath;
      38             :   }
      39             : 
      40           0 :   const nsString& CurrentFileName() const
      41             :   {
      42           0 :     return mCurrentFileName;
      43             :   }
      44             : 
      45           0 :   int64_t RowId() const
      46             :   {
      47           0 :     return mRowId;
      48             :   }
      49             : 
      50             :   nsresult Init(const nsAString& aPath);
      51             :   nsresult NextFile();
      52             : 
      53             : private:
      54             :   nsCOMPtr<nsISimpleEnumerator> mEntries;
      55             : 
      56             :   nsString mDirectoryPath;
      57             :   nsString mCurrentFileName;
      58             : 
      59             :   int64_t mRowId;
      60             : };
      61             : 
      62             : nsresult
      63           0 : VirtualTableCursor::Init(const nsAString& aPath)
      64             : {
      65             :   nsCOMPtr<nsIFile> directory =
      66           0 :     do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
      67           0 :   NS_ENSURE_TRUE(directory, NS_ERROR_FAILURE);
      68             : 
      69           0 :   nsresult rv = directory->InitWithPath(aPath);
      70           0 :   NS_ENSURE_SUCCESS(rv, rv);
      71             : 
      72           0 :   rv = directory->GetPath(mDirectoryPath);
      73           0 :   NS_ENSURE_SUCCESS(rv, rv);
      74             : 
      75           0 :   rv = directory->GetDirectoryEntries(getter_AddRefs(mEntries));
      76           0 :   NS_ENSURE_SUCCESS(rv, rv);
      77             : 
      78           0 :   rv = NextFile();
      79           0 :   NS_ENSURE_SUCCESS(rv, rv);
      80             : 
      81           0 :   return NS_OK;
      82             : }
      83             : 
      84             : nsresult
      85           0 : VirtualTableCursor::NextFile()
      86             : {
      87             :   bool hasMore;
      88           0 :   nsresult rv = mEntries->HasMoreElements(&hasMore);
      89           0 :   NS_ENSURE_SUCCESS(rv, rv);
      90             : 
      91           0 :   if (!hasMore) {
      92           0 :     mCurrentFileName.SetIsVoid(true);
      93           0 :     return NS_OK;
      94             :   }
      95             : 
      96           0 :   nsCOMPtr<nsISupports> entry;
      97           0 :   rv = mEntries->GetNext(getter_AddRefs(entry));
      98           0 :   NS_ENSURE_SUCCESS(rv, rv);
      99             : 
     100           0 :   nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
     101           0 :   NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
     102             : 
     103           0 :   rv = file->GetLeafName(mCurrentFileName);
     104           0 :   NS_ENSURE_SUCCESS(rv, rv);
     105             : 
     106           0 :   mRowId++;
     107             : 
     108           0 :   return NS_OK;
     109             : }
     110             : 
     111           0 : int Connect(sqlite3* aDB, void* aAux, int aArgc, const char* const* aArgv,
     112             :             sqlite3_vtab** aVtab, char** aErr)
     113             : {
     114             :   static const char virtualTableSchema[] =
     115             :     "CREATE TABLE fs ("
     116             :       "name TEXT, "
     117             :       "path TEXT"
     118             :     ")";
     119             : 
     120           0 :   int rc = sqlite3_declare_vtab(aDB, virtualTableSchema);
     121           0 :   if (rc != SQLITE_OK) {
     122           0 :     return rc;
     123             :   }
     124             : 
     125           0 :   sqlite3_vtab* vt = new sqlite3_vtab();
     126           0 :   memset(vt, 0, sizeof(*vt));
     127             : 
     128           0 :   *aVtab = vt;
     129             : 
     130           0 :   return SQLITE_OK;
     131             : }
     132             : 
     133           0 : int Disconnect(sqlite3_vtab* aVtab )
     134             : {
     135             :   delete aVtab;
     136             : 
     137           0 :   return SQLITE_OK;
     138             : }
     139             : 
     140           0 : int BestIndex(sqlite3_vtab* aVtab, sqlite3_index_info* aInfo)
     141             : {
     142             :   // Here we specify what index constraints we want to handle. That is, there
     143             :   // might be some columns with particular constraints in which we can help
     144             :   // SQLite narrow down the result set.
     145             :   //
     146             :   // For example, take the "path = x" where x is a directory. In this case,
     147             :   // we can narrow our search to just this directory instead of the entire file
     148             :   // system. This can be a significant optimization. So, we want to handle that
     149             :   // constraint. To do so, we would look for two specific input conditions:
     150             :   //
     151             :   // 1. aInfo->aConstraint[i].iColumn == 1
     152             :   // 2. aInfo->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_EQ
     153             :   //
     154             :   // The first states that the path column is being used in one of the input
     155             :   // constraints and the second states that the constraint involves the equal
     156             :   // operator.
     157             :   //
     158             :   // An even more specific search would be for name='xxx', in which case we
     159             :   // can limit the search to a single file, if it exists.
     160             :   //
     161             :   // What we have to do here is look for all of our index searches and select
     162             :   // the narrowest. We can only pick one, so obviously we want the one that
     163             :   // is the most specific, which leads to the smallest result set.
     164             : 
     165           0 :   for(int i = 0; i < aInfo->nConstraint; i++) {
     166           0 :     if (aInfo->aConstraint[i].iColumn == 1 && aInfo->aConstraint[i].usable) {
     167           0 :       if (aInfo->aConstraint[i].op & SQLITE_INDEX_CONSTRAINT_EQ) {
     168           0 :         aInfo->aConstraintUsage[i].argvIndex = 1;
     169             :       }
     170           0 :       break;
     171             :     }
     172             : 
     173             :     // TODO: handle single files (constrained also by the name column)
     174             :   }
     175             : 
     176           0 :   return SQLITE_OK;
     177             : }
     178             : 
     179           0 : int Open(sqlite3_vtab* aVtab, sqlite3_vtab_cursor** aCursor)
     180             : {
     181           0 :   VirtualTableCursor* cursor = new VirtualTableCursor();
     182             : 
     183           0 :   *aCursor = reinterpret_cast<sqlite3_vtab_cursor*>(cursor);
     184             : 
     185           0 :   return SQLITE_OK;
     186             : }
     187             : 
     188           0 : int Close(sqlite3_vtab_cursor* aCursor)
     189             : {
     190           0 :   VirtualTableCursor* cursor = reinterpret_cast<VirtualTableCursor*>(aCursor);
     191             : 
     192           0 :   delete cursor;
     193             : 
     194           0 :   return SQLITE_OK;
     195             : }
     196             : 
     197           0 : int Filter(sqlite3_vtab_cursor* aCursor, int aIdxNum, const char* aIdxStr,
     198             :            int aArgc, sqlite3_value** aArgv)
     199             : {
     200           0 :   VirtualTableCursor* cursor = reinterpret_cast<VirtualTableCursor*>(aCursor);
     201             : 
     202           0 :   if(aArgc <= 0) {
     203           0 :     return SQLITE_OK;
     204             :   }
     205             : 
     206             :   nsDependentString path(
     207           0 :     reinterpret_cast<const char16_t*>(::sqlite3_value_text16(aArgv[0])));
     208             : 
     209           0 :   nsresult rv = cursor->Init(path);
     210           0 :   NS_ENSURE_SUCCESS(rv, SQLITE_ERROR);
     211             : 
     212           0 :   return SQLITE_OK;
     213             : }
     214             : 
     215           0 : int Next(sqlite3_vtab_cursor* aCursor)
     216             : {
     217           0 :   VirtualTableCursor* cursor = reinterpret_cast<VirtualTableCursor*>(aCursor);
     218             : 
     219           0 :   nsresult rv = cursor->NextFile();
     220           0 :   NS_ENSURE_SUCCESS(rv, SQLITE_ERROR);
     221             : 
     222           0 :   return SQLITE_OK;
     223             : }
     224             : 
     225           0 : int Eof(sqlite3_vtab_cursor* aCursor)
     226             : {
     227           0 :   VirtualTableCursor* cursor = reinterpret_cast<VirtualTableCursor*>(aCursor);
     228           0 :   return cursor->CurrentFileName().IsVoid() ? 1 : 0;
     229             : }
     230             : 
     231           0 : int Column(sqlite3_vtab_cursor* aCursor, sqlite3_context* aContext,
     232             :            int aColumnIndex)
     233             : {
     234           0 :   VirtualTableCursor* cursor = reinterpret_cast<VirtualTableCursor*>(aCursor);
     235             : 
     236           0 :   switch (aColumnIndex) {
     237             :     // name
     238             :     case 0: {
     239           0 :       const nsString& name = cursor->CurrentFileName();
     240           0 :       sqlite3_result_text16(aContext, name.get(),
     241           0 :                             name.Length() * sizeof(char16_t),
     242           0 :                             SQLITE_TRANSIENT);
     243           0 :       break;
     244             :     }
     245             : 
     246             :     // path
     247             :     case 1: {
     248           0 :       const nsString& path = cursor->DirectoryPath();
     249           0 :       sqlite3_result_text16(aContext, path.get(),
     250           0 :                             path.Length() * sizeof(char16_t),
     251           0 :                             SQLITE_TRANSIENT);
     252           0 :       break;
     253             :     }
     254             :     default:
     255           0 :       NS_NOTREACHED("Unsupported column!");
     256             :   }
     257             : 
     258           0 :   return SQLITE_OK;
     259             : }
     260             : 
     261           0 : int RowId(sqlite3_vtab_cursor* aCursor, sqlite3_int64* aRowid)
     262             : {
     263           0 :   VirtualTableCursor* cursor = reinterpret_cast<VirtualTableCursor*>(aCursor);
     264             : 
     265           0 :   *aRowid = cursor->RowId();
     266             : 
     267           0 :   return SQLITE_OK;
     268             : }
     269             : 
     270             : } // namespace
     271             : 
     272             : namespace mozilla {
     273             : namespace storage {
     274             : 
     275           0 : int RegisterFileSystemModule(sqlite3* aDB, const char* aName)
     276             : {
     277             :   static sqlite3_module module = {
     278             :     1,
     279             :     Connect,
     280             :     Connect,
     281             :     BestIndex,
     282             :     Disconnect,
     283             :     Disconnect,
     284             :     Open,
     285             :     Close,
     286             :     Filter,
     287             :     Next,
     288             :     Eof,
     289             :     Column,
     290             :     RowId,
     291             :     nullptr,
     292             :     nullptr,
     293             :     nullptr,
     294             :     nullptr,
     295             :     nullptr,
     296             :     nullptr,
     297             :     nullptr
     298             :   };
     299             : 
     300           0 :   return sqlite3_create_module(aDB, aName, &module, nullptr);
     301             : }
     302             : 
     303             : } // namespace storage
     304             : } // namespace mozilla

Generated by: LCOV version 1.13