diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index a392ff614693e0cba62a64757decfbb14506f895..4141942d6f07e3af5143be43a0addbae196823e6 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -184,7 +184,8 @@ set (COMMON_UNIT_TESTS_LIB_SRC_FILES
   utils/RegexTest.cpp
   utils/UtilsTest.cpp
   UserIdentityTest.cpp
-  optionalTest.cpp)
+  optionalTest.cpp
+  rangeTest.cpp)
 
 add_library (ctacommonunittests SHARED
   ${COMMON_UNIT_TESTS_LIB_SRC_FILES})
diff --git a/common/range.hpp b/common/range.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..96b3eccd7f4970038b021f1787a6e96a2ae804aa
--- /dev/null
+++ b/common/range.hpp
@@ -0,0 +1,95 @@
+/*
+ * The CERN Tape Archive (CTA) project
+ * Copyright (C) 2015  CERN
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <limits>
+#include "common/exception/Exception.hpp"
+
+namespace cta {
+template <typename T>
+class range: public std::initializer_list<T> {
+public:
+  range (T begin, T end, T step=1): m_begin(begin), m_end(end), m_step(step) {}
+
+  class iterator {
+  private:
+    friend range;
+    enum class direction: bool { forward, backward };
+    iterator(T begin, T end, T step, iterator::direction dir): m_val(begin), m_limit(end), m_step(step), m_dir(dir) {}
+  public:
+    CTA_GENERATE_EXCEPTION_CLASS(DereferencingPastEnd);
+    T operator*() { if (m_val == m_limit) throw DereferencingPastEnd("In range::operator*(): dereferencing out of bounds"); return m_val; }
+    iterator & operator++() { doInc(); return *this; }
+    iterator operator++(int) { iterator ret(*this); doInc(); return ret; }
+    void doInc() { 
+      switch (m_dir) { 
+        // Increment/decrement variable, preventing over/underflow, and overshooting the limit.
+        case direction::forward:
+          // Prevent overflow
+          if (m_step > std::numeric_limits<T>::max() - m_val) {
+            m_val=m_limit;
+          } else {
+            m_val+=m_step;
+            // Prevent overshoot.
+            if (m_val > m_limit)
+              m_val=m_limit;
+          }
+          break;
+        case direction::backward: 
+          // Prevent underflow
+          if (m_step > m_val - std::numeric_limits<T>::max() ) {
+            m_val=m_limit;
+          } else {
+            m_val-=m_step;
+            if (m_val < m_limit) 
+              m_val = m_limit; 
+          }
+          break;
+      }
+    }
+    bool operator==(const iterator& other) { checkIteratorsComparable(other); return m_val == other.m_val; }
+    bool operator!=(const iterator& other) { checkIteratorsComparable(other); return m_val != other.m_val; }
+    CTA_GENERATE_EXCEPTION_CLASS(NonComparableIterators);
+  private:
+    void checkIteratorsComparable(const iterator & other) const {
+      if (m_limit != other.m_limit || m_step != other.m_step || m_dir != other.m_dir)
+        throw NonComparableIterators("In range::checkIteratorsComparable(): comparing iterators from different ranges.");
+    }
+    
+    T m_val;
+    const T m_limit, m_step;
+    direction m_dir;
+  };
+
+  iterator cbegin() const {
+    return iterator(m_begin, m_end, m_step, m_begin<=m_end?iterator::direction::forward:iterator::direction::backward);
+  }
+
+  iterator cend() const {
+    return iterator(m_end, m_end, m_step, m_begin<=m_end?iterator::direction::forward:iterator::direction::backward);
+  }
+  
+  iterator begin() const { return cbegin(); }
+  iterator end() const { return cend(); }
+private:
+  const T m_begin;
+  const T m_end;
+  const T m_step;
+};
+} // namesapce cta
diff --git a/common/rangeTest.cpp b/common/rangeTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b7c4413401139e2483d240f5da3de2783012bc70
--- /dev/null
+++ b/common/rangeTest.cpp
@@ -0,0 +1,53 @@
+/*
+ * The CERN Tape Archive (CTA) project
+ * Copyright (C) 2015  CERN
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "range.hpp"
+#include <list>
+
+#include <gtest/gtest.h>
+
+namespace unitTests {
+
+TEST(cta_rangeTest, basic) {
+  using namespace cta;
+  
+  std::list<size_t> l;
+  // Test forward
+  for (const auto &i: range<size_t>(0, 4)) l.emplace_back(i);
+  ASSERT_EQ(std::list<size_t>({0,1,2,3}), l);
+  l.clear();
+  // Test forward with step.
+  for (const auto &i: range<size_t>(0, 10, 3)) l.emplace_back(i);
+  ASSERT_EQ(std::list<size_t>({0,3,6,9}), l);
+  l.clear();
+  // Test forward overflow
+  const auto max = std::numeric_limits<size_t>::max();
+  for (const auto &i: range<size_t>(max - 10, max, 3)) l.emplace_back(i);
+  ASSERT_EQ(std::list<size_t>({max-10, max-7, max-4, max-1}), l);
+  l.clear();
+  // Test backwards
+  for (const auto &i: range<size_t>(10, 5)) l.emplace_back(i);
+  ASSERT_EQ(std::list<size_t>({10, 9, 8, 7, 6}), l);
+  l.clear();
+  // Test backwards with step and underflow.
+  for (const auto &i: range<size_t>(10, 0, 3)) l.emplace_back(i);
+  ASSERT_EQ(std::list<size_t>({10, 7, 4, 1}), l);
+
+}
+
+}
\ No newline at end of file