Open Lighting Architecture
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PDU.h
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU Library General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  *
16  * PDU.h
17  * Interface for the PDU and PDUBlock classes
18  * Copyright (C) 2007-2009 Simon Newton
19  */
20 
21 #ifndef PLUGINS_E131_E131_PDU_H_
22 #define PLUGINS_E131_E131_PDU_H_
23 
24 #include <stdint.h>
25 #include <ola/io/OutputStream.h>
26 #include <ola/io/OutputBuffer.h>
27 #include <vector>
28 
29 namespace ola {
30 namespace plugin {
31 namespace e131 {
32 
33 
35 
36 
37 /*
38  * The Base PDU class
39  * TODO(simon): make this into a template based on vector size.
40  */
41 class PDU {
42  public:
43  typedef enum {
44  ONE_BYTE = 1,
45  TWO_BYTES = 2,
46  FOUR_BYTES = 4,
47  } vector_size;
48 
49  PDU(unsigned int vector, vector_size size = FOUR_BYTES):
50  m_vector(vector),
51  m_vector_size(size) {}
52  virtual ~PDU() {}
53 
54  // Returns the size of this PDU
55  virtual unsigned int Size() const;
56  virtual unsigned int VectorSize() const { return m_vector_size; }
57  virtual unsigned int HeaderSize() const = 0;
58  virtual unsigned int DataSize() const = 0;
59 
60  // Set the vector
61  void SetVector(unsigned int vector) { m_vector = vector; }
62 
63  /*
64  * Pack the PDU into the memory pointed to by data
65  * @return true on success, false on failure
66  */
67  virtual bool Pack(uint8_t *data, unsigned int *length) const;
68  virtual bool PackHeader(uint8_t *data, unsigned int *length) const = 0;
69  virtual bool PackData(uint8_t *data, unsigned int *length) const = 0;
70 
74  virtual void Write(OutputStream *stream) const;
75  virtual void PackHeader(OutputStream *stream) const = 0;
76  virtual void PackData(OutputStream *stream) const = 0;
77 
78  static void PrependFlagsAndLength(
80  uint8_t flags = VFLAG_MASK | HFLAG_MASK | DFLAG_MASK);
81 
82  static void PrependFlagsAndLength(
84  unsigned int length,
85  uint8_t flags);
86 
87  // This indicates a vector is present
88  static const uint8_t VFLAG_MASK = 0x40;
89  // This indicates a header field is present
90  static const uint8_t HFLAG_MASK = 0x20;
91  // This indicates a data field is present
92  static const uint8_t DFLAG_MASK = 0x10;
93 
94  private:
95  unsigned int m_vector;
96  unsigned int m_vector_size;
97 
98  // The max PDU length that can be represented with the 2 byte format for
99  // the length field.
100  static const unsigned int TWOB_LENGTH_LIMIT = 0x0FFF;
101 };
102 
103 
104 /*
105  * Represents a block of pdus
106  */
107 template <class C>
108 class PDUBlock {
109  public:
110  PDUBlock(): m_size(0) {}
111  ~PDUBlock() {}
112 
113  // Add a PDU to this block
114  void AddPDU(const C *msg) {
115  m_pdus.push_back(msg);
116  m_size += msg->Size();
117  }
118  // Remove all PDUs from the block
119  void Clear() {
120  m_pdus.clear();
121  m_size = 0;
122  }
123  // The number of bytes this block would consume, this ignores optimizations
124  // like repeating headers/vectors.
125  unsigned int Size() const { return m_size; }
126  /*
127  * Pack this PDUBlock into memory pointed to by data
128  * @return true on success, false on failure
129  */
130  bool Pack(uint8_t *data, unsigned int *length) const;
131 
135  void Write(OutputStream *stream) const;
136 
137  private:
138  std::vector<const C*> m_pdus;
139  unsigned int m_size;
140 };
141 
142 
143 /*
144  * Pack this block of PDUs into a buffer
145  * @param data a pointer to the buffer
146  * @param length size of the buffer, updated with the number of bytes used
147  * @return true on success, false on failure
148  */
149 template <class C>
150 bool PDUBlock<C>::Pack(uint8_t *data, unsigned int *length) const {
151  bool status = true;
152  unsigned int i = 0;
153  typename std::vector<const C*>::const_iterator iter;
154  for (iter = m_pdus.begin(); iter != m_pdus.end(); ++iter) {
155  // TODO(simon): optimize repeated headers & vectors here
156  unsigned int remaining = i < *length ? *length - i : 0;
157  status &= (*iter)->Pack(data + i, &remaining);
158  i+= remaining;
159  }
160  *length = i;
161  return status;
162 }
163 
164 
165 /*
166  * Write this block of PDUs to an OutputStream.
167  * @param stream the OutputStream to write to
168  * @return true on success, false on failure
169  */
170 template <class C>
171 void PDUBlock<C>::Write(OutputStream *stream) const {
172  typename std::vector<const C*>::const_iterator iter;
173  for (iter = m_pdus.begin(); iter != m_pdus.end(); ++iter) {
174  // TODO(simon): optimize repeated headers & vectors here
175  (*iter)->Write(stream);
176  }
177 }
178 } // namespace e131
179 } // namespace plugin
180 } // namespace ola
181 #endif // PLUGINS_E131_E131_PDU_H_