blob: 69d08097a8fb3981501cd40e478b5c305035a3d2 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -08004 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07005 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -08006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080022 */
23
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080024#include "common.hpp"
25
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080026#include "exclude.hpp"
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080027
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -070028namespace ndn {
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080029
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070030Exclude::Exclude()
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080031{
32}
33
34// example: ANY /b /d ANY /f
35//
36// ordered in map as:
37//
38// /f (false); /d (true); /b (false); / (true)
39//
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070040// lower_bound(/) -> / (true) <-- excluded (equal)
41// lower_bound(/a) -> / (true) <-- excluded (any)
42// lower_bound(/b) -> /b (false) <--- excluded (equal)
43// lower_bound(/c) -> /b (false) <--- not excluded (not equal and no ANY)
44// lower_bound(/d) -> /d (true) <- excluded
45// lower_bound(/e) -> /d (true) <- excluded
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080046bool
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070047Exclude::isExcluded(const name::Component& comp) const
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080048{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070049 const_iterator lowerBound = m_exclude.lower_bound(comp);
50 if (lowerBound == end())
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080051 return false;
52
53 if (lowerBound->second)
54 return true;
55 else
56 return lowerBound->first == comp;
57
58 return false;
59}
60
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070061Exclude&
62Exclude::excludeOne(const name::Component& comp)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080063{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070064 if (!isExcluded(comp))
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080065 {
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070066 m_exclude.insert(std::make_pair(comp, false));
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080067 }
68 return *this;
69}
70
71
72// example: ANY /b0 /d0 ANY /f0
73//
74// ordered in map as:
75//
76// /f0 (false); /d0 (true); /b0 (false); / (true)
77//
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070078// lower_bound(/) -> / (true) <-- excluded (equal)
79// lower_bound(/a0) -> / (true) <-- excluded (any)
80// lower_bound(/b0) -> /b0 (false) <--- excluded (equal)
81// lower_bound(/c0) -> /b0 (false) <--- not excluded (not equal and no ANY)
82// lower_bound(/d0) -> /d0 (true) <- excluded
83// lower_bound(/e0) -> /d0 (true) <- excluded
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080084
85
86// examples with desired outcomes
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070087// excludeRange(/, /f0) -> ANY /f0
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080088// /f0 (false); / (true)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070089// excludeRange(/, /f1) -> ANY /f1
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080090// /f1 (false); / (true)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070091// excludeRange(/a0, /e0) -> ANY /f0
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080092// /f0 (false); / (true)
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070093// excludeRange(/a0, /e0) -> ANY /f0
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080094// /f0 (false); / (true)
95
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070096// excludeRange(/b1, /c0) -> ANY /b0 /b1 ANY /c0 /d0 ANY /f0
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -080097// /f0 (false); /d0 (true); /c0 (false); /b1 (true); /b0 (false); / (true)
98
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070099Exclude&
100Exclude::excludeRange(const name::Component& from, const name::Component& to)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800101{
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700102 if (from >= to) {
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700103 throw Error("Invalid exclude range [" + from.toUri() + ", " + to.toUri() + "] "
104 "(for single name exclude use Exclude::excludeOne)");
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700105 }
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800106
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700107 iterator newFrom = m_exclude.lower_bound(from);
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700108 if (newFrom == end() || !newFrom->second /*without ANY*/) {
109 std::pair<iterator, bool> fromResult = m_exclude.insert(std::make_pair(from, true));
110 newFrom = fromResult.first;
111 if (!fromResult.second) {
112 // this means that the lower bound is equal to the item itself. So, just update ANY flag
113 newFrom->second = true;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800114 }
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700115 }
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800116 // else
117 // nothing special if start of the range already exists with ANY flag set
118
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700119 iterator newTo = m_exclude.lower_bound(to); // !newTo cannot be end()
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700120 if (newTo == newFrom || !newTo->second) {
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700121 std::pair<iterator, bool> toResult = m_exclude.insert(std::make_pair(to, false));
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800122 newTo = toResult.first;
123 ++ newTo;
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700124 }
125 // else
126 // nothing to do really
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800127
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700128 m_exclude.erase(newTo, newFrom); // remove any intermediate node, since all of the are excluded
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800129
130 return *this;
131}
132
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700133Exclude&
134Exclude::excludeAfter(const name::Component& from)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800135{
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700136 iterator newFrom = m_exclude.lower_bound(from);
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700137 if (newFrom == end() || !newFrom->second /*without ANY*/) {
138 std::pair<iterator, bool> fromResult = m_exclude.insert(std::make_pair(from, true));
139 newFrom = fromResult.first;
140 if (!fromResult.second) {
141 // this means that the lower bound is equal to the item itself. So, just update ANY flag
142 newFrom->second = true;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800143 }
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700144 }
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800145 // else
146 // nothing special if start of the range already exists with ANY flag set
147
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700148 if (newFrom != m_exclude.begin()) {
149 // remove any intermediate node, since all of the are excluded
150 m_exclude.erase(m_exclude.begin(), newFrom);
151 }
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800152
153 return *this;
154}
155
156
157std::ostream&
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700158operator<<(std::ostream& os, const Exclude& exclude)
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800159{
160 bool empty = true;
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700161 for (Exclude::const_reverse_iterator i = exclude.rbegin(); i != exclude.rend(); i++) {
162 if (!i->first.empty()) {
163 if (!empty) os << ",";
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700164 os << i->first.toUri();
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700165 empty = false;
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800166 }
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700167 if (i->second) {
168 if (!empty) os << ",";
169 os << "*";
170 empty = false;
171 }
172 }
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800173 return os;
174}
175
Alexander Afanasyevb3a6af42014-01-03 13:08:28 -0800176
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700177} // namespace ndn