<commit_before>#include "renderMesh.hpp"
#include "Vertex.hpp"
#include "Mesh.hpp"
#include "Rasterizer.hpp"

const float kProjPlaneDist = 320.f;

void draw(Rasterizer& raster, const Mesh& mesh, const arma::mat44& mat)
{
    const unsigned * idxs = mesh.getIndices();
    unsigned idxc = mesh.getIndexCount();

    for(int i = 2; i < idxc; i += 3)
    {
        const Vertex& a = mesh.getVertex(idxs[i - 2]);
        const Vertex& b = mesh.getVertex(idxs[i - 1]);
        const Vertex& c = mesh.getVertex(idxs[i - 0]);

        arma::vec4 av;
        av(0) = a.position.x;
        av(1) = a.position.y;
        av(2) = a.position.z;
        av(3) = 1.f;

        arma::vec4 bv;
        bv(0) = b.position.x;
        bv(1) = b.position.y;
        bv(2) = b.position.z;
        bv(3) = 1.f;

        arma::vec4 cv;
        cv(0) = c.position.x;
        cv(1) = c.position.y;
        cv(2) = c.position.z;
        cv(3) = 1.f;

        av = mat * av;
        bv = mat * bv;
        cv = mat * cv;

        const float kInvProjPlaneDist = 1.f / kProjPlaneDist;

        const float screenwidth = 640.f;
        const float screenheight = 480.f;

        av(0) = av(0) * (kProjPlaneDist / std::fabs(av(2))) + screenwidth / 2.f;
        av(1) = av(1) * (kProjPlaneDist / std::fabs(av(2))) + screenheight / 2.f;

        bv(0) = bv(0) * (kProjPlaneDist / std::fabs(bv(2))) + screenwidth / 2.f;
        bv(1) = bv(1) * (kProjPlaneDist / std::fabs(bv(2))) + screenheight / 2.f;

        cv(0) = cv(0) * (kProjPlaneDist / std::fabs(cv(2))) + screenwidth / 2.f;
        cv(1) = cv(1) * (kProjPlaneDist / std::fabs(cv(2))) + screenheight / 2.f;

        //        std::printf("0x%x %f\n", a.color, av(2));
        //        std::printf("0x%x %f\n", b.color, bv(2));
        //        std::printf("0x%x %f\n", c.color, cv(2));

        raster.addVertex(av(0), av(1), a.color, av(2), a.u, a.v);
        raster.addVertex(bv(0), bv(1), b.color, bv(2), b.u, b.v);
        raster.addVertex(cv(0), cv(1), c.color, cv(2), c.u, c.v);

        //        return;

        //        prim.drawTriangle(av(0), av(1), a.color, bv(0), bv(1), b.color, cv(0), cv(1), c.color);
    }//for

}<commit_msg>Clearing up a bit.<commit_after>#include "renderMesh.hpp"
#include "Vertex.hpp"
#include "Mesh.hpp"
#include "Rasterizer.hpp"

const float kProjPlaneDist = 320.f;

void draw(Rasterizer& raster, const Mesh& mesh, const arma::mat44& mat)
{
    const unsigned * idxs = mesh.getIndices();
    unsigned idxc = mesh.getIndexCount();

    for(int i = 2; i < idxc; i += 3)
    {
        const Vertex& a = mesh.getVertex(idxs[i - 2]);
        const Vertex& b = mesh.getVertex(idxs[i - 1]);
        const Vertex& c = mesh.getVertex(idxs[i - 0]);

        arma::vec4 av;
        av(0) = a.position.x;
        av(1) = a.position.y;
        av(2) = a.position.z;
        av(3) = 1.f;

        arma::vec4 bv;
        bv(0) = b.position.x;
        bv(1) = b.position.y;
        bv(2) = b.position.z;
        bv(3) = 1.f;

        arma::vec4 cv;
        cv(0) = c.position.x;
        cv(1) = c.position.y;
        cv(2) = c.position.z;
        cv(3) = 1.f;

        av = mat * av;
        bv = mat * bv;
        cv = mat * cv;

        const float screenwidth = 640.f;
        const float screenheight = 480.f;

        av(0) = av(0) * (kProjPlaneDist / std::fabs(av(2))) + screenwidth / 2.f;
        av(1) = av(1) * (kProjPlaneDist / std::fabs(av(2))) + screenheight / 2.f;

        bv(0) = bv(0) * (kProjPlaneDist / std::fabs(bv(2))) + screenwidth / 2.f;
        bv(1) = bv(1) * (kProjPlaneDist / std::fabs(bv(2))) + screenheight / 2.f;

        cv(0) = cv(0) * (kProjPlaneDist / std::fabs(cv(2))) + screenwidth / 2.f;
        cv(1) = cv(1) * (kProjPlaneDist / std::fabs(cv(2))) + screenheight / 2.f;

        raster.addVertex(av(0), av(1), a.color, av(2), a.u, a.v);
        raster.addVertex(bv(0), bv(1), b.color, bv(2), b.u, b.v);
        raster.addVertex(cv(0), cv(1), c.color, cv(2), c.u, c.v);
    }//for

}<|endoftext|>


<commit_before>#include "renderMesh.hpp"
#include "Vertex.hpp"
#include "Mesh.hpp"
#include "Rasterizer.hpp"

const float kProjPlaneDist = 320.f;
const float halfscreenwidth = 640.f / 2.f;
const float halfscreenheight = 480.f / 2.f;

void draw(Rasterizer& raster, const Mesh& mesh, const arma::mat44& mat, std::vector<BufferedVertice>& buff)
{
    const unsigned * idxs = mesh.getIndices();
    const unsigned idxc = mesh.getIndexCount();
    const unsigned vc = mesh.getVertexCount();
    arma::vec4 av;

    buff.clear();

    for(int i = 0; i < vc; ++i)
    {
        const Vertex& a = mesh.getVertex(i);

        av(0) = a.position.x;
        av(1) = a.position.y;
        av(2) = a.position.z;
        av(3) = 1.f;
        av = mat * av;

        av(0) = av(0) * (kProjPlaneDist / std::fabs(av(2))) + halfscreenwidth;
        av(1) = av(1) * (kProjPlaneDist / std::fabs(av(2))) + halfscreenheight;

        buff.push_back(BufferedVertice(av(0), av(1), a.color, av(2), a.u, a.v));

    }//for

    for(int i = 0; i < idxc; ++i)
    {
        const BufferedVertice&v = buff[idxs[i]];
        raster.addVertex(v.x, v.y, v.c, v.d, v.u, v.v);
    }
}<commit_msg>Made it use triangles not points in render mesh.<commit_after>#include "renderMesh.hpp"
#include "Vertex.hpp"
#include "Mesh.hpp"
#include "Rasterizer.hpp"

const float kProjPlaneDist = 320.f;
const float halfscreenwidth = 640.f / 2.f;
const float halfscreenheight = 480.f / 2.f;

void draw(Rasterizer& raster, const Mesh& mesh, const arma::mat44& mat, std::vector<BufferedVertice>& buff)
{
    const unsigned * idxs = mesh.getIndices();
    const unsigned idxc = mesh.getIndexCount();
    const unsigned vc = mesh.getVertexCount();
    arma::vec4 av;

    buff.clear();

    for(int i = 0; i < vc; ++i)
    {
        const Vertex& a = mesh.getVertex(i);

        av(0) = a.position.x;
        av(1) = a.position.y;
        av(2) = a.position.z;
        av(3) = 1.f;
        av = mat * av;

        av(0) = av(0) * (kProjPlaneDist / std::fabs(av(2))) + halfscreenwidth;
        av(1) = av(1) * (kProjPlaneDist / std::fabs(av(2))) + halfscreenheight;

        buff.push_back(BufferedVertice(av(0), av(1), a.color, av(2), a.u, a.v));

    }//for

    for(int i = 0; (i + 2) < idxc; i += 3)
    {
        const BufferedVertice& a = buff[idxs[i]];
        const BufferedVertice& b = buff[idxs[i + 1]];
        const BufferedVertice& c = buff[idxs[i + 2]];
        raster.addVertex(a.x, a.y, a.c, a.d, a.u, b.v);
        raster.addVertex(b.x, b.y, b.c, b.d, b.u, b.v);
        raster.addVertex(c.x, c.y, c.c, c.d, c.u, c.v);
    }
}<|endoftext|>


<commit_before>/*
* BER Decoder
* (C) 1999-2008 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/ber_dec.h>
#include <botan/bigint.h>
#include <botan/get_byte.h>

namespace Botan {

namespace {

/*
* BER decode an ASN.1 type tag
*/
size_t decode_tag(DataSource* ber, ASN1_Tag& type_tag, ASN1_Tag& class_tag)
   {
   byte b;
   if(!ber->read_byte(b))
      {
      class_tag = type_tag = NO_OBJECT;
      return 0;
      }

   if((b & 0x1F) != 0x1F)
      {
      type_tag = ASN1_Tag(b & 0x1F);
      class_tag = ASN1_Tag(b & 0xE0);
      return 1;
      }

   size_t tag_bytes = 1;
   class_tag = ASN1_Tag(b & 0xE0);

   size_t tag_buf = 0;
   while(true)
      {
      if(!ber->read_byte(b))
         throw BER_Decoding_Error("Long-form tag truncated");
      if(tag_buf & 0xFF000000)
         throw BER_Decoding_Error("Long-form tag overflowed 32 bits");
      ++tag_bytes;
      tag_buf = (tag_buf << 7) | (b & 0x7F);
      if((b & 0x80) == 0) break;
      }
   type_tag = ASN1_Tag(tag_buf);
   return tag_bytes;
   }

/*
* Find the EOC marker
*/
size_t find_eoc(DataSource*);

/*
* BER decode an ASN.1 length field
*/
size_t decode_length(DataSource* ber, size_t& field_size)
   {
   byte b;
   if(!ber->read_byte(b))
      throw BER_Decoding_Error("Length field not found");
   field_size = 1;
   if((b & 0x80) == 0)
      return b;

   field_size += (b & 0x7F);
   if(field_size == 1) return find_eoc(ber);
   if(field_size > 5)
      throw BER_Decoding_Error("Length field is too large");

   size_t length = 0;

   for(size_t i = 0; i != field_size - 1; ++i)
      {
      if(get_byte(0, length) != 0)
         throw BER_Decoding_Error("Field length overflow");
      if(!ber->read_byte(b))
         throw BER_Decoding_Error("Corrupted length field");
      length = (length << 8) | b;
      }
   return length;
   }

/*
* BER decode an ASN.1 length field
*/
size_t decode_length(DataSource* ber)
   {
   size_t dummy;
   return decode_length(ber, dummy);
   }

/*
* Find the EOC marker
*/
size_t find_eoc(DataSource* ber)
   {
   SecureVector<byte> buffer(DEFAULT_BUFFERSIZE), data;

   while(true)
      {
      const size_t got = ber->peek(&buffer[0], buffer.size(), data.size());
      if(got == 0)
         break;

      data += std::make_pair(&buffer[0], got);
      }

   DataSource_Memory source(data);
   data.clear();

   size_t length = 0;
   while(true)
      {
      ASN1_Tag type_tag, class_tag;
      size_t tag_size = decode_tag(&source, type_tag, class_tag);
      if(type_tag == NO_OBJECT)
         break;

      size_t length_size = 0;
      size_t item_size = decode_length(&source, length_size);
      source.discard_next(item_size);

      length += item_size + length_size + tag_size;

      if(type_tag == EOC)
         break;
      }
   return length;
   }

}

/*
* Check a type invariant on BER data
*/
void BER_Object::assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag)
   {
   if(this->type_tag != type_tag || this->class_tag != class_tag)
      throw BER_Decoding_Error("Tag mismatch when decoding");
   }

/*
* Check if more objects are there
*/
bool BER_Decoder::more_items() const
   {
   if(source->end_of_data() && (pushed.type_tag == NO_OBJECT))
      return false;
   return true;
   }

/*
* Verify that no bytes remain in the source
*/
BER_Decoder& BER_Decoder::verify_end()
   {
   if(!source->end_of_data() || (pushed.type_tag != NO_OBJECT))
      throw Invalid_State("BER_Decoder::verify_end called, but data remains");
   return (*this);
   }

/*
* Save all the bytes remaining in the source
*/
BER_Decoder& BER_Decoder::raw_bytes(MemoryRegion<byte>& out)
   {
   out.clear();
   byte buf;
   while(source->read_byte(buf))
      out.push_back(buf);
   return (*this);
   }

/*
* Discard all the bytes remaining in the source
*/
BER_Decoder& BER_Decoder::discard_remaining()
   {
   byte buf;
   while(source->read_byte(buf))
      ;
   return (*this);
   }

/*
* Return the BER encoding of the next object
*/
BER_Object BER_Decoder::get_next_object()
   {
   BER_Object next;

   if(pushed.type_tag != NO_OBJECT)
      {
      next = pushed;
      pushed.class_tag = pushed.type_tag = NO_OBJECT;
      return next;
      }

   decode_tag(source, next.type_tag, next.class_tag);
   if(next.type_tag == NO_OBJECT)
      return next;

   size_t length = decode_length(source);
   next.value.resize(length);
   if(source->read(&next.value[0], length) != length)
      throw BER_Decoding_Error("Value truncated");

   if(next.type_tag == EOC && next.class_tag == UNIVERSAL)
      return get_next_object();

   return next;
   }

/*
* Push a object back into the stream
*/
void BER_Decoder::push_back(const BER_Object& obj)
   {
   if(pushed.type_tag != NO_OBJECT)
      throw Invalid_State("BER_Decoder: Only one push back is allowed");
   pushed = obj;
   }

/*
* Begin decoding a CONSTRUCTED type
*/
BER_Decoder BER_Decoder::start_cons(ASN1_Tag type_tag,
                                    ASN1_Tag class_tag)
   {
   BER_Object obj = get_next_object();
   obj.assert_is_a(type_tag, ASN1_Tag(class_tag | CONSTRUCTED));

   BER_Decoder result(&obj.value[0], obj.value.size());
   result.parent = this;
   return result;
   }

/*
* Finish decoding a CONSTRUCTED type
*/
BER_Decoder& BER_Decoder::end_cons()
   {
   if(!parent)
      throw Invalid_State("BER_Decoder::end_cons called with NULL parent");
   if(!source->end_of_data())
      throw Decoding_Error("BER_Decoder::end_cons called with data left");
   return (*parent);
   }

/*
* BER_Decoder Constructor
*/
BER_Decoder::BER_Decoder(DataSource& src)
   {
   source = &src;
   owns = false;
   pushed.type_tag = pushed.class_tag = NO_OBJECT;
   parent = 0;
   }

/*
* BER_Decoder Constructor
 */
BER_Decoder::BER_Decoder(const byte data[], size_t length)
   {
   source = new DataSource_Memory(data, length);
   owns = true;
   pushed.type_tag = pushed.class_tag = NO_OBJECT;
   parent = 0;
   }

/*
* BER_Decoder Constructor
*/
BER_Decoder::BER_Decoder(const MemoryRegion<byte>& data)
   {
   source = new DataSource_Memory(data);
   owns = true;
   pushed.type_tag = pushed.class_tag = NO_OBJECT;
   parent = 0;
   }

/*
* BER_Decoder Copy Constructor
*/
BER_Decoder::BER_Decoder(const BER_Decoder& other)
   {
   source = other.source;
   owns = false;
   if(other.owns)
      {
      other.owns = false;
      owns = true;
      }
   pushed.type_tag = pushed.class_tag = NO_OBJECT;
   parent = other.parent;
   }

/*
* BER_Decoder Destructor
*/
BER_Decoder::~BER_Decoder()
   {
   if(owns)
      delete source;
   source = 0;
   }

/*
* Request for an object to decode itself
*/
BER_Decoder& BER_Decoder::decode(ASN1_Object& obj)
   {
   obj.decode_from(*this);
   return (*this);
   }

/*
* Decode a BER encoded NULL
*/
BER_Decoder& BER_Decoder::decode_null()
   {
   BER_Object obj = get_next_object();
   obj.assert_is_a(NULL_TAG, UNIVERSAL);
   if(obj.value.size())
      throw BER_Decoding_Error("NULL object had nonzero size");
   return (*this);
   }

/*
* Decode a BER encoded BOOLEAN
*/
BER_Decoder& BER_Decoder::decode(bool& out)
   {
   return decode(out, BOOLEAN, UNIVERSAL);
   }

/*
* Decode a small BER encoded INTEGER
*/
BER_Decoder& BER_Decoder::decode(size_t& out)
   {
   return decode(out, INTEGER, UNIVERSAL);
   }

/*
* Decode a BER encoded INTEGER
*/
BER_Decoder& BER_Decoder::decode(BigInt& out)
   {
   return decode(out, INTEGER, UNIVERSAL);
   }

BER_Decoder& BER_Decoder::decode_octet_string_bigint(BigInt& out)
   {
   SecureVector<byte> out_vec;
   decode(out_vec, OCTET_STRING);
   out = BigInt::decode(&out_vec[0], out_vec.size());
   return (*this);
   }

/*
* Decode a BER encoded BOOLEAN
*/
BER_Decoder& BER_Decoder::decode(bool& out,
                                 ASN1_Tag type_tag, ASN1_Tag class_tag)
   {
   BER_Object obj = get_next_object();
   obj.assert_is_a(type_tag, class_tag);

   if(obj.value.size() != 1)
      throw BER_Decoding_Error("BER boolean value had invalid size");

   out = (obj.value[0]) ? true : false;
   return (*this);
   }

/*
* Decode a small BER encoded INTEGER
*/
BER_Decoder& BER_Decoder::decode(size_t& out,
                                 ASN1_Tag type_tag, ASN1_Tag class_tag)
   {
   BigInt integer;
   decode(integer, type_tag, class_tag);

   if(integer.bits() > 32)
      throw BER_Decoding_Error("Decoded integer value larger than expected");

   out = 0;
   for(size_t i = 0; i != 4; ++i)
      out = (out << 8) | integer.byte_at(3-i);

   return (*this);
   }

/*
* Decode a small BER encoded INTEGER
*/
u64bit BER_Decoder::decode_constrained_integer(ASN1_Tag type_tag,
                                               ASN1_Tag class_tag,
                                               size_t T_bytes)
   {
   if(T_bytes > 8)
      throw BER_Decoding_Error("Can't decode small integer over 8 bytes");

   BigInt integer;
   decode(integer, type_tag, class_tag);

   if(integer.bits() > 8*T_bytes)
      throw BER_Decoding_Error("Decoded integer value larger than expected");

   u64bit out = 0;
   for(size_t i = 0; i != 8; ++i)
      out = (out << 8) | integer.byte_at(8-i);
   return out;
   }

/*
* Decode a BER encoded INTEGER
*/
BER_Decoder& BER_Decoder::decode(BigInt& out,
                                 ASN1_Tag type_tag, ASN1_Tag class_tag)
   {
   BER_Object obj = get_next_object();
   obj.assert_is_a(type_tag, class_tag);

   if(obj.value.empty())
      out = 0;
   else
      {
      const bool negative = (obj.value[0] & 0x80) ? true : false;

      if(negative)
         {
         for(size_t i = obj.value.size(); i > 0; --i)
            if(obj.value[i-1]--)
               break;
         for(size_t i = 0; i != obj.value.size(); ++i)
            obj.value[i] = ~obj.value[i];
         }

      out = BigInt(&obj.value[0], obj.value.size());

      if(negative)
         out.flip_sign();
      }

   return (*this);
   }

/*
* BER decode a BIT STRING or OCTET STRING
*/
BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& out, ASN1_Tag real_type)
   {
   return decode(out, real_type, real_type, UNIVERSAL);
   }

/*
* BER decode a BIT STRING or OCTET STRING
*/
BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& buffer,
                                 ASN1_Tag real_type,
                                 ASN1_Tag type_tag, ASN1_Tag class_tag)
   {
   if(real_type != OCTET_STRING && real_type != BIT_STRING)
      throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type);

   BER_Object obj = get_next_object();
   obj.assert_is_a(type_tag, class_tag);

   if(real_type == OCTET_STRING)
      buffer = obj.value;
   else
      {
      if(obj.value[0] >= 8)
         throw BER_Decoding_Error("Bad number of unused bits in BIT STRING");

      buffer.resize(obj.value.size() - 1);
      copy_mem(&buffer[0], &obj.value[1], obj.value.size() - 1);
      }
   return (*this);
   }

/*
* Decode an OPTIONAL string type
*/
BER_Decoder& BER_Decoder::decode_optional_string(MemoryRegion<byte>& out,
                                                 ASN1_Tag real_type,
                                                 u16bit type_no)
   {
   BER_Object obj = get_next_object();

   ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no);

   out.clear();
   push_back(obj);

   if(obj.type_tag == type_tag && obj.class_tag == CONTEXT_SPECIFIC)
      decode(out, real_type, type_tag, CONTEXT_SPECIFIC);

   return (*this);
   }

}
<commit_msg>This should always have reported what it saw and expected<commit_after>/*
* BER Decoder
* (C) 1999-2008 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/ber_dec.h>
#include <botan/bigint.h>
#include <botan/get_byte.h>

namespace Botan {

namespace {

/*
* BER decode an ASN.1 type tag
*/
size_t decode_tag(DataSource* ber, ASN1_Tag& type_tag, ASN1_Tag& class_tag)
   {
   byte b;
   if(!ber->read_byte(b))
      {
      class_tag = type_tag = NO_OBJECT;
      return 0;
      }

   if((b & 0x1F) != 0x1F)
      {
      type_tag = ASN1_Tag(b & 0x1F);
      class_tag = ASN1_Tag(b & 0xE0);
      return 1;
      }

   size_t tag_bytes = 1;
   class_tag = ASN1_Tag(b & 0xE0);

   size_t tag_buf = 0;
   while(true)
      {
      if(!ber->read_byte(b))
         throw BER_Decoding_Error("Long-form tag truncated");
      if(tag_buf & 0xFF000000)
         throw BER_Decoding_Error("Long-form tag overflowed 32 bits");
      ++tag_bytes;
      tag_buf = (tag_buf << 7) | (b & 0x7F);
      if((b & 0x80) == 0) break;
      }
   type_tag = ASN1_Tag(tag_buf);
   return tag_bytes;
   }

/*
* Find the EOC marker
*/
size_t find_eoc(DataSource*);

/*
* BER decode an ASN.1 length field
*/
size_t decode_length(DataSource* ber, size_t& field_size)
   {
   byte b;
   if(!ber->read_byte(b))
      throw BER_Decoding_Error("Length field not found");
   field_size = 1;
   if((b & 0x80) == 0)
      return b;

   field_size += (b & 0x7F);
   if(field_size == 1) return find_eoc(ber);
   if(field_size > 5)
      throw BER_Decoding_Error("Length field is too large");

   size_t length = 0;

   for(size_t i = 0; i != field_size - 1; ++i)
      {
      if(get_byte(0, length) != 0)
         throw BER_Decoding_Error("Field length overflow");
      if(!ber->read_byte(b))
         throw BER_Decoding_Error("Corrupted length field");
      length = (length << 8) | b;
      }
   return length;
   }

/*
* BER decode an ASN.1 length field
*/
size_t decode_length(DataSource* ber)
   {
   size_t dummy;
   return decode_length(ber, dummy);
   }

/*
* Find the EOC marker
*/
size_t find_eoc(DataSource* ber)
   {
   SecureVector<byte> buffer(DEFAULT_BUFFERSIZE), data;

   while(true)
      {
      const size_t got = ber->peek(&buffer[0], buffer.size(), data.size());
      if(got == 0)
         break;

      data += std::make_pair(&buffer[0], got);
      }

   DataSource_Memory source(data);
   data.clear();

   size_t length = 0;
   while(true)
      {
      ASN1_Tag type_tag, class_tag;
      size_t tag_size = decode_tag(&source, type_tag, class_tag);
      if(type_tag == NO_OBJECT)
         break;

      size_t length_size = 0;
      size_t item_size = decode_length(&source, length_size);
      source.discard_next(item_size);

      length += item_size + length_size + tag_size;

      if(type_tag == EOC)
         break;
      }
   return length;
   }

}

/*
* Check a type invariant on BER data
*/
void BER_Object::assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag)
   {
   if(this->type_tag != type_tag || this->class_tag != class_tag)
      throw BER_Decoding_Error("Tag mismatch when decoding got " +
                               to_string(this->type_tag) + "/" +
                               to_string(this->class_tag) + " expected " +
                               to_string(type_tag) + "/" +
                               to_string(class_tag));
   }

/*
* Check if more objects are there
*/
bool BER_Decoder::more_items() const
   {
   if(source->end_of_data() && (pushed.type_tag == NO_OBJECT))
      return false;
   return true;
   }

/*
* Verify that no bytes remain in the source
*/
BER_Decoder& BER_Decoder::verify_end()
   {
   if(!source->end_of_data() || (pushed.type_tag != NO_OBJECT))
      throw Invalid_State("BER_Decoder::verify_end called, but data remains");
   return (*this);
   }

/*
* Save all the bytes remaining in the source
*/
BER_Decoder& BER_Decoder::raw_bytes(MemoryRegion<byte>& out)
   {
   out.clear();
   byte buf;
   while(source->read_byte(buf))
      out.push_back(buf);
   return (*this);
   }

/*
* Discard all the bytes remaining in the source
*/
BER_Decoder& BER_Decoder::discard_remaining()
   {
   byte buf;
   while(source->read_byte(buf))
      ;
   return (*this);
   }

/*
* Return the BER encoding of the next object
*/
BER_Object BER_Decoder::get_next_object()
   {
   BER_Object next;

   if(pushed.type_tag != NO_OBJECT)
      {
      next = pushed;
      pushed.class_tag = pushed.type_tag = NO_OBJECT;
      return next;
      }

   decode_tag(source, next.type_tag, next.class_tag);
   if(next.type_tag == NO_OBJECT)
      return next;

   size_t length = decode_length(source);
   next.value.resize(length);
   if(source->read(&next.value[0], length) != length)
      throw BER_Decoding_Error("Value truncated");

   if(next.type_tag == EOC && next.class_tag == UNIVERSAL)
      return get_next_object();

   return next;
   }

/*
* Push a object back into the stream
*/
void BER_Decoder::push_back(const BER_Object& obj)
   {
   if(pushed.type_tag != NO_OBJECT)
      throw Invalid_State("BER_Decoder: Only one push back is allowed");
   pushed = obj;
   }

/*
* Begin decoding a CONSTRUCTED type
*/
BER_Decoder BER_Decoder::start_cons(ASN1_Tag type_tag,
                                    ASN1_Tag class_tag)
   {
   BER_Object obj = get_next_object();
   obj.assert_is_a(type_tag, ASN1_Tag(class_tag | CONSTRUCTED));

   BER_Decoder result(&obj.value[0], obj.value.size());
   result.parent = this;
   return result;
   }

/*
* Finish decoding a CONSTRUCTED type
*/
BER_Decoder& BER_Decoder::end_cons()
   {
   if(!parent)
      throw Invalid_State("BER_Decoder::end_cons called with NULL parent");
   if(!source->end_of_data())
      throw Decoding_Error("BER_Decoder::end_cons called with data left");
   return (*parent);
   }

/*
* BER_Decoder Constructor
*/
BER_Decoder::BER_Decoder(DataSource& src)
   {
   source = &src;
   owns = false;
   pushed.type_tag = pushed.class_tag = NO_OBJECT;
   parent = 0;
   }

/*
* BER_Decoder Constructor
 */
BER_Decoder::BER_Decoder(const byte data[], size_t length)
   {
   source = new DataSource_Memory(data, length);
   owns = true;
   pushed.type_tag = pushed.class_tag = NO_OBJECT;
   parent = 0;
   }

/*
* BER_Decoder Constructor
*/
BER_Decoder::BER_Decoder(const MemoryRegion<byte>& data)
   {
   source = new DataSource_Memory(data);
   owns = true;
   pushed.type_tag = pushed.class_tag = NO_OBJECT;
   parent = 0;
   }

/*
* BER_Decoder Copy Constructor
*/
BER_Decoder::BER_Decoder(const BER_Decoder& other)
   {
   source = other.source;
   owns = false;
   if(other.owns)
      {
      other.owns = false;
      owns = true;
      }
   pushed.type_tag = pushed.class_tag = NO_OBJECT;
   parent = other.parent;
   }

/*
* BER_Decoder Destructor
*/
BER_Decoder::~BER_Decoder()
   {
   if(owns)
      delete source;
   source = 0;
   }

/*
* Request for an object to decode itself
*/
BER_Decoder& BER_Decoder::decode(ASN1_Object& obj)
   {
   obj.decode_from(*this);
   return (*this);
   }

/*
* Decode a BER encoded NULL
*/
BER_Decoder& BER_Decoder::decode_null()
   {
   BER_Object obj = get_next_object();
   obj.assert_is_a(NULL_TAG, UNIVERSAL);
   if(obj.value.size())
      throw BER_Decoding_Error("NULL object had nonzero size");
   return (*this);
   }

/*
* Decode a BER encoded BOOLEAN
*/
BER_Decoder& BER_Decoder::decode(bool& out)
   {
   return decode(out, BOOLEAN, UNIVERSAL);
   }

/*
* Decode a small BER encoded INTEGER
*/
BER_Decoder& BER_Decoder::decode(size_t& out)
   {
   return decode(out, INTEGER, UNIVERSAL);
   }

/*
* Decode a BER encoded INTEGER
*/
BER_Decoder& BER_Decoder::decode(BigInt& out)
   {
   return decode(out, INTEGER, UNIVERSAL);
   }

BER_Decoder& BER_Decoder::decode_octet_string_bigint(BigInt& out)
   {
   SecureVector<byte> out_vec;
   decode(out_vec, OCTET_STRING);
   out = BigInt::decode(&out_vec[0], out_vec.size());
   return (*this);
   }

/*
* Decode a BER encoded BOOLEAN
*/
BER_Decoder& BER_Decoder::decode(bool& out,
                                 ASN1_Tag type_tag, ASN1_Tag class_tag)
   {
   BER_Object obj = get_next_object();
   obj.assert_is_a(type_tag, class_tag);

   if(obj.value.size() != 1)
      throw BER_Decoding_Error("BER boolean value had invalid size");

   out = (obj.value[0]) ? true : false;
   return (*this);
   }

/*
* Decode a small BER encoded INTEGER
*/
BER_Decoder& BER_Decoder::decode(size_t& out,
                                 ASN1_Tag type_tag, ASN1_Tag class_tag)
   {
   BigInt integer;
   decode(integer, type_tag, class_tag);

   if(integer.bits() > 32)
      throw BER_Decoding_Error("Decoded integer value larger than expected");

   out = 0;
   for(size_t i = 0; i != 4; ++i)
      out = (out << 8) | integer.byte_at(3-i);

   return (*this);
   }

/*
* Decode a small BER encoded INTEGER
*/
u64bit BER_Decoder::decode_constrained_integer(ASN1_Tag type_tag,
                                               ASN1_Tag class_tag,
                                               size_t T_bytes)
   {
   if(T_bytes > 8)
      throw BER_Decoding_Error("Can't decode small integer over 8 bytes");

   BigInt integer;
   decode(integer, type_tag, class_tag);

   if(integer.bits() > 8*T_bytes)
      throw BER_Decoding_Error("Decoded integer value larger than expected");

   u64bit out = 0;
   for(size_t i = 0; i != 8; ++i)
      out = (out << 8) | integer.byte_at(8-i);
   return out;
   }

/*
* Decode a BER encoded INTEGER
*/
BER_Decoder& BER_Decoder::decode(BigInt& out,
                                 ASN1_Tag type_tag, ASN1_Tag class_tag)
   {
   BER_Object obj = get_next_object();
   obj.assert_is_a(type_tag, class_tag);

   if(obj.value.empty())
      out = 0;
   else
      {
      const bool negative = (obj.value[0] & 0x80) ? true : false;

      if(negative)
         {
         for(size_t i = obj.value.size(); i > 0; --i)
            if(obj.value[i-1]--)
               break;
         for(size_t i = 0; i != obj.value.size(); ++i)
            obj.value[i] = ~obj.value[i];
         }

      out = BigInt(&obj.value[0], obj.value.size());

      if(negative)
         out.flip_sign();
      }

   return (*this);
   }

/*
* BER decode a BIT STRING or OCTET STRING
*/
BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& out, ASN1_Tag real_type)
   {
   return decode(out, real_type, real_type, UNIVERSAL);
   }

/*
* BER decode a BIT STRING or OCTET STRING
*/
BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& buffer,
                                 ASN1_Tag real_type,
                                 ASN1_Tag type_tag, ASN1_Tag class_tag)
   {
   if(real_type != OCTET_STRING && real_type != BIT_STRING)
      throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type);

   BER_Object obj = get_next_object();
   obj.assert_is_a(type_tag, class_tag);

   if(real_type == OCTET_STRING)
      buffer = obj.value;
   else
      {
      if(obj.value[0] >= 8)
         throw BER_Decoding_Error("Bad number of unused bits in BIT STRING");

      buffer.resize(obj.value.size() - 1);
      copy_mem(&buffer[0], &obj.value[1], obj.value.size() - 1);
      }
   return (*this);
   }

/*
* Decode an OPTIONAL string type
*/
BER_Decoder& BER_Decoder::decode_optional_string(MemoryRegion<byte>& out,
                                                 ASN1_Tag real_type,
                                                 u16bit type_no)
   {
   BER_Object obj = get_next_object();

   ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no);

   out.clear();
   push_back(obj);

   if(obj.type_tag == type_tag && obj.class_tag == CONTEXT_SPECIFIC)
      decode(out, real_type, type_tag, CONTEXT_SPECIFIC);

   return (*this);
   }

}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <random>

#include "random.h"

static std::mt19937_64 random_engine;

void initRandom()
{
    random_engine.seed(time(NULL));
}

float random(float fmin, float fmax)
{
    return std::uniform_real_distribution<>(fmin, fmax)(random_engine);
}

int irandom(int imin, int imax)
{
    return std::uniform_int_distribution<>(imin, imax)(random_engine);
}
<commit_msg>Update random.cpp (#98)<commit_after>#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <random>

#include "random.h"

static std::mt19937_64 random_engine;

void initRandom()
{
    random_engine.seed(time(NULL));
}

float random(float fmin, float fmax)
{
    return std::uniform_real_distribution<float>(fmin, fmax)(random_engine);
}

int irandom(int imin, int imax)
{
    return std::uniform_int_distribution<>(imin, imax)(random_engine);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __BASE_BITUNION_HH__
#define __BASE_BITUNION_HH__

#include <inttypes.h>
#include "base/bitfield.hh"

//	The following implements the BitUnion system of defining bitfields
//on top of an underlying class. This is done through the pervasive use of
//both named and unnamed unions which all contain the same actual storage.
//Since they're unioned with each other, all of these storage locations
//overlap. This allows all of the bitfields to manipulate the same data
//without having to have access to each other. More details are provided with
//the individual components.

//This namespace is for classes which implement the backend of the BitUnion
//stuff. Don't use any of these directly, except for the Bitfield classes in
//the *BitfieldTypes class(es).
namespace BitfieldBackend
{
    //A base class for all bitfields. It instantiates the actual storage,
    //and provides getBits and setBits functions for manipulating it. The
    //Data template parameter is type of the underlying storage.
    template<class Data>
    class BitfieldBase
    {
      protected:
        Data __data;

        //This function returns a range of bits from the underlying storage.
        //It relies on the "bits" function above. It's the user's
        //responsibility to make sure that there is a properly overloaded
        //version of this function for whatever type they want to overlay.
        inline uint64_t
        getBits(int first, int last) const
        {
            return bits(__data, first, last);
        }

        //Similar to the above, but for settings bits with replaceBits.
        inline void
        setBits(int first, int last, uint64_t val)
        {
            replaceBits(__data, first, last, val);
        }
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class RegularBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class Bitfield : public BitfieldBase<Type>
        {
          public:
            operator uint64_t () const
            {
                return this->getBits(first, last);
            }

            uint64_t
            operator=(const uint64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class BitfieldRO : public Bitfield<first, last>
        {
          private:
            uint64_t
            operator=(const uint64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class BitfieldWO : public Bitfield<first, last>
        {
          private:
            operator uint64_t () const;

          public:
            using Bitfield<first, last>::operator=;
        };
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class SignedBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class SignedBitfield : public BitfieldBase<Type>
        {
          public:
            operator int64_t () const
            {
                return sext<first - last + 1>(this->getBits(first, last));
            }

            int64_t
            operator=(const int64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class SignedBitfieldRO : public SignedBitfield<first, last>
        {
          private:
            int64_t
            operator=(const int64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class SignedBitfieldWO : public SignedBitfield<first, last>
        {
          private:
            operator int64_t () const;

          public:
            int64_t operator=(const int64_t _data)
            {
                *((SignedBitfield<first, last> *)this) = _data;
                return _data;
            }
        };
    };

    template<class Type>
    class BitfieldTypes : public RegularBitfieldTypes<Type>,
                          public SignedBitfieldTypes<Type>
    {};

    //When a BitUnion is set up, an underlying class is created which holds
    //the actual union. This class then inherits from it, and provids the
    //implementations for various operators. Setting things up this way
    //prevents having to redefine these functions in every different BitUnion
    //type. More operators could be implemented in the future, as the need
    //arises.
    template <class Type, class Base>
    class BitUnionOperators : public Base
    {
      public:
        operator Type () const
        {
            return Base::__data;
        }

        Type
        operator=(const Type & _data)
        {
            Base::__data = _data;
            return _data;
        }

        bool
        operator<(const Base & base) const
        {
            return Base::__data < base.__data;
        }

        bool
        operator==(const Base & base) const
        {
            return Base::__data == base.__data;
        }
    };
}

//This macro is a backend for other macros that specialize it slightly.
//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
//sticks the class which has the actual union in it, which
//BitfieldOperators above inherits from. Putting these classes in a special
//namespace ensures that there will be no collisions with other names as long
//as the BitUnion names themselves are all distinct and nothing else uses
//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
//creates a typedef of the "type" parameter called __DataType. This allows
//the type to propagate outside of the macro itself in a controlled way.
//Finally, the base storage is defined which BitfieldOperators will refer to
//in the operators it defines. This macro is intended to be followed by
//bitfield definitions which will end up inside it's union. As explained
//above, these is overlayed the __data member in its entirety by each of the
//bitfields which are defined in the union, creating shared storage with no
//overhead.
#define __BitUnion(type, name) \
    namespace BitfieldUnderlyingClasses \
    { \
        class name; \
    } \
    class BitfieldUnderlyingClasses::name : \
        public BitfieldBackend::BitfieldTypes<type> \
    { \
      public: \
        typedef type __DataType; \
        union { \
            type __data;\

//This closes off the class and union started by the above macro. It is
//followed by a typedef which makes "name" refer to a BitfieldOperator
//class inheriting from the class and union just defined, which completes
//building up the type for the user.
#define EndBitUnion(name) \
        }; \
    }; \
    typedef BitfieldBackend::BitUnionOperators< \
        BitfieldUnderlyingClasses::name::__DataType, \
        BitfieldUnderlyingClasses::name> name;

//This sets up a bitfield which has other bitfields nested inside of it. The
//__data member functions like the "underlying storage" of the top level
//BitUnion. Like everything else, it overlays with the top level storage, so
//making it a regular bitfield type makes the entire thing function as a
//regular bitfield when referred to by itself.
#define __SubBitUnion(fieldType, first, last, name) \
    class : public BitfieldBackend::BitfieldTypes<__DataType> \
    { \
      public: \
        union { \
            fieldType<first, last> __data;

//This closes off the union created above and gives it a name. Unlike the top
//level BitUnion, we're interested in creating an object instead of a type.
//The operators are defined in the macro itself instead of a class for
//technical reasons. If someone determines a way to move them to one, please
//do so.
#define EndSubBitUnion(name) \
        }; \
        inline operator const __DataType () \
        { return __data; } \
        \
        inline const __DataType operator = (const __DataType & _data) \
        { __data = _data; } \
    } name;

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SubBitUnion(name, first, last) \
    __SubBitUnion(Bitfield, first, last, name)

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SignedSubBitUnion(name, first, last) \
    __SubBitUnion(SignedBitfield, first, last, name)

//Use this to define an arbitrary type overlayed with bitfields.
#define BitUnion(type, name) __BitUnion(type, name)

//Use this to define conveniently sized values overlayed with bitfields.
#define BitUnion64(name) __BitUnion(uint64_t, name)
#define BitUnion32(name) __BitUnion(uint32_t, name)
#define BitUnion16(name) __BitUnion(uint16_t, name)
#define BitUnion8(name) __BitUnion(uint8_t, name)

#endif // __BASE_BITUNION_HH__
<commit_msg>Add a conversion constructor so a bitunion can be initialized to a value. Previously, the bitunion would need to be declared and then assigned to separately.<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __BASE_BITUNION_HH__
#define __BASE_BITUNION_HH__

#include <inttypes.h>
#include "base/bitfield.hh"

//	The following implements the BitUnion system of defining bitfields
//on top of an underlying class. This is done through the pervasive use of
//both named and unnamed unions which all contain the same actual storage.
//Since they're unioned with each other, all of these storage locations
//overlap. This allows all of the bitfields to manipulate the same data
//without having to have access to each other. More details are provided with
//the individual components.

//This namespace is for classes which implement the backend of the BitUnion
//stuff. Don't use any of these directly, except for the Bitfield classes in
//the *BitfieldTypes class(es).
namespace BitfieldBackend
{
    //A base class for all bitfields. It instantiates the actual storage,
    //and provides getBits and setBits functions for manipulating it. The
    //Data template parameter is type of the underlying storage.
    template<class Data>
    class BitfieldBase
    {
      protected:
        Data __data;

        //This function returns a range of bits from the underlying storage.
        //It relies on the "bits" function above. It's the user's
        //responsibility to make sure that there is a properly overloaded
        //version of this function for whatever type they want to overlay.
        inline uint64_t
        getBits(int first, int last) const
        {
            return bits(__data, first, last);
        }

        //Similar to the above, but for settings bits with replaceBits.
        inline void
        setBits(int first, int last, uint64_t val)
        {
            replaceBits(__data, first, last, val);
        }
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class RegularBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class Bitfield : public BitfieldBase<Type>
        {
          public:
            operator uint64_t () const
            {
                return this->getBits(first, last);
            }

            uint64_t
            operator=(const uint64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class BitfieldRO : public Bitfield<first, last>
        {
          private:
            uint64_t
            operator=(const uint64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class BitfieldWO : public Bitfield<first, last>
        {
          private:
            operator uint64_t () const;

          public:
            using Bitfield<first, last>::operator=;
        };
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class SignedBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class SignedBitfield : public BitfieldBase<Type>
        {
          public:
            operator int64_t () const
            {
                return sext<first - last + 1>(this->getBits(first, last));
            }

            int64_t
            operator=(const int64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class SignedBitfieldRO : public SignedBitfield<first, last>
        {
          private:
            int64_t
            operator=(const int64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class SignedBitfieldWO : public SignedBitfield<first, last>
        {
          private:
            operator int64_t () const;

          public:
            int64_t operator=(const int64_t _data)
            {
                *((SignedBitfield<first, last> *)this) = _data;
                return _data;
            }
        };
    };

    template<class Type>
    class BitfieldTypes : public RegularBitfieldTypes<Type>,
                          public SignedBitfieldTypes<Type>
    {};

    //When a BitUnion is set up, an underlying class is created which holds
    //the actual union. This class then inherits from it, and provids the
    //implementations for various operators. Setting things up this way
    //prevents having to redefine these functions in every different BitUnion
    //type. More operators could be implemented in the future, as the need
    //arises.
    template <class Type, class Base>
    class BitUnionOperators : public Base
    {
      public:
        BitUnionOperators(Type & _data)
        {
            Base::__data = _data;
        }

        BitUnionOperators() {}

        operator Type () const
        {
            return Base::__data;
        }

        Type
        operator=(const Type & _data)
        {
            Base::__data = _data;
            return _data;
        }

        bool
        operator<(const Base & base) const
        {
            return Base::__data < base.__data;
        }

        bool
        operator==(const Base & base) const
        {
            return Base::__data == base.__data;
        }
    };
}

//This macro is a backend for other macros that specialize it slightly.
//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
//sticks the class which has the actual union in it, which
//BitfieldOperators above inherits from. Putting these classes in a special
//namespace ensures that there will be no collisions with other names as long
//as the BitUnion names themselves are all distinct and nothing else uses
//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
//creates a typedef of the "type" parameter called __DataType. This allows
//the type to propagate outside of the macro itself in a controlled way.
//Finally, the base storage is defined which BitfieldOperators will refer to
//in the operators it defines. This macro is intended to be followed by
//bitfield definitions which will end up inside it's union. As explained
//above, these is overlayed the __data member in its entirety by each of the
//bitfields which are defined in the union, creating shared storage with no
//overhead.
#define __BitUnion(type, name) \
    namespace BitfieldUnderlyingClasses \
    { \
        class name; \
    } \
    class BitfieldUnderlyingClasses::name : \
        public BitfieldBackend::BitfieldTypes<type> \
    { \
      public: \
        typedef type __DataType; \
        union { \
            type __data;\

//This closes off the class and union started by the above macro. It is
//followed by a typedef which makes "name" refer to a BitfieldOperator
//class inheriting from the class and union just defined, which completes
//building up the type for the user.
#define EndBitUnion(name) \
        }; \
    }; \
    typedef BitfieldBackend::BitUnionOperators< \
        BitfieldUnderlyingClasses::name::__DataType, \
        BitfieldUnderlyingClasses::name> name;

//This sets up a bitfield which has other bitfields nested inside of it. The
//__data member functions like the "underlying storage" of the top level
//BitUnion. Like everything else, it overlays with the top level storage, so
//making it a regular bitfield type makes the entire thing function as a
//regular bitfield when referred to by itself.
#define __SubBitUnion(fieldType, first, last, name) \
    class : public BitfieldBackend::BitfieldTypes<__DataType> \
    { \
      public: \
        union { \
            fieldType<first, last> __data;

//This closes off the union created above and gives it a name. Unlike the top
//level BitUnion, we're interested in creating an object instead of a type.
//The operators are defined in the macro itself instead of a class for
//technical reasons. If someone determines a way to move them to one, please
//do so.
#define EndSubBitUnion(name) \
        }; \
        inline operator const __DataType () \
        { return __data; } \
        \
        inline const __DataType operator = (const __DataType & _data) \
        { __data = _data; } \
    } name;

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SubBitUnion(name, first, last) \
    __SubBitUnion(Bitfield, first, last, name)

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SignedSubBitUnion(name, first, last) \
    __SubBitUnion(SignedBitfield, first, last, name)

//Use this to define an arbitrary type overlayed with bitfields.
#define BitUnion(type, name) __BitUnion(type, name)

//Use this to define conveniently sized values overlayed with bitfields.
#define BitUnion64(name) __BitUnion(uint64_t, name)
#define BitUnion32(name) __BitUnion(uint32_t, name)
#define BitUnion16(name) __BitUnion(uint16_t, name)
#define BitUnion8(name) __BitUnion(uint8_t, name)

#endif // __BASE_BITUNION_HH__
<|endoftext|>


<commit_before>// dcd-recog.cc
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright 2013-2014 Yandex LLC
// Copyright 2014 Paul R. Dixon
// \file
// Main decoding command

#include <fstream>
#include <iostream>
#include <string>

#include <fst/extensions/far/far.h>

#include <dcd/clevel-decoder.h>
#include <dcd/cascade.h>
#include <dcd/config.h>
#include <dcd/cpu-stats.h>
#include <dcd/generic-transition-model.h>
#include <dcd/hmm-transition-model.h>
#include <dcd/kaldi-lattice-arc.h>
#include <dcd/lattice.h>
#include <dcd/simple-lattice.h>
#include <dcd/log.h>
#include <dcd/memdebug.h>
#include <dcd/utils.h>

using namespace std;
using namespace dcd;
using namespace fst;

string lingware;
string tm_type = "generic";
string word_symbols_file;
string logfile = "/dev/stderr";

//Simple table writer for Kaldi FST tables
template <class A>
class TableWriter {
 public:
  typedef A Arc;

  // Creates a new (empty) FST table; returns NULL on error.
  static TableWriter* Create(const string& filename) {
    ofstream* strm = new ofstream(filename.c_str());
    if (strm->is_open())
      return new TableWriter(strm);
    return 0;
  }
  virtual void Add(const string& key, const Fst<A>& fst) {
    (*strm_) << key;
    (*strm_) << char(32);
    fst.Write(*strm_, FstWriteOptions());
  }

  virtual ~TableWriter() {
    if (strm_)
      delete strm_;
  }

 private:
  TableWriter(ostream* strm) : strm_(strm) { }
  ostream* strm_;
  DISALLOW_COPY_AND_ASSIGN(TableWriter);
};

//L is the decoder lattice type
//B is the output lattice semiring
template<class TransModel, class L, class B>
int CLevelDecoderMain(ParseOptions &po, SearchOptions *opts,
    const string &word_symbols_file) {
  typedef typename TransModel::FrontEnd FrontEnd;
  typedef CLevelDecoder<StdFst, TransModel, L> Decoder;
  PROFILE_BEGIN(ModelLoad);
  string trans_model_rs = po.GetArg(1);
  string fst_rs = po.GetArg(2);
  string feat_rs = po.GetArg(3);
  string out_ws = po.GetArg(4);
  Logger logger("dcd-recog", std::cerr, opts->colorize);
  logger(INFO) << "Decoder type : " << Decoder::Type();

  FarWriter<B>* farwriter =
    FarWriter<B>::Create(out_ws, fst::FAR_DEFAULT);
  if (!farwriter)
    logger(FATAL) << "Failed to create far writer : " << out_ws;

  cerr << endl;

  Cascade<StdArc>* cascade = 0;
  TransModel* trans_model = 0;
  SymbolTable* wordsyms  = 0;

  logger(INFO) << "Attempting to read fst " << fst_rs;
  cascade = Cascade<StdArc>::Read(fst_rs);
  if (!cascade)
    logger(FATAL) << "Failed to load fst from file : " << fst_rs;
  cerr << endl;

  logger(INFO) << "Attempting to read transition model " <<  trans_model_rs;
  trans_model = TransModel::ReadFsts(trans_model_rs,
                                                 opts->trans_scale);
  trans_model->DumpInfo(logger);
  if (!trans_model)
    logger(FATAL) << "Failed to read transition model";
  wordsyms = 0;
  if (!word_symbols_file.empty()) {
    logger(INFO) << "Attempting to read word symbols from "
      << word_symbols_file;
    wordsyms = SymbolTable::ReadText(word_symbols_file);
    opts->wordsyms = wordsyms;
  }
  PROFILE_END();

  logger(INFO) << "Attempting to read features from " << feat_rs;
  SequentialBaseFloatMatrixReader feature_reader(feat_rs, true);
  Timer timer;
  int total_num_frames = 0;
  double total_time = 0.0f;

  if (g_dcd_memdebug_enabled)
    logger(INFO) << "Memory allocated before decoding : "
                 <<  g_dcd_current_num_allocated / kMegaByte << " MB";

  CPUStats cpustats;
  //These need to be here as the each call returns the usage between
  //calls to the function
  cpustats.GetCurrentProcessCPULoad();
  cpustats.GetSystemCPULoad();

  StdFst *fst = 0;
  Decoder *decoder = 0;
  int num = 0;
  for (; !feature_reader.Done(); feature_reader.Next(), ++num) {
    if (num % opts->fst_reset_period == 0) {
      logger(INFO) << "Rebuilding cascade and decoder at utterance : " << num;
      if (decoder) {
        delete decoder;
        decoder = 0;
      }
      fst = cascade->Rebuild();
      if (!fst)
        logger(FATAL) << "Cascade build failed";
      if (fst->Start() == kNoStateId)
        logger(FATAL) << "Fst does not have a valid start state";
      decoder = new Decoder(fst, trans_model, *opts);
    }
    const string& key = feature_reader.Key();
    opts->source = key;
    const Matrix<float>& features = feature_reader.Value();
    int frame_count = features.NumRows();
    logger(INFO) << "Decoding features : " << key << ", # frames "
                 << frame_count;

    FrontEnd frontend(features, 1.0f);
    VectorFst<B> ofst;
    VectorFst<B> lattice;
    trans_model->SetInput(&frontend, *opts);
    timer.Reset();
    float cost = decoder->Decode(trans_model, *opts, &ofst,
        opts->gen_lattice ? &lattice : 0);
    double elapsed = timer.Elapsed();
    stringstream farkey;
    farkey << setfill('0') << setw(5) << num << "_" << key;
    farwriter->Add(farkey.str(), opts->gen_lattice ? lattice : ofst);
    stringstream ss;
    int numwords = 0;
    for (StateIterator<Fst<B> > siter(ofst); !siter.Done(); siter.Next()) {
      ArcIterator<Fst<B> > aiter(ofst, siter.Value());
      if (!aiter.Done()) {
        const B &arc = aiter.Value();
        if (arc.olabel) {
          if (wordsyms) {
            ++numwords;
            const string &word = wordsyms->Find(arc.olabel);
            if (word.empty()) {
              logger(WARN) << "Missing word sym : " << arc.olabel;
              ss << "MISSING_WORD_SYM ";
            } else {
              ss << word << " ";
            }
          }
        }
      }
    }
    string recogstring = ss.str();
    ss.str("");

    ss << "Finished decoding : " << endl
       << "\t\t  Best cost : " << cost << endl
       << "\t\t  Average log-likelihood per frame : "
       << cost / frame_count << endl
       << "\t\t  Decoding time : " << elapsed << endl
       << "\t\t  RTF : " << (elapsed * 100.0 / frame_count) << endl
       << "\t\t  Number of words : " << numwords << endl
       << "\t\t  Recog result : (" << key << ") "
       << recogstring << endl
       << "\t\t  Process CPU load : "
       << cpustats.GetCurrentProcessCPULoad() << endl
       << "\t\t  System CPU load : "
       << cpustats.GetSystemCPULoad() << endl
       << "\t\t  Peak memory usage : "
       << GetPeakRSS() / (1024 * 1024) << " MB" << endl
       << "\t\t  Current memory usage : "
       << GetCurrentRSS() / (1024 * 1024) << " MB" << endl;
    if (g_dcd_memdebug_enabled)
      ss << "\t\t  Memory allocated after decoding : "
         <<  g_dcd_current_num_allocated / kMegaByte << " MB" << endl;
    logger(INFO) << ss.str();
    total_time += elapsed;
    total_num_frames += frame_count;
    feature_reader.FreeCurrent();
  }
  logger(INFO) << "Decoding summary : " << endl
    << "\t\t  Average RTF : "
    <<  total_time * 100 / total_num_frames << endl
    << "\t\t  Peak memory usage  : "
    << GetPeakRSS() / (1024 * 1024) << " MB" << endl
    << "\t\t  Total # of utterances : " << num << endl
    << "\t\t  Total # of frames : " << total_num_frames << endl
    << "\t\t  Total decoding time : " << total_time << endl;

  PROFILE_BEGIN(ModelCleanup);
  if (farwriter)
    delete farwriter;
  if (decoder)
    delete decoder;
  if (cascade)
    delete cascade;
  if (trans_model)
    delete trans_model;
  if (wordsyms)
    delete wordsyms;
  PROFILE_END();
  return 0;
}

DECLARE_int32(v);

struct DecodeMainEntryBase {

  explicit DecodeMainEntryBase(const string& desc = "") :
    desc_(desc) { }

  const string& Description() {
    return desc_;
  }

  virtual int Run(ParseOptions &po, SearchOptions *opts,
                  const string &word_symbols_file) = 0;

  virtual ~DecodeMainEntryBase() = 0;

  string desc_;
};

DecodeMainEntryBase::~DecodeMainEntryBase() {
}

template<class T, class L, class B>
struct DecodeMainEntry : public DecodeMainEntryBase {

  typedef CLevelDecoder<StdFst,T, L> D;

  DecodeMainEntry() : DecodeMainEntryBase(D::Type() + "_" + B::Type()) {
  }

  virtual int Run(ParseOptions &po, SearchOptions *opts,
                  const string &word_symbols_file) {
    return CLevelDecoderMain<T, L, B>(po, opts, word_symbols_file);
  }
};

unordered_map<string, DecodeMainEntryBase*> main_map;

void ClearMainRegister() {
  for (unordered_map<string, DecodeMainEntryBase*>::iterator it
      =  main_map.begin(); it != main_map.end(); ++it ) {
    delete it->second;
  }
  main_map.clear();
}

DecodeMainEntryBase* FindEntry(const string& key) {
  unordered_map<string, DecodeMainEntryBase*>::iterator it =
    main_map.find(key);
  if (it == main_map.end()) {
  #ifdef HAVEDL
    logger(INFO) << "Attempting to load shared object : " << key << "-dcd.so";
    void* handle = dlopen(key + "-dcd.so", RTLD_LAZY);
    if (!handle)
      logger(FATAL) << "FindEntry : " << dlerror();
    DecodeMainEntryBase* entry = FindEntry(key);
    if (!entry)
      logger(FATAL) <<"Entry lookup failed in : " << key << "-dcd.so";
    return entry;
  #endif
    return 0;
  } else {
    return it->second;
  }
}

template<class T, class L, class B>
struct DecodeMainRegisterer {
  explicit DecodeMainRegisterer(const string& name, const string& desc = "") {
    if (main_map.find(name) != main_map.end())
      LOG(FATAL)  << "Registered type already exists : " << name;
    main_map[name] = new DecodeMainEntry<T, L, B>;
  }
};

#define REGISTER_DECODER_MAIN(N, T, D, B, L) \
  static DecodeMainRegisterer<T<D>, L, B> \
    decode_registerer ## _ ## T ## _ ## D ## _ ## _ ## L ## B(N);

REGISTER_DECODER_MAIN("hmm_lattice", HMMTransitionModel,
    Decodable, StdArc, Lattice);

REGISTER_DECODER_MAIN("hmm_lattice_kaldi", HMMTransitionModel,
    Decodable, KaldiLatticeArc, Lattice);

REGISTER_DECODER_MAIN("hmm_simple", HMMTransitionModel,
    Decodable, StdArc, SimpleLattice);

REGISTER_DECODER_MAIN("generic_lattice", GenericTransitionModel,
    Decodable, StdArc, Lattice);

//REGISTER_DECODER_MAIN("hmm_hitstats", HMMTransitionModel,
//  SimpleDecodableHitStats, StdArc);

int main(int argc, char *argv[]) {
  PROFILE_FUNC();
  g_dcd_global_allocated = g_dcd_current_num_allocated;
  const char *usage = "Decode some speech\n"
        "Usage: dcd-recog [options] trans-model-in (fst-in|fsts-rspecifier) "
        "features-rspecifier far-wspecifier";

  PrintVersionInfo();
  cerr << endl;
  PrintMachineInfo();
  cerr << endl;
  cerr << "Program arguments : " << endl;
  ParseOptions po(usage);
  SearchOptions opts;
  po.Register("decoder_type", &tm_type, "Type of decoder to use");
  po.Register("word_symbols_table", &word_symbols_file, "");
  po.Register("lingware", &lingware, "");
  po.Register("logfile", &logfile, "/dev/stderr");
  /*po.Register("wfst");
  po.Register("trans_model");
  po.Register("input");
  po.Register("output");*/
  opts.Register(&po);
  po.Read(argc, argv);

  if (po.NumArgs() != 4) {
    po.PrintUsage();
    cerr << "Built-in decoder types : " << endl;
    for (unordered_map<string, DecodeMainEntryBase*>::iterator it
        =  main_map.begin(); it != main_map.end(); ++it ) {
      cerr << "  " << it->first << " : " << it->second->Description() << endl;
    }
    exit(1);
  }

  opts.Check();
  cerr << endl << "Search options : " << endl << opts << endl;

  DecodeMainEntryBase* runner = FindEntry(tm_type);
  if (!runner)
    logger(FATAL) << "Unknown decoder type : " << tm_type;
  runner->Run(po, &opts, word_symbols_file);

  ClearMainRegister();
  PrintMemorySummary();

  PROFILE_UPDATE(); // update all profiles
  PROFILE_OUTPUT(NULL); // print to terminal
}

<commit_msg>changed<commit_after>// dcd-recog.cc
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright 2013-2014 Yandex LLC
// Copyright 2014 Paul R. Dixon
// \file
// Main decoding command

#include <fstream>
#include <iostream>
#include <string>

#include <fst/extensions/far/far.h>

#include <dcd/clevel-decoder.h>
#include <dcd/cascade.h>
#include <dcd/config.h>
#include <dcd/cpu-stats.h>
#include <dcd/generic-transition-model.h>
#include <dcd/hmm-transition-model.h>
#include <dcd/kaldi-lattice-arc.h>
#include <dcd/lattice.h>
#include <dcd/simple-lattice.h>
#include <dcd/log.h>
#include <dcd/memdebug.h>
#include <dcd/utils.h>

using namespace std;
using namespace dcd;
using namespace fst;

string lingware;
string tm_type = "generic";
string word_symbols_file;
string logfile = "/dev/stderr";

//Simple table writer for Kaldi FST tables
template <class A>
class TableWriter {
 public:
  typedef A Arc;

  // Creates a new (empty) FST table; returns NULL on error.
  static TableWriter* Create(const string& filename) {
    ofstream* strm = new ofstream(filename.c_str());
    if (strm->is_open())
      return new TableWriter(strm);
    return 0;
  }
  virtual void Add(const string& key, const Fst<A>& fst) {
    (*strm_) << key;
    (*strm_) << char(32);
    fst.Write(*strm_, FstWriteOptions());
  }

  virtual ~TableWriter() {
    if (strm_)
      delete strm_;
  }

 private:
  TableWriter(ostream* strm) : strm_(strm) { }
  ostream* strm_;
  DISALLOW_COPY_AND_ASSIGN(TableWriter);
};

//L is the decoder lattice type
//B is the output lattice semiring
template<class TransModel, class L, class B>
int CLevelDecoderMain(ParseOptions &po, SearchOptions *opts,
    const string &word_symbols_file) {
  typedef typename TransModel::FrontEnd FrontEnd;
  typedef CLevelDecoder<StdFst, TransModel, L> Decoder;
  PROFILE_BEGIN(ModelLoad);
  string trans_model_rs = po.GetArg(1);
  string fst_rs = po.GetArg(2);
  string feat_rs = po.GetArg(3);
  string out_ws = po.GetArg(4);
  Logger logger("dcd-recog", std::cerr, opts->colorize);
  logger(INFO) << "Decoder type : " << Decoder::Type();

  FarWriter<B>* farwriter =
    FarWriter<B>::Create(out_ws, fst::FAR_DEFAULT);
  if (!farwriter)
    logger(FATAL) << "Failed to create far writer : " << out_ws;

  cerr << endl;

  Cascade<StdArc>* cascade = 0;
  TransModel* trans_model = 0;
  SymbolTable* wordsyms  = 0;

  logger(INFO) << "Attempting to read fst " << fst_rs;
  cascade = Cascade<StdArc>::Read(fst_rs);
  if (!cascade)
    logger(FATAL) << "Failed to load fst from file : " << fst_rs;
  cerr << endl;

  logger(INFO) << "Attempting to read transition model " <<  trans_model_rs;
  trans_model = TransModel::ReadFsts(trans_model_rs,
                                                 opts->trans_scale);
  trans_model->DumpInfo(logger);
  if (!trans_model)
    logger(FATAL) << "Failed to read transition model";
  wordsyms = 0;
  if (!word_symbols_file.empty()) {
    logger(INFO) << "Attempting to read word symbols from "
      << word_symbols_file;
    wordsyms = SymbolTable::ReadText(word_symbols_file);
    opts->wordsyms = wordsyms;
  }
  PROFILE_END();

  logger(INFO) << "Attempting to read features from " << feat_rs;
  SequentialBaseFloatMatrixReader feature_reader(feat_rs, true);
  Timer timer;
  int total_num_frames = 0;
  double total_time = 0.0f;

  if (g_dcd_memdebug_enabled)
    logger(INFO) << "Memory allocated before decoding : "
                 <<  g_dcd_current_num_allocated / kMegaByte << " MB";

  CPUStats cpustats;
  //These need to be here as the each call returns the usage between
  //calls to the function
  cpustats.GetCurrentProcessCPULoad();
  cpustats.GetSystemCPULoad();
  StdFst *fst = 0;
  Decoder *decoder = 0;
  int num = 0;
  for (; !feature_reader.Done(); feature_reader.Next(), ++num) {
    if (num % opts->fst_reset_period == 0) {
      logger(INFO) << "Rebuilding cascade and decoder at utterance : " << num;
      if (decoder) {
        delete decoder;
        decoder = 0;
      }
      fst = cascade->Rebuild();
      if (!fst)
        logger(FATAL) << "Cascade build failed";
      if (fst->Start() == kNoStateId)
        logger(FATAL) << "Fst does not have a valid start state";
      decoder = new Decoder(fst, trans_model, *opts);
    }
    const string& key = feature_reader.Key();
    opts->source = key;
    const Matrix<float>& features = feature_reader.Value();
    int frame_count = features.NumRows();
    logger(INFO) << "Decoding features : " << key << ", # frames "
                 << frame_count;

    FrontEnd frontend(features, 1.0f);
    VectorFst<B> ofst;
    VectorFst<B> lattice;
    trans_model->SetInput(&frontend, *opts);
    timer.Reset();
    float cost = decoder->Decode(trans_model, *opts, &ofst,
        opts->gen_lattice ? &lattice : 0);
    double elapsed = timer.Elapsed();
    stringstream farkey;
    farkey << setfill('0') << setw(5) << num << "_" << key;
    farwriter->Add(farkey.str(), opts->gen_lattice ? lattice : ofst);
    stringstream ss;
    int numwords = 0;
    for (StateIterator<Fst<B> > siter(ofst); !siter.Done(); siter.Next()) {
      ArcIterator<Fst<B> > aiter(ofst, siter.Value());
      if (!aiter.Done()) {
        const B &arc = aiter.Value();
        if (arc.olabel) {
          if (wordsyms) {
            ++numwords;
            const string &word = wordsyms->Find(arc.olabel);
            if (word.empty()) {
              logger(WARN) << "Missing word sym : " << arc.olabel;
              ss << "MISSING_WORD_SYM ";
            } else {
              ss << word << " ";
            }
          }
        }
      }
    }
    string recogstring = ss.str();
    ss.str("");

    ss << "Finished decoding : " << endl
       << "\t\t  Best cost : " << cost << endl
       << "\t\t  Average log-likelihood per frame : "
       << cost / frame_count << endl
       << "\t\t  Decoding time : " << elapsed << endl
       << "\t\t  RTF : " << (elapsed * 100.0 / frame_count) << endl
       << "\t\t  Number of words : " << numwords << endl
       << "\t\t  Recog result : (" << key << ") "
       << recogstring << endl
       << "\t\t  Process CPU load : "
       << cpustats.GetCurrentProcessCPULoad() << endl
       << "\t\t  System CPU load : "
       << cpustats.GetSystemCPULoad() << endl
       << "\t\t  Peak memory usage : "
       << GetPeakRSS() / (1024 * 1024) << " MB" << endl
       << "\t\t  Current memory usage : "
       << GetCurrentRSS() / (1024 * 1024) << " MB" << endl;
    if (g_dcd_memdebug_enabled)
      ss << "\t\t  Memory allocated after decoding : "
         <<  g_dcd_current_num_allocated / kMegaByte << " MB" << endl;
    logger(INFO) << ss.str();
    total_time += elapsed;
    total_num_frames += frame_count;
    feature_reader.FreeCurrent();
  }
  logger(INFO) << "Decoding summary : " << endl
    << "\t\t  Average RTF : "
    <<  total_time * 100 / total_num_frames << endl
    << "\t\t  Peak memory usage  : "
    << GetPeakRSS() / (1024 * 1024) << " MB" << endl
    << "\t\t  Total # of utterances : " << num << endl
    << "\t\t  Total # of frames : " << total_num_frames << endl
    << "\t\t  Total decoding time : " << total_time << endl;

  PROFILE_BEGIN(ModelCleanup);
  if (farwriter)
    delete farwriter;
  if (decoder)
    delete decoder;
  if (cascade)
    delete cascade;
  if (trans_model)
    delete trans_model;
  if (wordsyms)
    delete wordsyms;
  PROFILE_END();
  return 0;
}

DECLARE_int32(v);

struct DecodeMainEntryBase {

  explicit DecodeMainEntryBase(const string& desc = "") :
    desc_(desc) { }

  const string& Description() {
    return desc_;
  }

  virtual int Run(ParseOptions &po, SearchOptions *opts,
                  const string &word_symbols_file) = 0;

  virtual ~DecodeMainEntryBase() = 0;

  string desc_;
};

DecodeMainEntryBase::~DecodeMainEntryBase() {
}

template<class T, class L, class B>
struct DecodeMainEntry : public DecodeMainEntryBase {

  typedef CLevelDecoder<StdFst,T, L> D;

  DecodeMainEntry() : DecodeMainEntryBase(D::Type() + "_" + B::Type()) {
  }

  virtual int Run(ParseOptions &po, SearchOptions *opts,
                  const string &word_symbols_file) {
    return CLevelDecoderMain<T, L, B>(po, opts, word_symbols_file);
  }
};

unordered_map<string, DecodeMainEntryBase*> main_map;

void ClearMainRegister() {
  for (unordered_map<string, DecodeMainEntryBase*>::iterator it
      =  main_map.begin(); it != main_map.end(); ++it ) {
    delete it->second;
  }
  main_map.clear();
}

DecodeMainEntryBase* FindEntry(const string& key) {
  unordered_map<string, DecodeMainEntryBase*>::iterator it =
    main_map.find(key);
  if (it == main_map.end()) {
  #ifdef HAVEDL
    logger(INFO) << "Attempting to load shared object : " << key << "-dcd.so";
    void* handle = dlopen(key + "-dcd.so", RTLD_LAZY);
    if (!handle)
      logger(FATAL) << "FindEntry : " << dlerror();
    DecodeMainEntryBase* entry = FindEntry(key);
    if (!entry)
      logger(FATAL) <<"Entry lookup failed in : " << key << "-dcd.so";
    return entry;
  #endif
    return 0;
  } else {
    return it->second;
  }
}

template<class T, class L, class B>
struct DecodeMainRegisterer {
  explicit DecodeMainRegisterer(const string& name, const string& desc = "") {
    if (main_map.find(name) != main_map.end())
      LOG(FATAL)  << "Registered type already exists : " << name;
    main_map[name] = new DecodeMainEntry<T, L, B>;
  }
};

#define REGISTER_DECODER_MAIN(N, T, D, B, L) \
  static DecodeMainRegisterer<T<D>, L, B> \
    decode_registerer ## _ ## T ## _ ## D ## _ ## _ ## L ## B(N);

REGISTER_DECODER_MAIN("hmm_lattice", HMMTransitionModel,
    Decodable, StdArc, Lattice);

REGISTER_DECODER_MAIN("hmm_lattice_kaldi", HMMTransitionModel,
    Decodable, KaldiLatticeArc, Lattice);

REGISTER_DECODER_MAIN("hmm_simple", HMMTransitionModel,
    Decodable, StdArc, SimpleLattice);

REGISTER_DECODER_MAIN("generic_lattice", GenericTransitionModel,
    Decodable, StdArc, Lattice);

//REGISTER_DECODER_MAIN("hmm_hitstats", HMMTransitionModel,
//  SimpleDecodableHitStats, StdArc);

int main(int argc, char *argv[]) {
  PROFILE_FUNC();
  g_dcd_global_allocated = g_dcd_current_num_allocated;
  const char *usage = "Decode some speech\n"
        "Usage: dcd-recog [options] trans-model-in (fst-in|fsts-rspecifier) "
        "features-rspecifier far-wspecifier";

  PrintVersionInfo();
  cerr << endl;
  PrintMachineInfo();
  cerr << endl;
  cerr << "Program arguments : " << endl;
  ParseOptions po(usage);
  SearchOptions opts;
  po.Register("decoder_type", &tm_type, "Type of decoder to use");
  po.Register("word_symbols_table", &word_symbols_file, "");
  po.Register("lingware", &lingware, "");
  po.Register("logfile", &logfile, "/dev/stderr");
  /*po.Register("wfst");
  po.Register("trans_model");
  po.Register("input");
  po.Register("output");*/
  opts.Register(&po);
  po.Read(argc, argv);

  if (po.NumArgs() != 4) {
    po.PrintUsage();
    cerr << "Built-in decoder types : " << endl;
    for (unordered_map<string, DecodeMainEntryBase*>::iterator it
        =  main_map.begin(); it != main_map.end(); ++it ) {
      cerr << "  " << it->first << " : " << it->second->Description() << endl;
    }
    exit(1);
  }

  opts.Check();
  cerr << endl << "Search options : " << endl << opts << endl;

  DecodeMainEntryBase* runner = FindEntry(tm_type);
  if (!runner)
    logger(FATAL) << "Unknown decoder type : " << tm_type;
  runner->Run(po, &opts, word_symbols_file);

  ClearMainRegister();
  PrintMemorySummary();

  PROFILE_UPDATE(); // update all profiles
  PROFILE_OUTPUT(NULL); // print to terminal
}

<|endoftext|>


<commit_before>#include <string>
#include <vector>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <sys/wait.h>
#include <queue>
#include "command.cpp"

using namespace boost;
using namespace std;

class rshell{
	protected:
		//Data Members
		string commands;
		string nextConnector;
		vector<string> commandlist;
		queue<command*> vecCommands;
		bool prevCommandPass;
		bool allCount;
		bool forceExit;
		int numParen;
		int numBrack;
	public:
		//Constructor
		rshell(){
			commands = "";
			nextConnector = ";";
			prevCommandPass = true;
			forceExit = false;
			allCount = true;
		}

		// Parses the string (strings ending in ';' will keep the ';')
		void parseAllCommands(){
			char_separator<char> delims(" ","&,;,|,(,),[,]");
			tokenizer<char_separator<char> > tokenlist(commands, delims);
			for (tokenizer<char_separator<char> >::iterator i = tokenlist.begin(); i != tokenlist.end(); i++){
				string com(*i);
				commandlist.push_back(com);
			}
			for(unsigned c = 0; c < commandlist.size(); ++c){
				if(commandlist.at(c) == "("){ numParen++; }
				if(commandlist.at(c) == ")"){ numParen--; }
				if(commandlist.at(c) == "["){ numBrack++; }
				if(commandlist.at(c) == "]"){ numBrack--; }
			}
			if(numParen != 0){
				cout << "Invalid number of parenthesis" << endl;
			}
			if(numBrack != 0){
				cout << "Invalid number of brackets" << endl;
			}
		}

		// Builds commands and places them in a queue in order of precedence
		void commandBuilder(){
			vector<string> tempVec;
			string tempConnect;
			unsigned int i = 0;
			for(; i < commandlist.size(); ++i){
				if(!checkParen(i)){
					if(i != 0){
						if( (commandlist.at(i - 1) == ")") && (checkBreaker(i)) ){
							if( commandlist.at(i) == ";"){
								tempConnect = ";";
								tempVec.push_back(commandlist.at(i));
							}
							else if( commandlist.at(i) == "|"){
								tempConnect = "||";
								tempVec.push_back(commandlist.at(i));
							}
							else{
								tempConnect = "&&";
								tempVec.push_back(commandlist.at(i));
							}
						}
						else{
							tempVec.push_back(commandlist.at(i));
						}
					}
					else{
						tempVec.push_back(commandlist.at(i));
					}
				}
				else if(commandlist.at(i) == ")"){
					if(tempConnect.empty()){
						vecCommands.push(new command(tempVec) );
						tempVec.clear();
					}
					else{
						vecCommands.push(new command(tempVec, tempConnect) );
						tempConnect.clear();
						tempVec.clear();
					}
				}
			}
			if(i == commandlist.size()){
				if (tempVec.size() > 0){
					vecCommands.push(new command(tempVec) );
				}
			}
			else if(commandlist.size() == 1){
				vecCommands.push(new command(tempVec) );
			}
		}

		//Splits commandlist into commands with their arguments then calls executeCommand to run them.
		void executeAllCommands(){
			while (!vecCommands.empty()){
				vecCommands.front()->execute(prevCommandPass);
				prevCommandPass = vecCommands.front()->getPass();
				vecCommands.pop();
			}
		}

		//	Checks if the string is a breaker
		bool checkBreaker(int i){
			if ( (unsigned)i < commandlist.size() + 1){
				if (commandlist.at(i) == "|" && commandlist.at(i + 1) == "|"){
					return true;
				}
				else if (commandlist.at(i) == "&" && commandlist.at(i + 1) == "&"){
					return true;
				}
				else if (commandlist.at(i) == ";"){
					return true;
				}
				else{
					return false;
				}
			}
			else if( (unsigned)i == commandlist.size() + 1){
				if(commandlist.at(i) == ";"){
					return true;
				}
				return false;
			}
			else{
				return false;
			}
		}

		//Checks for Parenthesis
		bool checkParen(unsigned i){
			if( commandlist.at(i) == "(" ){
				return true;
			}
			if( commandlist.at(i) == ")" ){
				return true;
			}
			return false;
		}

		//Checks for brackets
		bool checkBrack(unsigned i){
			if( commandlist.at(i) == "[" ){
				return true;
			}
			if( commandlist.at(i) == "]" ){
				return true;
			}
			return false;
		}

		//Starts the program.
		void run(){
			while (!forceExit && commands != "exit"){
				cout << "$";
				getline(cin, commands);
				parseAllCommands();
				commandBuilder();
				executeAllCommands();
				commandlist.clear();
				nextConnector = ";";
				prevCommandPass = true;
			}
		}
};
<commit_msg>fixed err msg for invalid paren/brack<commit_after>#include <string>
#include <vector>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <sys/wait.h>
#include <queue>
#include "command.cpp"

using namespace boost;
using namespace std;

class rshell{
	protected:
		//Data Members
		string commands;
		string nextConnector;
		vector<string> commandlist;
		queue<command*> vecCommands;
		bool prevCommandPass;
		bool allCount;
		bool forceExit;
		int numParen;
		int numBrack;
	public:
		//Constructor
		rshell(){
			commands = "";
			nextConnector = ";";
			prevCommandPass = true;
			forceExit = false;
			allCount = true;
		}

		// Parses the string (strings ending in ';' will keep the ';')
		bool parseAllCommands(){
			char_separator<char> delims(" ","&,;,|,(,),[,]");
			tokenizer<char_separator<char> > tokenlist(commands, delims);
			for (tokenizer<char_separator<char> >::iterator i = tokenlist.begin(); i != tokenlist.end(); i++){
				string com(*i);
				commandlist.push_back(com);
			}
			for(unsigned c = 0; c < commandlist.size(); ++c){
				if(commandlist.at(c) == "("){ numParen++; }
				if(commandlist.at(c) == ")"){ numParen--; }
				if(commandlist.at(c) == "["){ numBrack++; }
				if(commandlist.at(c) == "]"){ numBrack--; }
			}
			if(numParen != 0){
				cout << "Invalid number of parenthesis" << endl;
				return false;
			}
			if(numBrack != 0){
				cout << "Invalid number of brackets" << endl;
				return false;
			}
			return true;
		}

		// Builds commands and places them in a queue in order of precedence
		void commandBuilder(){
			vector<string> tempVec;
			string tempConnect;
			unsigned int i = 0;
			for(; i < commandlist.size(); ++i){
				if(!checkParen(i)){
					if(i != 0){
						if( (commandlist.at(i - 1) == ")") && (checkBreaker(i)) ){
							if( commandlist.at(i) == ";"){
								tempConnect = ";";
								tempVec.push_back(commandlist.at(i));
							}
							else if( commandlist.at(i) == "|"){
								tempConnect = "||";
								tempVec.push_back(commandlist.at(i));
							}
							else{
								tempConnect = "&&";
								tempVec.push_back(commandlist.at(i));
							}
						}
						else{
							tempVec.push_back(commandlist.at(i));
						}
					}
					else{
						tempVec.push_back(commandlist.at(i));
					}
				}
				else if(commandlist.at(i) == ")"){
					if(tempConnect.empty()){
						vecCommands.push(new command(tempVec) );
						tempVec.clear();
					}
					else{
						vecCommands.push(new command(tempVec, tempConnect) );
						tempConnect.clear();
						tempVec.clear();
					}
				}
			}
			if(i == commandlist.size()){
				if (tempVec.size() > 0){
					vecCommands.push(new command(tempVec) );
				}
			}
			else if(commandlist.size() == 1){
				vecCommands.push(new command(tempVec) );
			}
		}

		//Splits commandlist into commands with their arguments then calls executeCommand to run them.
		void executeAllCommands(){
			while (!vecCommands.empty()){
				vecCommands.front()->execute(prevCommandPass);
				prevCommandPass = vecCommands.front()->getPass();
				vecCommands.pop();
			}
		}

		//	Checks if the string is a breaker
		bool checkBreaker(int i){
			if ( (unsigned)i < commandlist.size() + 1){
				if (commandlist.at(i) == "|" && commandlist.at(i + 1) == "|"){
					return true;
				}
				else if (commandlist.at(i) == "&" && commandlist.at(i + 1) == "&"){
					return true;
				}
				else if (commandlist.at(i) == ";"){
					return true;
				}
				else{
					return false;
				}
			}
			else if( (unsigned)i == commandlist.size() + 1){
				if(commandlist.at(i) == ";"){
					return true;
				}
				return false;
			}
			else{
				return false;
			}
		}

		//Checks for Parenthesis
		bool checkParen(unsigned i){
			if( commandlist.at(i) == "(" ){
				return true;
			}
			if( commandlist.at(i) == ")" ){
				return true;
			}
			return false;
		}

		//Checks for brackets
		bool checkBrack(unsigned i){
			if( commandlist.at(i) == "[" ){
				return true;
			}
			if( commandlist.at(i) == "]" ){
				return true;
			}
			return false;
		}

		//Starts the program.
		void run(){
			while (!forceExit && commands != "exit"){
				cout << "$";
				getline(cin, commands);
				if(parseAllCommands()){
					commandBuilder();
					executeAllCommands();
					commandlist.clear();
					nextConnector = ";";
					prevCommandPass = true;
				}
			}
		}
};
<|endoftext|>