1/* 2 * Copyright 2006-2013, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <mime/MimeSnifferAddonManager.h> 8 9#include <new> 10 11#include <Autolock.h> 12#include <MimeType.h> 13 14#include <MimeSnifferAddon.h> 15 16 17namespace BPrivate { 18namespace Storage { 19namespace Mime { 20 21 22// singleton instance 23MimeSnifferAddonManager* MimeSnifferAddonManager::sManager = NULL; 24 25 26// AddonReference 27struct MimeSnifferAddonManager::AddonReference { 28 AddonReference(BMimeSnifferAddon* addon) 29 : fAddon(addon), 30 fReferenceCount(1) 31 { 32 } 33 34 ~AddonReference() 35 { 36 delete fAddon; 37 } 38 39 BMimeSnifferAddon* Addon() const 40 { 41 return fAddon; 42 } 43 44 void GetReference() 45 { 46 atomic_add(&fReferenceCount, 1); 47 } 48 49 void PutReference() 50 { 51 if (atomic_add(&fReferenceCount, -1) == 1) 52 delete this; 53 } 54 55private: 56 BMimeSnifferAddon* fAddon; 57 int32 fReferenceCount; 58}; 59 60 61// constructor 62MimeSnifferAddonManager::MimeSnifferAddonManager() 63 : fLock("mime sniffer manager"), 64 fAddons(20), 65 fMinimalBufferSize(0) 66{ 67} 68 69// destructor 70MimeSnifferAddonManager::~MimeSnifferAddonManager() 71{ 72} 73 74// Default 75MimeSnifferAddonManager* 76MimeSnifferAddonManager::Default() 77{ 78 return sManager; 79} 80 81// CreateDefault 82status_t 83MimeSnifferAddonManager::CreateDefault() 84{ 85 MimeSnifferAddonManager* manager 86 = new(std::nothrow) MimeSnifferAddonManager; 87 if (!manager) 88 return B_NO_MEMORY; 89 90 sManager = manager; 91 92 return B_OK; 93} 94 95// DeleteDefault 96void 97MimeSnifferAddonManager::DeleteDefault() 98{ 99 MimeSnifferAddonManager* manager = sManager; 100 sManager = NULL; 101 102 delete manager; 103} 104 105// AddMimeSnifferAddon 106status_t 107MimeSnifferAddonManager::AddMimeSnifferAddon(BMimeSnifferAddon* addon) 108{ 109 if (!addon) 110 return B_BAD_VALUE; 111 112 BAutolock locker(fLock); 113 if (!locker.IsLocked()) 114 return B_ERROR; 115 116 // create a reference for the addon 117 AddonReference* reference = new(std::nothrow) AddonReference(addon); 118 if (!reference) 119 return B_NO_MEMORY; 120 121 // add the reference 122 if (!fAddons.AddItem(reference)) { 123 delete reference; 124 return B_NO_MEMORY; 125 } 126 127 // update minimal buffer size 128 size_t minBufferSize = addon->MinimalBufferSize(); 129 if (minBufferSize > fMinimalBufferSize) 130 fMinimalBufferSize = minBufferSize; 131 132 return B_OK; 133} 134 135// MinimalBufferSize 136size_t 137MimeSnifferAddonManager::MinimalBufferSize() 138{ 139 return fMinimalBufferSize; 140} 141 142// GuessMimeType 143float 144MimeSnifferAddonManager::GuessMimeType(const char* fileName, BMimeType* type) 145{ 146 // get addons 147 AddonReference** addons = NULL; 148 int32 count = 0; 149 status_t error = _GetAddons(addons, count); 150 if (error != B_OK) 151 return -1; 152 153 // iterate over the addons and find the most fitting type 154 float bestPriority = -1; 155 for (int32 i = 0; i < count; i++) { 156 BMimeType currentType; 157 float priority = addons[i]->Addon()->GuessMimeType(fileName, 158 ¤tType); 159 if (priority > bestPriority) { 160 type->SetTo(currentType.Type()); 161 bestPriority = priority; 162 } 163 } 164 165 // release addons 166 _PutAddons(addons, count); 167 168 return bestPriority; 169} 170 171// GuessMimeType 172float 173MimeSnifferAddonManager::GuessMimeType(BFile* file, const void* buffer, 174 int32 length, BMimeType* type) 175{ 176 // get addons 177 AddonReference** addons = NULL; 178 int32 count = 0; 179 status_t error = _GetAddons(addons, count); 180 if (error != B_OK) 181 return -1; 182 183 // iterate over the addons and find the most fitting type 184 float bestPriority = -1; 185 for (int32 i = 0; i < count; i++) { 186 BMimeType currentType; 187 float priority = addons[i]->Addon()->GuessMimeType(file, buffer, 188 length, ¤tType); 189 if (priority > bestPriority) { 190 type->SetTo(currentType.Type()); 191 bestPriority = priority; 192 } 193 } 194 195 // release addons 196 _PutAddons(addons, count); 197 198 return bestPriority; 199} 200 201// _GetAddons 202status_t 203MimeSnifferAddonManager::_GetAddons(AddonReference**& references, int32& count) 204{ 205 BAutolock locker(fLock); 206 if (!locker.IsLocked()) 207 return B_ERROR; 208 209 count = fAddons.CountItems(); 210 references = new(std::nothrow) AddonReference*[count]; 211 if (!references) 212 return B_NO_MEMORY; 213 214 for (int32 i = 0; i < count; i++) { 215 references[i] = (AddonReference*)fAddons.ItemAt(i); 216 references[i]->GetReference(); 217 } 218 219 return B_OK; 220} 221 222// _PutAddons 223void 224MimeSnifferAddonManager::_PutAddons(AddonReference** references, int32 count) 225{ 226 for (int32 i = 0; i < count; i++) 227 references[i]->PutReference(); 228 229 delete[] references; 230} 231 232 233} // namespace Mime 234} // namespace Storage 235} // namespace BPrivate 236