Open Lighting Architecture  0.9.0
 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 /*
34  * The Base PDU class
35  * TODO(simon): make this into a template based on vector size.
36  */
37 class PDU {
38  public:
39  typedef enum {
40  ONE_BYTE = 1,
41  TWO_BYTES = 2,
42  FOUR_BYTES = 4,
43  } vector_size;
44 
45  PDU(unsigned int vector, vector_size size = FOUR_BYTES):
46  m_vector(vector),
47  m_vector_size(size) {}
48  virtual ~PDU() {}
49 
50  // Returns the size of this PDU
51  virtual unsigned int Size() const;
52  virtual unsigned int VectorSize() const { return m_vector_size; }
53  virtual unsigned int HeaderSize() const = 0;
54  virtual unsigned int DataSize() const = 0;
55 
56  // Set the vector
57  void SetVector(unsigned int vector) { m_vector = vector; }
58 
59  /*
60  * Pack the PDU into the memory pointed to by data
61  * @return true on success, false on failure
62  */
63  virtual bool Pack(uint8_t *data, unsigned int *length) const;
64  virtual bool PackHeader(uint8_t *data, unsigned int *length) const = 0;
65  virtual bool PackData(uint8_t *data, unsigned int *length) const = 0;
66 
70  virtual void Write(ola::io::OutputStream *stream) const;
71  virtual void PackHeader(ola::io::OutputStream *stream) const = 0;
72  virtual void PackData(ola::io::OutputStream *stream) const = 0;
73 
74  static void PrependFlagsAndLength(
76  uint8_t flags = VFLAG_MASK | HFLAG_MASK | DFLAG_MASK);
77 
78  static void PrependFlagsAndLength(
80  unsigned int length,
81  uint8_t flags);
82 
83  // This indicates a vector is present
84  static const uint8_t VFLAG_MASK = 0x40;
85  // This indicates a header field is present
86  static const uint8_t HFLAG_MASK = 0x20;
87  // This indicates a data field is present
88  static const uint8_t DFLAG_MASK = 0x10;
89 
90  private:
91  unsigned int m_vector;
92  unsigned int m_vector_size;
93 
94  // The max PDU length that can be represented with the 2 byte format for
95  // the length field.
96  static const unsigned int TWOB_LENGTH_LIMIT = 0x0FFF;
97 };
98 
99 
100 /*
101  * Represents a block of pdus
102  */
103 template <class C>
104 class PDUBlock {
105  public:
106  PDUBlock(): m_size(0) {}
107  ~PDUBlock() {}
108 
109  // Add a PDU to this block
110  void AddPDU(const C *msg) {
111  m_pdus.push_back(msg);
112  m_size += msg->Size();
113  }
114  // Remove all PDUs from the block
115  void Clear() {
116  m_pdus.clear();
117  m_size = 0;
118  }
119  // The number of bytes this block would consume, this ignores optimizations
120  // like repeating headers/vectors.
121  unsigned int Size() const { return m_size; }
122  /*
123  * Pack this PDUBlock into memory pointed to by data
124  * @return true on success, false on failure
125  */
126  bool Pack(uint8_t *data, unsigned int *length) const;
127 
131  void Write(ola::io::OutputStream *stream) const;
132 
133  private:
134  std::vector<const C*> m_pdus;
135  unsigned int m_size;
136 };
137 
138 
139 /*
140  * Pack this block of PDUs into a buffer
141  * @param data a pointer to the buffer
142  * @param length size of the buffer, updated with the number of bytes used
143  * @return true on success, false on failure
144  */
145 template <class C>
146 bool PDUBlock<C>::Pack(uint8_t *data, unsigned int *length) const {
147  bool status = true;
148  unsigned int i = 0;
149  typename std::vector<const C*>::const_iterator iter;
150  for (iter = m_pdus.begin(); iter != m_pdus.end(); ++iter) {
151  // TODO(simon): optimize repeated headers & vectors here
152  unsigned int remaining = i < *length ? *length - i : 0;
153  status &= (*iter)->Pack(data + i, &remaining);
154  i+= remaining;
155  }
156  *length = i;
157  return status;
158 }
159 
160 
161 /*
162  * Write this block of PDUs to an OutputStream.
163  * @param stream the OutputStream to write to
164  * @return true on success, false on failure
165  */
166 template <class C>
168  typename std::vector<const C*>::const_iterator iter;
169  for (iter = m_pdus.begin(); iter != m_pdus.end(); ++iter) {
170  // TODO(simon): optimize repeated headers & vectors here
171  (*iter)->Write(stream);
172  }
173 }
174 } // namespace e131
175 } // namespace plugin
176 } // namespace ola
177 #endif // PLUGINS_E131_E131_PDU_H_