A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
bit-serializer.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Universita' di Firenze, Italy
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
18 */
19
20#include "ns3/bit-serializer.h"
21
22#include "ns3/bit-deserializer.h"
23
24#include <iostream>
25
26using namespace ns3;
27
28// The main purpose of the BitSerializer and bitDeserializer classes is to
29// simplify the bit serialization and deserialization in headers, trailers
30// and packet bodies.
31//
32// This is usually performed by using bit masks, which works great if the
33// field delimiters are known in advance, and are in a fixed position.
34// If the field (i.e., a group of bits) position is dependent from some
35// other parameter, then the code is more complex.
36// If the field boundary is not even a multiple of a byte, then the problem
37// is even more complex.
38//
39// BitSerializer allows you to "push" bits into a temporary buffer, and then
40// extract an array of uint8_t to be used in
41// Buffer::Iterator:Write (uint8_t const *buffer, uint32_t size).
42//
43// Similarly, BitDeserializer can be initialized by an array of uint8_t,
44// typically obtained by a Buffer::Iterator:Read (uint8_t *buffer, uint32_t size)
45// and then "pop" bits from the underlying buffer.
46//
47// This example shows the basic operations.
48
49int
50main()
51{
52 BitSerializer testBitSerializer1;
53
54 // add 7 bits - 0x55 (101 0101)
55 testBitSerializer1.PushBits(0x55, 7);
56 // add 3 bits - 0x7 (111)
57 testBitSerializer1.PushBits(0x7, 3);
58 // add 2 bits - 0x0 (00)
59 testBitSerializer1.PushBits(0x0, 2);
60 // The results is 1010 1011 1100.
61 // Adding 4 bits of padding at the end the result is 0xabc0.
62
63 std::vector<uint8_t> result = testBitSerializer1.GetBytes();
64
65 std::cout << "Result: ";
66 for (std::size_t i = 0; i < result.size(); i++)
67 {
68 std::cout << std::hex << int(result[i]) << " ";
69 }
70 std::cout << std::endl;
71 std::cout << "Expecting: ab c0" << std::endl;
72
73 // Here, instead of printing bits, you typically serialize them using
74 // Buffer::Iterator:Write (uint8_t const *buffer, uint32_t size).
75 //
76 // In this case the number of bits pushed is not a multiple of a byte
77 // so the class adds a padding at the end of the buffer.
78 // This is the default behaviour.
79
80 BitSerializer testBitSerializer2;
81
82 // add 7 bits - 0x55 (101 0101)
83 testBitSerializer2.PushBits(0x55, 7);
84 // add 3 bits - 0x7 (111)
85 testBitSerializer2.PushBits(0x7, 3);
86 // add 2 bits - 0x0 (00)
87 testBitSerializer2.PushBits(0x0, 2);
88
89 // Change the class behaviour so to use a padding at the start of the buffer.
90 testBitSerializer2.InsertPaddingAtEnd(false);
91 // The results is 1010 1011 1100.
92 // Adding 4 bits of padding at the start the result is 0xabc.
93
94 result = testBitSerializer2.GetBytes();
95
96 std::cout << "Result: ";
97 for (std::size_t i = 0; i < result.size(); i++)
98 {
99 std::cout << std::hex << int(result[i]) << " ";
100 }
101 std::cout << std::endl;
102 std::cout << "Expecting: a bc" << std::endl;
103
104 // Here, instead of printing bits, you typically serialize them using
105 // Buffer::Iterator:Write (uint8_t const *buffer, uint32_t size).
106 //
107 // In this case the number of bits pushed is not a multiple of a byte
108 // so the class adds a padding at the start of the buffer.
109
110 BitDeserializer testBitDeserializer;
111 uint8_t test[2];
112 test[0] = 0xab;
113 test[1] = 0xc0;
114
115 // Typically a BitDeserializer will be initialized by an array obtained by
116 // Buffer::Iterator:Read (uint8_t *buffer, uint32_t size).
117
118 testBitDeserializer.PushBytes(test, 2);
119 uint16_t nibble1 = testBitDeserializer.GetBits(7);
120 uint8_t nibble2 = testBitDeserializer.GetBits(3);
121 uint8_t nibble3 = testBitDeserializer.GetBits(2);
122 // if you deserialize too many bits you'll get an assert.
123 // uint8_t errorNibble = testBitDeserializer.GetBits (6);
124
125 std::cout << "Result: " << std::hex << nibble1 << " " << +nibble2 << " " << +nibble3 << " "
126 << std::endl;
127 std::cout << "Expecting: 55 7 0" << std::endl;
128
129 return 0;
130}
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.
-ns3 Test suite for the ns3 wrapper script