GCC Code Coverage Report


Directory: ./
File: Svc/Ccsds/CfdpManager/Types/FileDataPdu.cpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 74 85 87.1%
Functions: 9 9 100.0%
Branches: 44 58 75.9%

Line Branch Exec Source
1 // ======================================================================
2 // \title FileDataPdu.cpp
3 // \author Brian Campuzano
4 // \brief cpp file for CFDP File Data PDU
5 // ======================================================================
6
7 #include <Fw/Types/Assert.hpp>
8 #include <Svc/Ccsds/CfdpManager/Types/FileDataPdu.hpp>
9 #include <config/CfdpCfg.hpp>
10
11 namespace Svc {
12 namespace Ccsds {
13 namespace Cfdp {
14
15 85 void FileDataPdu::initialize(PduDirection direction,
16 Cfdp::Class::T txmMode,
17 EntityId sourceEid,
18 TransactionSeq transactionSeq,
19 EntityId destEid,
20 FileSize offset,
21 U16 dataSize,
22 const U8* data) {
23 // Initialize header with PduTypeEnum::FILE_DATA type
24 85 this->m_header.initialize(PduTypeEnum::FILE_DATA, direction, txmMode, sourceEid, transactionSeq, destEid);
25
26 85 this->m_offset = offset;
27 85 this->m_dataSize = dataSize;
28 85 this->m_data = data;
29 85 }
30
31 158 U32 FileDataPdu::getBufferSize() const {
32 158 U32 size = this->m_header.getBufferSize();
33
34 // Offset field size depends on large file flag
35
1/2
✗ Branch 6 not taken.
✓ Branch 7 taken 158 times.
158 if (this->m_header.m_largeFileFlag == LargeFileFlag::LARGE_FILE_64_BIT) {
36 size += static_cast<U32>(sizeof(U64)); // 8-byte offset
37 } else {
38 158 size += static_cast<U32>(sizeof(U32)); // 4-byte offset
39 }
40
41 158 size += this->m_dataSize; // actual data
42 158 return size;
43 }
44
45 37 U32 FileDataPdu::getMaxFileDataSize() {
46 37 U32 size = this->m_header.getBufferSize();
47
48 // Offset field size depends on large file flag
49
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 37 times.
37 if (this->m_header.m_largeFileFlag == LargeFileFlag::LARGE_FILE_64_BIT) {
50 size += static_cast<U32>(sizeof(U64)); // 8-byte offset
51 } else {
52 37 size += static_cast<U32>(sizeof(U32)); // 4-byte offset
53 }
54
55 37 return MaxPduSize - size;
56 }
57
58 4 Fw::SerializeStatus FileDataPdu::toBuffer(Fw::Buffer& buffer) const {
59
3/3
✓ Branch 5 taken 4 times.
✓ Branch 11 taken 4 times.
✓ Branch 14 taken 4 times.
4 Fw::SerialBuffer serialBuffer(buffer.getData(), buffer.getSize());
60
1/1
✓ Branch 4 taken 4 times.
4 Fw::SerializeStatus status = this->toSerialBuffer(serialBuffer);
61
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (status == Fw::FW_SERIALIZE_OK) {
62
2/2
✓ Branch 5 taken 4 times.
✓ Branch 8 taken 4 times.
4 buffer.setSize(serialBuffer.getSize());
63 }
64 4 return status;
65 4 }
66
67 2 Fw::SerializeStatus FileDataPdu::fromBuffer(const Fw::Buffer& buffer) {
68 // Create SerialBuffer from Buffer
69
3/3
✓ Branch 5 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 14 taken 2 times.
2 Fw::SerialBuffer serialBuffer(const_cast<Fw::Buffer&>(buffer).getData(), const_cast<Fw::Buffer&>(buffer).getSize());
70
1/1
✓ Branch 2 taken 2 times.
2 serialBuffer.fill();
71
72 // Deserialize header first
73
1/1
✓ Branch 4 taken 2 times.
2 Fw::SerializeStatus status = this->m_header.fromSerialBuffer(serialBuffer);
74
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (status != Fw::FW_SERIALIZE_OK) {
75 return status;
76 }
77
78 // Validate this is a file data PDU
79
2/2
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
2 if (this->m_header.m_pduType != PduType::PDU_TYPE_FILE_DATA) {
80 1 return Fw::FW_DESERIALIZE_TYPE_MISMATCH;
81 }
82
83 // Set the type to PduTypeEnum::FILE_DATA since we've validated it
84 1 this->m_header.m_type = PduTypeEnum::FILE_DATA;
85
86 // Deserialize the file data body
87
1/1
✓ Branch 4 taken 1 times.
1 return this->fromSerialBuffer(serialBuffer);
88 2 }
89
90 83 Fw::SerializeStatus FileDataPdu::toSerialBuffer(Fw::SerialBuffer& serialBuffer) const {
91 83 FW_ASSERT(this->m_header.m_type == PduTypeEnum::FILE_DATA);
92
93 // Calculate PDU data length (everything after header)
94
2/2
✓ Branch 7 taken 83 times.
✓ Branch 15 taken 83 times.
83 U32 dataLength = this->getBufferSize() - this->m_header.getBufferSize();
95
96 // Update header with data length
97 83 PduHeader headerCopy = this->m_header;
98 83 headerCopy.setPduDataLength(static_cast<U16>(dataLength));
99
100 // Serialize header
101
1/1
✓ Branch 3 taken 83 times.
83 Fw::SerializeStatus status = headerCopy.toSerialBuffer(serialBuffer);
102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (status != Fw::FW_SERIALIZE_OK) {
103 return status;
104 }
105
106 // Serialize offset - size depends on large file flag
107
1/2
✗ Branch 6 not taken.
✓ Branch 7 taken 83 times.
83 if (this->m_header.m_largeFileFlag == LargeFileFlag::LARGE_FILE_64_BIT) {
108 // Serialize as 8 bytes (64-bit)
109 U64 offset64 = this->m_offset;
110 status = serialBuffer.serializeFrom(offset64);
111 } else {
112 // Serialize as 4 bytes (32-bit)
113 83 U32 offset32 = static_cast<U32>(this->m_offset);
114
1/1
✓ Branch 5 taken 83 times.
83 status = serialBuffer.serializeFrom(offset32);
115 }
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (status != Fw::FW_SERIALIZE_OK) {
117 return status;
118 }
119
120 // Serialize file data (only if there is data to serialize)
121
2/2
✓ Branch 4 taken 80 times.
✓ Branch 5 taken 3 times.
83 if (this->m_dataSize > 0) {
122
1/1
✓ Branch 12 taken 80 times.
80 status = serialBuffer.pushBytes(this->m_data, this->m_dataSize);
123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (status != Fw::FW_SERIALIZE_OK) {
124 return status;
125 }
126 }
127
128 83 return Fw::FW_SERIALIZE_OK;
129 }
130
131 95 Fw::SerializeStatus FileDataPdu::fromSerialBuffer(Fw::SerialBuffer& serialBuffer) {
132 95 FW_ASSERT(this->m_header.m_type == PduTypeEnum::FILE_DATA);
133
134 // Deserialize offset - size depends on large file flag
135 Fw::SerializeStatus status;
136 U8 offsetSize;
137
1/1
✓ Branch 8 taken 95 times.
95 status = serialBuffer.deserializeTo(this->m_offset);
138
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 94 times.
95 if (status != Fw::FW_SERIALIZE_OK) {
139 1 return status;
140 }
141 94 offsetSize = sizeof(this->m_offset);
142
143 // Calculate remaining data size based on header's PDU data length
144 94 U16 pduDataLength = this->m_header.getPduDataLength();
145
146 // Defensive check: prevent unsigned integer underflow
147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94 times.
94 if (pduDataLength < offsetSize) {
148 return Fw::FW_DESERIALIZE_SIZE_MISMATCH;
149 }
150
151 94 this->m_dataSize = static_cast<U16>(pduDataLength - offsetSize); // minus offset size
152
153 // Point to the data in the buffer (zero-copy)
154
1/1
✓ Branch 7 taken 94 times.
94 this->m_data = serialBuffer.getBuffAddrLeft();
155
156 // Validate we have enough bytes
157
3/3
✓ Branch 5 taken 94 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 93 times.
94 if (serialBuffer.getDeserializeSizeLeft() < this->m_dataSize) {
158 1 return Fw::FW_DESERIALIZE_SIZE_MISMATCH;
159 }
160
161 // Advance the buffer pointer
162 93 U8 tempBuf[1]; // Dummy buffer for validation
163
2/2
✓ Branch 4 taken 70159 times.
✓ Branch 5 taken 93 times.
70252 for (U16 i = 0; i < this->m_dataSize; ++i) {
164
1/1
✓ Branch 4 taken 70159 times.
70159 status = serialBuffer.popBytes(tempBuf, 1);
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70159 times.
70159 if (status != Fw::FW_SERIALIZE_OK) {
166 return status;
167 }
168 }
169
170 93 return Fw::FW_SERIALIZE_OK;
171 }
172
173 79 Fw::SerializeStatus FileDataPdu::serializeTo(Fw::SerialBufferBase& buffer, Fw::Endianness mode) const {
174 // Caller contract guarantees a SerialBuffer.
175
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 Fw::SerialBuffer* serialBuffer = static_cast<Fw::SerialBuffer*>(&buffer);
176 79 return this->toSerialBuffer(*serialBuffer);
177 }
178
179 94 Fw::SerializeStatus FileDataPdu::deserializeFrom(Fw::SerialBufferBase& buffer, Fw::Endianness mode) {
180 // Caller contract guarantees a SerialBuffer.
181
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 Fw::SerialBuffer* serialBuffer = static_cast<Fw::SerialBuffer*>(&buffer);
182
183 // Deserialize header first
184 94 Fw::SerializeStatus status = this->m_header.fromSerialBuffer(*serialBuffer);
185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94 times.
94 if (status != Fw::FW_SERIALIZE_OK) {
186 return status;
187 }
188
189 // Deserialize the file data body
190 94 return this->fromSerialBuffer(*serialBuffer);
191 }
192
193 } // namespace Cfdp
194 } // namespace Ccsds
195 } // namespace Svc
196