/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (c) 2013-2014,  Regents of the University of California.
 * All rights reserved.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 * This file licensed under New BSD License.  See COPYING for detailed information about
 * ndn-cxx library copyright, permissions, and redistribution restrictions.
 *
 */

#include "common.hpp"

#include "oid.hpp"

#include "../security/cryptopp.hpp"

#include <sstream>

using namespace std;
using namespace CryptoPP;

namespace ndn {

OID::OID(const char* oid)
{
  construct(oid);
}

OID::OID(const string& oid)
{
  construct(oid);
}

void
OID::construct(const std::string& oid)
{
  string str = oid + ".";

  size_t pos = 0;
  size_t ppos = 0;

  while (string::npos != pos) {
    ppos = pos;

    pos = str.find_first_of('.', pos);
    if (pos == string::npos)
      break;

    m_oid.push_back(atoi(str.substr(ppos, pos - ppos).c_str()));

    pos++;
  }
}

string OID::toString() const
{
  ostringstream convert;

  for (vector<int>::const_iterator it = m_oid.begin(); it != m_oid.end(); ++it) {
    if (it != m_oid.begin())
      convert << ".";
    convert << *it;
  }

  return convert.str();
}

bool
OID::equal(const OID& oid) const
{
  vector<int>::const_iterator i = m_oid.begin();
  vector<int>::const_iterator j = oid.m_oid.begin();

  for (; i != m_oid.end () && j != oid.m_oid.end (); i++, j++) {
    if (*i != *j)
      return false;
  }

  if (i == m_oid.end () && j == oid.m_oid.end ())
    return true;
  else
    return false;
}

inline void
EncodeValue(BufferedTransformation& bt, word32 v)
{
  for (unsigned int i = RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U) - 7; i != 0; i -= 7)
    bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));
  bt.Put((byte)(v & 0x7f));
}

inline size_t
DecodeValue(BufferedTransformation& bt, word32& v)
{
  v = 0;
  size_t i = 0;
  while (true)
    {
      byte b;
      if (!bt.Get(b))
        BERDecodeError();
      i++;
      if (v >> (8*sizeof(v) - 7)) // v about to overflow
        BERDecodeError();
      v <<= 7;
      v += b & 0x7f;
      if (!(b & 0x80))
        return i;
    }
}

void
OID::encode(CryptoPP::BufferedTransformation& out) const
{
  BOOST_ASSERT(m_oid.size() >= 2);

  ByteQueue temp;
  temp.Put(byte(m_oid[0] * 40 + m_oid[1]));
  for (size_t i = 2; i < m_oid.size(); i++)
    EncodeValue(temp, m_oid[i]);

  out.Put(OBJECT_IDENTIFIER);
  DERLengthEncode(out, temp.CurrentSize());
  temp.TransferTo(out);
}

void
OID::decode(CryptoPP::BufferedTransformation& in)
{
  byte b;
  if (!in.Get(b) || b != OBJECT_IDENTIFIER)
    BERDecodeError();

  size_t length;
  if (!BERLengthDecode(in, length) || length < 1)
    BERDecodeError();

  if (!in.Get(b))
    BERDecodeError();

  length--;
  m_oid.resize(2);
  m_oid[0] = b / 40;
  m_oid[1] = b % 40;

  while (length > 0)
    {
      word32 v;
      size_t valueLen = DecodeValue(in, v);
      if (valueLen > length)
        BERDecodeError();
      m_oid.push_back(v);
      length -= valueLen;
    }
}

} // namespace ndn
