1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 Universita' di Firenze, Italy
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19  */
20 
21 #include <iostream>
22 #include "bit-serializer.h"
23 #include "ns3/log.h"
24 #include "ns3/assert.h"
25 #include "ns3/abort.h"
26 
27 namespace ns3 {
28 
29 NS_LOG_COMPONENT_DEFINE ("BitSerializer");
30 
BitSerializer()31 BitSerializer::BitSerializer ()
32 {
33   NS_LOG_FUNCTION (this);
34   m_padAtEnd = true;
35 }
36 
InsertPaddingAtEnd(bool padAtEnd)37 void BitSerializer::InsertPaddingAtEnd (bool padAtEnd)
38 {
39   NS_LOG_FUNCTION (this);
40   m_padAtEnd = padAtEnd;
41 }
42 
PadAtStart()43 void BitSerializer::PadAtStart ()
44 {
45   NS_LOG_FUNCTION (this);
46 
47   uint8_t padding = 8 - (m_blob.size () % 8);
48 
49   m_blob.insert (m_blob.begin (), padding, false);
50 }
51 
PadAtEnd()52 void BitSerializer::PadAtEnd ()
53 {
54   uint8_t padding = 8 - (m_blob.size () % 8);
55 
56   m_blob.insert (m_blob.end (), padding, false);
57 }
58 
PushBits(uint64_t value,uint8_t significantBits)59 void BitSerializer::PushBits (uint64_t value, uint8_t significantBits)
60 {
61   NS_LOG_FUNCTION (this << value << +significantBits);
62 
63   uint64_t mask = 1;
64   mask <<= significantBits - 1;
65 
66   for (uint8_t i = 0; i < significantBits; i++)
67     {
68       if (value & mask)
69         {
70           m_blob.push_back (true);
71         }
72       else
73         {
74           m_blob.push_back (false);
75         }
76       mask >>= 1;
77     }
78 }
79 
GetBytes()80 std::vector<uint8_t> BitSerializer::GetBytes ()
81 {
82   NS_LOG_FUNCTION (this);
83 
84   std::vector<uint8_t> result;
85 
86   m_padAtEnd ? PadAtEnd () : PadAtStart ();
87 
88   for (auto it = m_blob.begin (); it != m_blob.end ();)
89     {
90       uint8_t tmp = 0;
91       for (uint8_t i = 0; i < 8; ++i)
92         {
93           tmp <<= 1;
94           tmp |= (*it & 1);
95           it++;
96         }
97       result.push_back (tmp);
98     }
99   m_blob.clear ();
100   return result;
101 }
102 
GetBytes(uint8_t * buffer,uint32_t size)103 uint8_t BitSerializer::GetBytes (uint8_t *buffer, uint32_t size)
104 {
105   NS_LOG_FUNCTION (this << buffer << size);
106 
107   uint8_t resultLen = 0;
108 
109   m_padAtEnd ? PadAtEnd () : PadAtStart ();
110 
111   NS_ABORT_MSG_IF (m_blob.size () <= 8 * size, "Target buffer is too short, " << m_blob.size () / 8 << " bytes needed" );
112 
113   for (auto it = m_blob.begin (); it != m_blob.end ();)
114     {
115       uint8_t tmp = 0;
116       for (uint8_t i = 0; i < 8; ++i)
117         {
118           tmp <<= 1;
119           tmp |= (*it & 1);
120           it++;
121         }
122       buffer[resultLen] = tmp;
123       resultLen++;
124 
125     }
126   m_blob.clear ();
127   return resultLen;
128 }
129 
130 } // namespace ns3
131