Panda3D
datagramBuffer.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file datagramBuffer.cxx
10  * @author rdb
11  * @date 2017-11-07
12  */
13 
14 #include "datagramBuffer.h"
15 
16 /**
17  * Writes a sequence of bytes to the beginning of the datagram file. This may
18  * be called any number of times after the file has been opened and before the
19  * first datagram is written. It may not be called once the first datagram is
20  * written.
21  */
23 write_header(const std::string &header) {
24  nassertr(!_wrote_first_datagram, false);
25 
26  _data.insert(_data.end(), header.begin(), header.end());
27  return true;
28 }
29 
30 /**
31  * Writes the given datagram to the file. Returns true on success, false if
32  * there is an error.
33  */
35 put_datagram(const Datagram &data) {
36  _wrote_first_datagram = true;
37 
38  // First, write the size of the upcoming datagram.
39  size_t num_bytes = data.get_length();
40  size_t offset = _data.size();
41 
42  if (num_bytes == (uint32_t)-1 || num_bytes != (uint32_t)num_bytes) {
43  // Write a large value as a 64-bit size.
44  _data.resize(offset + num_bytes + 4 + sizeof(uint64_t));
45  _data[offset++] = 0xff;
46  _data[offset++] = 0xff;
47  _data[offset++] = 0xff;
48  _data[offset++] = 0xff;
49 
50  LittleEndian s(&num_bytes, sizeof(uint64_t));
51  memcpy(&_data[offset], s.get_data(), sizeof(uint64_t));
52  offset += sizeof(uint64_t);
53  } else {
54  // Write a value that fits in 32 bits.
55  _data.resize(offset + num_bytes + sizeof(uint32_t));
56 
57  LittleEndian s(&num_bytes, sizeof(uint32_t));
58  memcpy(&_data[offset], s.get_data(), sizeof(uint32_t));
59  offset += sizeof(uint32_t);
60  }
61 
62  // Now, write the datagram itself.
63  memcpy(&_data[offset], data.get_data(), data.get_length());
64  return true;
65 }
66 
67 /**
68  * This does absolutely nothing.
69  */
71 flush() {
72 }
73 
74 /**
75  * Reads a sequence of bytes from the beginning of the datagram file. This
76  * may be called any number of times after the file has been opened and before
77  * the first datagram is read. It may not be called once the first datagram
78  * has been read.
79  */
81 read_header(std::string &header, size_t num_bytes) {
82  nassertr(!_read_first_datagram, false);
83  if (_read_offset + num_bytes > _data.size()) {
84  return false;
85  }
86 
87  header = std::string((char *)&_data[_read_offset], num_bytes);
88  _read_offset += num_bytes;
89  return true;
90 }
91 
92 /**
93  * Reads the next datagram from the file. Returns true on success, false if
94  * there is an error or end of file.
95  */
98  _read_first_datagram = true;
99  if (_read_offset + sizeof(uint32_t) > _data.size()) {
100  // Reached the end of the buffer.
101  return false;
102  }
103 
104  // First, get the size of the upcoming datagram.
105  uint32_t num_bytes_32;
106  LittleEndian s(&_data[_read_offset], 0, sizeof(uint32_t));
107  s.store_value(&num_bytes_32, sizeof(uint32_t));
108  _read_offset += 4;
109 
110  if (num_bytes_32 == 0) {
111  // A special case for a zero-length datagram: no need to try to read any
112  // data.
113  data.clear();
114  return true;
115  }
116 
117  size_t num_bytes = (size_t)num_bytes_32;
118  if (num_bytes_32 == (uint32_t)-1) {
119  // Another special case for a value larger than 32 bits.
120  uint64_t num_bytes_64;
121  LittleEndian s(&_data[_read_offset], 0, sizeof(uint64_t));
122  s.store_value(&num_bytes_64, sizeof(uint64_t));
123  _read_offset += 8;
124 
125  num_bytes = (size_t)num_bytes_64;
126  nassertr((uint64_t)num_bytes == num_bytes_64, false);
127  }
128 
129  // Make sure we have this much data to read.
130  nassertr_always(_read_offset + num_bytes <= _data.size(), false);
131 
132  data = Datagram(&_data[_read_offset], num_bytes);
133  _read_offset += num_bytes;
134  return true;
135 }
136 
137 /**
138  * Returns true if the buffer has reached the end-of-buffer. This test may
139  * only be made after a call to read_header() or get_datagram() has failed.
140  */
141 bool DatagramBuffer::
143  return (_read_offset + sizeof(uint32_t)) > _data.size();
144 }
145 
146 /**
147  * Returns true if the buffer has reached an error condition.
148  */
149 bool DatagramBuffer::
151  return false;
152 }
bool write_header(const std::string &header)
Writes a sequence of bytes to the beginning of the datagram file.
virtual bool is_error() override
Returns true if the buffer has reached an error condition.
virtual bool is_eof() override
Returns true if the buffer has reached the end-of-buffer.
const void * get_data() const
Returns the pointer to the first byte of the data, either reversed or nonreversed,...
NativeNumericData and ReversedNumericData work together to provide a sneaky interface for automatical...
virtual bool put_datagram(const Datagram &data) override
Writes the given datagram to the file.
virtual void flush() override
This does absolutely nothing.
void store_value(void *dest, size_t length) const
Copies the data, with byte reversal if appropriate, into the indicated numeric variable,...
bool read_header(std::string &header, size_t num_bytes)
Reads a sequence of bytes from the beginning of the datagram file.
virtual bool get_datagram(Datagram &data) override
Reads the next datagram from the file.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.