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
25using 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
48int 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.