1 /* This file is part of the Pangolin Project. 2 * http://github.com/stevenlovegrove/Pangolin 3 * 4 * Copyright (c) 2011-2013 Steven Lovegrove 5 * 6 * Permission is hereby granted, free of charge, to any person 7 * obtaining a copy of this software and associated documentation 8 * files (the "Software"), to deal in the Software without 9 * restriction, including without limitation the rights to use, 10 * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following 13 * conditions: 14 * 15 * The above copyright notice and this permission notice shall be 16 * included in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 */ 27 28 #pragma once 29 30 #include <memory> 31 #include <vector> 32 #include <algorithm> 33 34 #include <pangolin/utils/uri.h> 35 36 namespace pangolin 37 { 38 39 template<typename T> 40 struct FactoryInterface 41 { 42 typedef T FactoryItem; 43 44 virtual ~FactoryInterface() = default; 45 virtual std::unique_ptr<T> Open(const Uri& uri) = 0; 46 }; 47 48 template<typename T> 49 class FactoryRegistry 50 { 51 public: 52 // IMPORTANT: Implement for each templated instantiation within a seperate compilation unit. 53 static FactoryRegistry<T>& I(); 54 ~FactoryRegistry()55 ~FactoryRegistry() 56 { 57 } 58 RegisterFactory(std::shared_ptr<FactoryInterface<T>> factory,uint32_t precedence,const std::string & scheme_name)59 void RegisterFactory(std::shared_ptr<FactoryInterface<T>> factory, uint32_t precedence, const std::string& scheme_name ) 60 { 61 FactoryItem item = {precedence, scheme_name, factory}; 62 factories.push_back( item ); 63 std::sort(factories.begin(), factories.end()); 64 } 65 UnregisterFactory(FactoryInterface<T> * factory)66 void UnregisterFactory(FactoryInterface<T>* factory) 67 { 68 for( auto i = factories.end()-1; i != factories.begin(); --i) 69 { 70 if( i->factory.get() == factory ) { 71 factories.erase(i); 72 } 73 } 74 } 75 UnregisterAllFactories()76 void UnregisterAllFactories() 77 { 78 factories.clear(); 79 } 80 Open(const Uri & uri)81 std::unique_ptr<T> Open(const Uri& uri) 82 { 83 // Iterate over all registered factories in order of precedence. 84 for(auto& item : factories) { 85 if( item.scheme == uri.scheme) { 86 std::unique_ptr<T> video = item.factory->Open(uri); 87 if(video) { 88 return video; 89 } 90 } 91 } 92 93 return std::unique_ptr<T>(); 94 } 95 96 private: 97 struct FactoryItem 98 { 99 uint32_t precedence; 100 std::string scheme; 101 std::shared_ptr<FactoryInterface<T>> factory; 102 103 bool operator<(const FactoryItem& rhs) const { 104 return precedence < rhs.precedence; 105 } 106 }; 107 108 // Priority, Factory tuple 109 std::vector<FactoryItem> factories; 110 }; 111 112 #define PANGOLIN_REGISTER_FACTORY(x) void Register ## x ## Factory() 113 114 } 115