1/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation, nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30#include <string> 31#include <algorithm> 32#include <iterator> 33#include <DataItemIndex.h> 34#include <platform_lib_log_util.h> 35#include <IDataItemObserver.h> 36#include <DataItemId.h> 37 38using namespace std; 39using namespace loc_core; 40 41template <typename CT, typename DIT> 42inline DataItemIndex <CT,DIT> :: DataItemIndex () {} 43 44template <typename CT, typename DIT> 45inline DataItemIndex <CT,DIT> :: ~DataItemIndex () {} 46 47template <typename CT, typename DIT> 48void DataItemIndex <CT,DIT> :: getListOfSubscribedClients 49 ( 50 DIT id, 51 list <CT> & out 52) 53{ 54 typename map < DIT, list <CT> > :: iterator cdiIter = 55 mClientsPerDataItemMap.find (id); 56 if (cdiIter != mClientsPerDataItemMap.end ()) { 57 out = cdiIter->second; 58 } 59} 60 61 62template <typename CT, typename DIT> 63int DataItemIndex <CT,DIT> :: remove (DIT id) { 64 int result = 0; 65 ENTRY_LOG (); 66 mClientsPerDataItemMap.erase (id); 67 EXIT_LOG_WITH_ERROR ("%d",result); 68 return result; 69} 70 71template <typename CT, typename DIT> 72void DataItemIndex <CT,DIT> :: remove (const list <CT> & r, list <DIT> & out) { 73 ENTRY_LOG (); 74 typename map < DIT, list <CT> > :: iterator cdiIter = 75 mClientsPerDataItemMap.begin (); 76 while (cdiIter != mClientsPerDataItemMap.end()) { 77 typename list <CT> :: const_iterator it = r.begin (); 78 for (; it != r.end (); ++it) { 79 typename list <CT> :: iterator iter = 80 find 81 ( 82 cdiIter->second.begin (), 83 cdiIter->second.end (), 84 *it 85 ); 86 if (iter != cdiIter->second.end ()) { 87 cdiIter->second.erase (iter); 88 } 89 } 90 91 if (cdiIter->second.empty ()) { 92 out.push_back (cdiIter->first); 93 // Post-increment operator increases the iterator but returns the 94 // prevous one that will be invalidated by erase() 95 mClientsPerDataItemMap.erase (cdiIter++); 96 } else { 97 ++cdiIter; 98 } 99 } 100 EXIT_LOG_WITH_ERROR ("%d",0); 101} 102 103template <typename CT, typename DIT> 104void DataItemIndex <CT,DIT> :: remove 105( 106 DIT id, 107 const list <CT> & r, 108 list <CT> & out 109) 110{ 111 ENTRY_LOG (); 112 113 typename map < DIT, list <CT> > :: iterator cdiIter = 114 mClientsPerDataItemMap.find (id); 115 if (cdiIter != mClientsPerDataItemMap.end ()) { 116 set_intersection (cdiIter->second.begin (), cdiIter->second.end (), 117 r.begin (), r.end (), 118 inserter (out, out.begin ())); 119 if (!out.empty ()) { 120 typename list <CT> :: iterator it = out.begin (); 121 for (; it != out.end (); ++it) { 122 cdiIter->second.erase (find (cdiIter->second.begin (), 123 cdiIter->second.end (), 124 *it)); 125 } 126 } 127 if (cdiIter->second.empty ()) { 128 mClientsPerDataItemMap.erase (cdiIter); 129 EXIT_LOG_WITH_ERROR ("%d",0); 130 } 131 } 132 EXIT_LOG_WITH_ERROR ("%d",0); 133} 134 135template <typename CT, typename DIT> 136void DataItemIndex <CT,DIT> :: add 137( 138 DIT id, 139 const list <CT> & l, 140 list <CT> & out 141) 142{ 143 ENTRY_LOG (); 144 list <CT> difference; 145 typename map < DIT, list <CT> > :: iterator cdiIter = 146 mClientsPerDataItemMap.find (id); 147 if (cdiIter != mClientsPerDataItemMap.end ()) { 148 set_difference (l.begin (), l.end (), 149 cdiIter->second.begin (), cdiIter->second.end (), 150 inserter (difference, difference.begin ())); 151 if (!difference.empty ()) { 152 difference.sort (); 153 out = difference; 154 cdiIter->second.merge (difference); 155 } 156 } else { 157 out = l; 158 pair < DIT, list <CT> > cndipair (id, out); 159 mClientsPerDataItemMap.insert (cndipair); 160 } 161 EXIT_LOG_WITH_ERROR ("%d",0); 162} 163 164template <typename CT, typename DIT> 165void DataItemIndex <CT,DIT> :: add 166( 167 CT client, 168 const list <DIT> & l, 169 list <DIT> & out 170) 171{ 172 ENTRY_LOG (); 173 typename map < DIT, list <CT> > :: iterator cdiIter; 174 typename list <DIT> :: const_iterator it = l.begin (); 175 for (; it != l.end (); ++it) { 176 cdiIter = mClientsPerDataItemMap.find (*it); 177 if (cdiIter == mClientsPerDataItemMap.end ()) { 178 out.push_back (*it); 179 pair < DIT, list <CT> > cndiPair (*it, list <CT> (1, client)); 180 mClientsPerDataItemMap.insert (cndiPair); 181 } else { 182 typename list<CT> :: iterator clientIter = 183 find 184 ( 185 cdiIter->second.begin (), 186 cdiIter->second.end (), 187 client 188 ); 189 if (clientIter == cdiIter->second.end()) { 190 cdiIter->second.push_back (client); 191 } 192 } 193 } 194 EXIT_LOG_WITH_ERROR ("%d",0); 195} 196 197// Explicit instantiation must occur in same namespace where class is defined 198namespace loc_core 199{ 200 template class DataItemIndex <IDataItemObserver *, DataItemId>; 201 template class DataItemIndex <string, DataItemId>; 202} 203