A Discrete-Event Network Simulator
API
bit-serializer.cc
Go to the documentation of this file.
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 "ns3/bit-serializer.h"
23 #include "ns3/bit-deserializer.h"
24 
25 using namespace ns3;
26 
27 // The main purpose of the BitSerializer and bitDeserializer classes is to
28 // simplify the bit serialization and deserialization in headers, trailers
29 // and packet bodies.
30 //
31 // This is usually performed by using bit masks, which works great if the
32 // field delimiters are known in advance, and are in a fixed position.
33 // If the field (i.e., a group of bits) position is dependent from some
34 // other parameter, then the code is more complex.
35 // If the field boundary is not even a multiple of a byte, then the problem
36 // is even more complex.
37 //
38 // BitSerializer allows you to "push" bits into a temporary buffer, and then
39 // extract an array of uint8_t to be used in
40 // Buffer::Iterator:Write (uint8_t const *buffer, uint32_t size).
41 //
42 // Similarly, BitDeserializer can be initialized by an array of uint8_t,
43 // typically obtained by a Buffer::Iterator:Read (uint8_t *buffer, uint32_t size)
44 // and then "pop" bits from the underlying buffer.
45 //
46 // This example shows the basic operations.
47 
48 int main ()
49 {
50 
51  BitSerializer testBitSerializer1;
52 
53  // add 7 bits - 0x55 (101 0101)
54  testBitSerializer1.PushBits (0x55, 7);
55  // add 3 bits - 0x7 (111)
56  testBitSerializer1.PushBits (0x7, 3);
57  // add 2 bits - 0x0 (00)
58  testBitSerializer1.PushBits (0x0, 2);
59  // The results is 1010 1011 1100.
60  // Adding 4 bits of padding at the end the result is 0xabc0.
61 
62  std::vector<uint8_t> result = testBitSerializer1.GetBytes ();
63 
64  std::cout << "Result: ";
65  for (uint8_t i = 0; i < result.size (); i++)
66  {
67  std::cout << std::hex << int(result[i]) << " ";
68  }
69  std::cout << std::endl;
70  std::cout << "Expecting: ab c0" << std::endl;
71 
72  // Here, instead of printing bits, you typically serialize them using
73  // Buffer::Iterator:Write (uint8_t const *buffer, uint32_t size).
74  //
75  // In this case the number of bits pushed is not a multiple of a byte
76  // so the class adds a padding at the end of the buffer.
77  // This is the default behaviour.
78 
79  BitSerializer testBitSerializer2;
80 
81  // add 7 bits - 0x55 (101 0101)
82  testBitSerializer2.PushBits (0x55, 7);
83  // add 3 bits - 0x7 (111)
84  testBitSerializer2.PushBits (0x7, 3);
85  // add 2 bits - 0x0 (00)
86  testBitSerializer2.PushBits (0x0, 2);
87 
88  // Change the class behaviour so to use a padding at the start of the buffer.
89  testBitSerializer2.InsertPaddingAtEnd (false);
90  // The results is 1010 1011 1100.
91  // Adding 4 bits of padding at the start the result is 0xabc.
92 
93  result = testBitSerializer2.GetBytes ();
94 
95  std::cout << "Result: ";
96  for (uint8_t i = 0; i < result.size (); i++)
97  {
98  std::cout << std::hex << int(result[i]) << " ";
99  }
100  std::cout << std::endl;
101  std::cout << "Expecting: a bc" << std::endl;
102 
103  // Here, instead of printing bits, you typically serialize them using
104  // Buffer::Iterator:Write (uint8_t const *buffer, uint32_t size).
105  //
106  // In this case the number of bits pushed is not a multiple of a byte
107  // so the class adds a padding at the start of the buffer.
108 
109  BitDeserializer testBitDeserializer;
110  uint8_t test[2];
111  test[0] = 0xab;
112  test[1] = 0xc0;
113 
114  // Typically a BitDeserializer will be initialized by an array obtained by
115  // Buffer::Iterator:Read (uint8_t *buffer, uint32_t size).
116 
117  testBitDeserializer.PushBytes (test, 2);
118  uint16_t nibble1 = testBitDeserializer.GetBits (7);
119  uint8_t nibble2 = testBitDeserializer.GetBits (3);
120  uint8_t nibble3 = testBitDeserializer.GetBits (2);
121 // if you deserialize too many bits you'll get an assert.
122 // uint8_t errorNibble = testBitDeserializer.GetBits (6);
123 
124  std::cout << "Result: " << std::hex << nibble1 << " " << +nibble2 << " " << +nibble3 << " " << std::endl;
125  std::cout << "Expecting: 55 7 0" << std::endl;
126 
127  return 0;
128 }
Bit deserializer.
void PushBytes(std::vector< uint8_t > bytes)
Pushes some bytes into the blob to be deserialized.
uint64_t GetBits(uint8_t size)
Pops a given number of bits from the blob front.
Bit serializer.
void PushBits(uint64_t value, uint8_t significantBits)
Pushes a number of bits in the blob.
std::vector< uint8_t > GetBytes()
Get the bytes representation of the blob.
void InsertPaddingAtEnd(bool padAtEnd)
Toggles the padding insertion policy.
Every class exported by the ns3 library is enclosed in the ns3 namespace.