separate selectors
diff --git a/include/ccnx-name.h b/include/ccnx-name.h
index 8b8be4a..5f5a5c0 100644
--- a/include/ccnx-name.h
+++ b/include/ccnx-name.h
@@ -132,73 +132,6 @@
 operator <(const Name &n1, const Name &n2);
 
 
-struct InterestSelectorException:
-  virtual boost::exception, virtual exception {};
-
-class Selectors
-{
-public:
-  Selectors();
-  Selectors(const Selectors &other);
-  ~Selectors(){};
-
-  typedef enum
-  {
-    AOK_CS = 0x1,
-    AOK_NEW = 0x2,
-    AOK_DEFAULT = 0x3, // (AOK_CS | AOK_NEW)
-    AOK_STALE = 0x4,
-    AOK_EXPIRE = 0x10
-  } AOK;
-
-  typedef enum
-  {
-    LEFT = 0,
-    RIGHT = 1,
-    DEFAULT = 2
-  } CHILD_SELECTOR;
-
-  inline Selectors &
-  maxSuffixComps(int maxSCs) {m_maxSuffixComps = maxSCs; return *this;}
-
-  inline Selectors &
-  minSuffixComps(int minSCs) {m_minSuffixComps = minSCs; return *this;}
-
-  inline Selectors &
-  answerOriginKind(AOK kind) {m_answerOriginKind = kind; return *this;}
-
-  inline Selectors &
-  interestLifetime(int lifetime) {m_interestLifetime = lifetime; return *this;}
-
-  inline Selectors &
-  scope(int scope) {m_scope = scope; return *this;}
-
-  inline Selectors &
-  childSelector(CHILD_SELECTOR child) {m_childSelector = child; return *this;}
-
-  // this has no effect now
-  inline Selectors &
-  publisherPublicKeyDigest(const Bytes &digest) {m_publisherPublicKeyDigest = digest; return *this;}
-
-  CcnxCharbufPtr
-  toCcnxCharbuf() const;
-
-  bool
-  isEmpty() const;
-
-  bool
-  operator==(const Selectors &other);
-
-private:
-  int m_maxSuffixComps;
-  int m_minSuffixComps;
-  AOK m_answerOriginKind;
-  double m_interestLifetime;
-  int m_scope;
-  CHILD_SELECTOR m_childSelector;
-  // not used now
-  Bytes m_publisherPublicKeyDigest;
-};
 
 } // Ccnx
 #endif
diff --git a/include/ccnx-selectors.h b/include/ccnx-selectors.h
new file mode 100644
index 0000000..1275217
--- /dev/null
+++ b/include/ccnx-selectors.h
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012-2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+#ifndef CCNX_SELECTORS_H
+#define CCNX_SELECTORS_H
+
+#include "ccnx-common.h"
+#include "ccnx-name.h"
+
+namespace Ccnx {
+
+struct InterestSelectorException:
+  virtual boost::exception, virtual exception {};
+
+class Selectors
+{
+public:
+  Selectors();
+  Selectors(const Selectors &other);
+  ~Selectors(){};
+
+  typedef enum
+  {
+    AOK_CS = 0x1,
+    AOK_NEW = 0x2,
+    AOK_DEFAULT = 0x3, // (AOK_CS | AOK_NEW)
+    AOK_STALE = 0x4,
+    AOK_EXPIRE = 0x10
+  } AOK;
+
+  typedef enum
+  {
+    LEFT = 0,
+    RIGHT = 1,
+    DEFAULT = 2
+  } CHILD_SELECTOR;
+
+  inline Selectors &
+  maxSuffixComps(int maxSCs) {m_maxSuffixComps = maxSCs; return *this;}
+
+  inline Selectors &
+  minSuffixComps(int minSCs) {m_minSuffixComps = minSCs; return *this;}
+
+  inline Selectors &
+  answerOriginKind(AOK kind) {m_answerOriginKind = kind; return *this;}
+
+  inline Selectors &
+  interestLifetime(int lifetime) {m_interestLifetime = lifetime; return *this;}
+
+  inline Selectors &
+  scope(int scope) {m_scope = scope; return *this;}
+
+  inline Selectors &
+  childSelector(CHILD_SELECTOR child) {m_childSelector = child; return *this;}
+
+  // this has no effect now
+  inline Selectors &
+  publisherPublicKeyDigest(const Bytes &digest) {m_publisherPublicKeyDigest = digest; return *this;}
+
+  CcnxCharbufPtr
+  toCcnxCharbuf() const;
+
+  bool
+  isEmpty() const;
+
+  bool
+  operator==(const Selectors &other);
+
+private:
+  int m_maxSuffixComps;
+  int m_minSuffixComps;
+  AOK m_answerOriginKind;
+  double m_interestLifetime;
+  int m_scope;
+  CHILD_SELECTOR m_childSelector;
+  // not used now
+  Bytes m_publisherPublicKeyDigest;
+};
+
+} // Ccnx
+
+#endif
diff --git a/include/ccnx-tunnel.h b/include/ccnx-tunnel.h
index bc13f9a..104c7cf 100644
--- a/include/ccnx-tunnel.h
+++ b/include/ccnx-tunnel.h
@@ -6,6 +6,7 @@
 #include "ccnx-common.h"
 #include "ccnx-wrapper.h"
 #include "ccnx-name.h"
+#include "ccnx-selectors.h"
 
 #define _OVERRIDE
 #ifdef __GNUC__
diff --git a/include/ccnx-wrapper.h b/include/ccnx-wrapper.h
index 6e8e595..667d4be 100644
--- a/include/ccnx-wrapper.h
+++ b/include/ccnx-wrapper.h
@@ -7,6 +7,7 @@
 
 #include "ccnx-common.h"
 #include "ccnx-name.h"
+#include "ccnx-selectors.h"
 #include "ccnx-closure.h"
 
 using namespace std;
diff --git a/src/ccnx-name.cpp b/src/ccnx-name.cpp
index 9bc2663..3803987 100644
--- a/src/ccnx-name.cpp
+++ b/src/ccnx-name.cpp
@@ -274,117 +274,5 @@
   return ss1.str() < ss2.str();
 }
 
-Selectors::Selectors()
-          : m_maxSuffixComps(-1)
-          , m_minSuffixComps(-1)
-          , m_answerOriginKind(AOK_DEFAULT)
-          , m_interestLifetime(-1.0)
-          , m_scope(-1)
-          , m_childSelector(DEFAULT)
-{
-}
-
-Selectors::Selectors(const Selectors &other)
-{
-  m_maxSuffixComps = other.m_maxSuffixComps;
-  m_minSuffixComps = other.m_minSuffixComps;
-  m_answerOriginKind = other.m_answerOriginKind;
-  m_interestLifetime = other.m_interestLifetime;
-  m_scope = other.m_scope;
-  m_childSelector = other.m_childSelector;
-  m_publisherPublicKeyDigest = other.m_publisherPublicKeyDigest;
-}
-
-bool
-Selectors::operator == (const Selectors &other)
-{
-  return m_maxSuffixComps == other.m_maxSuffixComps
-         && m_minSuffixComps == other.m_minSuffixComps
-         && m_answerOriginKind == other.m_answerOriginKind
-         && (m_interestLifetime - other.m_interestLifetime) < 10e-4
-         && m_scope == other.m_scope
-         && m_childSelector == other.m_childSelector;
-}
-
-bool
-Selectors::isEmpty() const
-{
-  return m_maxSuffixComps == -1
-         && m_minSuffixComps == -1
-         && m_answerOriginKind == AOK_DEFAULT
-         && (m_interestLifetime - (-1.0)) < 10e-4
-         && m_scope == -1
-         && m_childSelector == DEFAULT;
-}
-
-
-CcnxCharbufPtr
-Selectors::toCcnxCharbuf() const
-{
-  if (isEmpty())
-  {
-    return CcnxCharbuf::Null;
-  }
-  CcnxCharbufPtr ptr(new CcnxCharbuf());
-  ccn_charbuf *cbuf = ptr->getBuf();
-  ccn_charbuf_append_tt(cbuf, CCN_DTAG_Interest, CCN_DTAG);
-  ccn_charbuf_append_tt(cbuf, CCN_DTAG_Name, CCN_DTAG);
-  ccn_charbuf_append_closer(cbuf); // </Name>
-
-  if (m_maxSuffixComps < m_minSuffixComps)
-  {
-    boost::throw_exception(InterestSelectorException() << error_info_str("MaxSuffixComps = " + boost::lexical_cast<string>(m_maxSuffixComps) + " is smaller than  MinSuffixComps = " + boost::lexical_cast<string>(m_minSuffixComps)));
-  }
-
-  if (m_maxSuffixComps > 0)
-  {
-    ccnb_tagged_putf(cbuf, CCN_DTAG_MaxSuffixComponents, "%d", m_maxSuffixComps);
-  }
-
-  if (m_minSuffixComps > 0)
-  {
-    ccnb_tagged_putf(cbuf, CCN_DTAG_MinSuffixComponents, "%d", m_minSuffixComps);
-  }
-
-  if (m_answerOriginKind != AOK_DEFAULT)
-  {
-    // it was not using "ccnb_tagged_putf" in ccnx c code, no idea why
-    ccn_charbuf_append_tt(cbuf, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
-    ccnb_append_number(cbuf, m_answerOriginKind);
-    ccn_charbuf_append_closer(cbuf); // <AnswerOriginKind>
-  }
-
-  if (m_scope != -1)
-  {
-    ccnb_tagged_putf(cbuf, CCN_DTAG_Scope, "%d", m_scope);
-  }
-
-  if (m_interestLifetime > 0.0)
-  {
-    // Ccnx timestamp unit is weird 1/4096 second
-    // this is from their code
-    unsigned lifetime = 4096 * (m_interestLifetime + 1.0/8192.0);
-    if (lifetime == 0 || lifetime > (30 << 12))
-    {
-      boost::throw_exception(InterestSelectorException() << error_info_str("Ccnx requires 0 < lifetime < 30.0. lifetime= " + boost::lexical_cast<string>(m_interestLifetime)));
-    }
-    unsigned char buf[3] = {0};
-    for (int i = sizeof(buf) - 1; i >= 0; i--, lifetime >>= 8)
-    {
-      buf[i] = lifetime & 0xff;
-    }
-    ccnb_append_tagged_blob(cbuf, CCN_DTAG_InterestLifetime, buf, sizeof(buf));
-  }
-
-  if (m_childSelector != DEFAULT)
-  {
-    ccnb_tagged_putf(cbuf, CCN_DTAG_ChildSelector, "%d", m_childSelector);
-  }
-
-
-  ccn_charbuf_append_closer(cbuf); // </Interest>
-
-  return ptr;
-}
 
 } // Ccnx
diff --git a/src/ccnx-selectors.cpp b/src/ccnx-selectors.cpp
new file mode 100644
index 0000000..001c1b7
--- /dev/null
+++ b/src/ccnx-selectors.cpp
@@ -0,0 +1,120 @@
+#include "ccnx-selectors.h"
+#include "ccnx-common.h"
+#include <boost/lexical_cast.hpp>
+
+namespace Ccnx {
+
+Selectors::Selectors()
+          : m_maxSuffixComps(-1)
+          , m_minSuffixComps(-1)
+          , m_answerOriginKind(AOK_DEFAULT)
+          , m_interestLifetime(-1.0)
+          , m_scope(-1)
+          , m_childSelector(DEFAULT)
+{
+}
+
+Selectors::Selectors(const Selectors &other)
+{
+  m_maxSuffixComps = other.m_maxSuffixComps;
+  m_minSuffixComps = other.m_minSuffixComps;
+  m_answerOriginKind = other.m_answerOriginKind;
+  m_interestLifetime = other.m_interestLifetime;
+  m_scope = other.m_scope;
+  m_childSelector = other.m_childSelector;
+  m_publisherPublicKeyDigest = other.m_publisherPublicKeyDigest;
+}
+
+bool
+Selectors::operator == (const Selectors &other)
+{
+  return m_maxSuffixComps == other.m_maxSuffixComps
+         && m_minSuffixComps == other.m_minSuffixComps
+         && m_answerOriginKind == other.m_answerOriginKind
+         && (m_interestLifetime - other.m_interestLifetime) < 10e-4
+         && m_scope == other.m_scope
+         && m_childSelector == other.m_childSelector;
+}
+
+bool
+Selectors::isEmpty() const
+{
+  return m_maxSuffixComps == -1
+         && m_minSuffixComps == -1
+         && m_answerOriginKind == AOK_DEFAULT
+         && (m_interestLifetime - (-1.0)) < 10e-4
+         && m_scope == -1
+         && m_childSelector == DEFAULT;
+}
+
+
+CcnxCharbufPtr
+Selectors::toCcnxCharbuf() const
+{
+  if (isEmpty())
+  {
+    return CcnxCharbuf::Null;
+  }
+  CcnxCharbufPtr ptr(new CcnxCharbuf());
+  ccn_charbuf *cbuf = ptr->getBuf();
+  ccn_charbuf_append_tt(cbuf, CCN_DTAG_Interest, CCN_DTAG);
+  ccn_charbuf_append_tt(cbuf, CCN_DTAG_Name, CCN_DTAG);
+  ccn_charbuf_append_closer(cbuf); // </Name>
+
+  if (m_maxSuffixComps < m_minSuffixComps)
+  {
+    boost::throw_exception(InterestSelectorException() << error_info_str("MaxSuffixComps = " + boost::lexical_cast<string>(m_maxSuffixComps) + " is smaller than  MinSuffixComps = " + boost::lexical_cast<string>(m_minSuffixComps)));
+  }
+
+  if (m_maxSuffixComps > 0)
+  {
+    ccnb_tagged_putf(cbuf, CCN_DTAG_MaxSuffixComponents, "%d", m_maxSuffixComps);
+  }
+
+  if (m_minSuffixComps > 0)
+  {
+    ccnb_tagged_putf(cbuf, CCN_DTAG_MinSuffixComponents, "%d", m_minSuffixComps);
+  }
+
+  if (m_answerOriginKind != AOK_DEFAULT)
+  {
+    // it was not using "ccnb_tagged_putf" in ccnx c code, no idea why
+    ccn_charbuf_append_tt(cbuf, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
+    ccnb_append_number(cbuf, m_answerOriginKind);
+    ccn_charbuf_append_closer(cbuf); // <AnswerOriginKind>
+  }
+
+  if (m_scope != -1)
+  {
+    ccnb_tagged_putf(cbuf, CCN_DTAG_Scope, "%d", m_scope);
+  }
+
+  if (m_interestLifetime > 0.0)
+  {
+    // Ccnx timestamp unit is weird 1/4096 second
+    // this is from their code
+    unsigned lifetime = 4096 * (m_interestLifetime + 1.0/8192.0);
+    if (lifetime == 0 || lifetime > (30 << 12))
+    {
+      boost::throw_exception(InterestSelectorException() << error_info_str("Ccnx requires 0 < lifetime < 30.0. lifetime= " + boost::lexical_cast<string>(m_interestLifetime)));
+    }
+    unsigned char buf[3] = {0};
+    for (int i = sizeof(buf) - 1; i >= 0; i--, lifetime >>= 8)
+    {
+      buf[i] = lifetime & 0xff;
+    }
+    ccnb_append_tagged_blob(cbuf, CCN_DTAG_InterestLifetime, buf, sizeof(buf));
+  }
+
+  if (m_childSelector != DEFAULT)
+  {
+    ccnb_tagged_putf(cbuf, CCN_DTAG_ChildSelector, "%d", m_childSelector);
+  }
+
+
+  ccn_charbuf_append_closer(cbuf); // </Interest>
+
+  return ptr;
+}
+
+} // Ccnx
diff --git a/test/test-ccnx-name.cc b/test/test-ccnx-name.cc
index 5084246..f617397 100644
--- a/test/test-ccnx-name.cc
+++ b/test/test-ccnx-name.cc
@@ -33,10 +33,4 @@
   // Charbuf related stuff will be checked in other place
 }
 
-BOOST_AUTO_TEST_CASE (SelectorsTest)
-{
-  Selectors s;
-  BOOST_CHECK(s.isEmpty());
-}
-
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/test-ccnx-wrapper.cc b/test/test-ccnx-wrapper.cc
index 58d8d24..7c010ec 100644
--- a/test/test-ccnx-wrapper.cc
+++ b/test/test-ccnx-wrapper.cc
@@ -1,6 +1,7 @@
 #include "ccnx-wrapper.h"
 #include "ccnx-closure.h"
 #include "ccnx-name.h"
+#include "ccnx-selectors.h"
 #include "ccnx-pco.h"
 #include <unistd.h>
 
diff --git a/wscript b/wscript
index e18214a..609f64d 100644
--- a/wscript
+++ b/wscript
@@ -67,6 +67,7 @@
             'src/ccnx-tunnel.cpp',
             'src/object-db-file.cpp',
             'src/ccnx-name.cpp',
+            'src/ccnx-selectors.cpp',
             ],
         use = 'BOOST BOOST_THREAD SSL CCNX',
         includes = ['include', ],