blob: d2eed7078bcc9ed8de4c1d966d8aa6265c9ce5a8 [file] [log] [blame]
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07002/**
3 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -08005 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -08008 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07009 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080013 */
14
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080015#include "common.hpp"
16
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080017#include "exclude.hpp"
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080018
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -070019namespace ndn {
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080020
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070021Exclude::Exclude()
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080022{
23}
24
25// example: ANY /b /d ANY /f
26//
27// ordered in map as:
28//
29// /f (false); /d (true); /b (false); / (true)
30//
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070031// lower_bound(/) -> / (true) <-- excluded (equal)
32// lower_bound(/a) -> / (true) <-- excluded (any)
33// lower_bound(/b) -> /b (false) <--- excluded (equal)
34// lower_bound(/c) -> /b (false) <--- not excluded (not equal and no ANY)
35// lower_bound(/d) -> /d (true) <- excluded
36// lower_bound(/e) -> /d (true) <- excluded
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080037bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070038Exclude::isExcluded(const name::Component& comp) const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080039{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070040 const_iterator lowerBound = m_exclude.lower_bound(comp);
41 if (lowerBound == end())
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080042 return false;
43
44 if (lowerBound->second)
45 return true;
46 else
47 return lowerBound->first == comp;
48
49 return false;
50}
51
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070052Exclude&
53Exclude::excludeOne(const name::Component& comp)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080054{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070055 if (!isExcluded(comp))
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080056 {
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070057 m_exclude.insert(std::make_pair(comp, false));
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080058 }
59 return *this;
60}
61
62
63// example: ANY /b0 /d0 ANY /f0
64//
65// ordered in map as:
66//
67// /f0 (false); /d0 (true); /b0 (false); / (true)
68//
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070069// lower_bound(/) -> / (true) <-- excluded (equal)
70// lower_bound(/a0) -> / (true) <-- excluded (any)
71// lower_bound(/b0) -> /b0 (false) <--- excluded (equal)
72// lower_bound(/c0) -> /b0 (false) <--- not excluded (not equal and no ANY)
73// lower_bound(/d0) -> /d0 (true) <- excluded
74// lower_bound(/e0) -> /d0 (true) <- excluded
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080075
76
77// examples with desired outcomes
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070078// excludeRange(/, /f0) -> ANY /f0
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080079// /f0 (false); / (true)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070080// excludeRange(/, /f1) -> ANY /f1
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080081// /f1 (false); / (true)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070082// excludeRange(/a0, /e0) -> ANY /f0
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080083// /f0 (false); / (true)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070084// excludeRange(/a0, /e0) -> ANY /f0
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080085// /f0 (false); / (true)
86
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070087// excludeRange(/b1, /c0) -> ANY /b0 /b1 ANY /c0 /d0 ANY /f0
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080088// /f0 (false); /d0 (true); /c0 (false); /b1 (true); /b0 (false); / (true)
89
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070090Exclude&
91Exclude::excludeRange(const name::Component& from, const name::Component& to)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080092{
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -070093 if (from >= to) {
Alexander Afanasyev9c578182014-05-14 17:28:28 -070094 throw Error("Invalid exclude range [" + from.toUri() + ", " + to.toUri() + "] "
95 "(for single name exclude use Exclude::excludeOne)");
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -070096 }
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080097
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070098 iterator newFrom = m_exclude.lower_bound(from);
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -070099 if (newFrom == end() || !newFrom->second /*without ANY*/) {
100 std::pair<iterator, bool> fromResult = m_exclude.insert(std::make_pair(from, true));
101 newFrom = fromResult.first;
102 if (!fromResult.second) {
103 // this means that the lower bound is equal to the item itself. So, just update ANY flag
104 newFrom->second = true;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800105 }
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700106 }
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800107 // else
108 // nothing special if start of the range already exists with ANY flag set
109
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700110 iterator newTo = m_exclude.lower_bound(to); // !newTo cannot be end()
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700111 if (newTo == newFrom || !newTo->second) {
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700112 std::pair<iterator, bool> toResult = m_exclude.insert(std::make_pair(to, false));
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800113 newTo = toResult.first;
114 ++ newTo;
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700115 }
116 // else
117 // nothing to do really
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800118
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700119 m_exclude.erase(newTo, newFrom); // remove any intermediate node, since all of the are excluded
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800120
121 return *this;
122}
123
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700124Exclude&
125Exclude::excludeAfter(const name::Component& from)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800126{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700127 iterator newFrom = m_exclude.lower_bound(from);
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700128 if (newFrom == end() || !newFrom->second /*without ANY*/) {
129 std::pair<iterator, bool> fromResult = m_exclude.insert(std::make_pair(from, true));
130 newFrom = fromResult.first;
131 if (!fromResult.second) {
132 // this means that the lower bound is equal to the item itself. So, just update ANY flag
133 newFrom->second = true;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800134 }
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700135 }
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800136 // else
137 // nothing special if start of the range already exists with ANY flag set
138
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700139 if (newFrom != m_exclude.begin()) {
140 // remove any intermediate node, since all of the are excluded
141 m_exclude.erase(m_exclude.begin(), newFrom);
142 }
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800143
144 return *this;
145}
146
147
148std::ostream&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700149operator<<(std::ostream& os, const Exclude& exclude)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800150{
151 bool empty = true;
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700152 for (Exclude::const_reverse_iterator i = exclude.rbegin(); i != exclude.rend(); i++) {
153 if (!i->first.empty()) {
154 if (!empty) os << ",";
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700155 os << i->first.toUri();
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700156 empty = false;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800157 }
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700158 if (i->second) {
159 if (!empty) os << ",";
160 os << "*";
161 empty = false;
162 }
163 }
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800164 return os;
165}
166
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800167
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700168} // namespace ndn