Allow button display symbols to be Unicode characters
[lsnes.git] / include / library / controller-data.hpp
blob7f7b3d48530306ad1ea597077bdf7d50398c838d
1 #ifndef _library__controller_data__hpp__included__
2 #define _library__controller_data__hpp__included__
4 #include <cstring>
5 #include <climits>
6 #include <cstdio>
7 #include <cstdlib>
8 #include <cstdio>
9 #include <cstdint>
10 #include <sstream>
11 #include <iomanip>
12 #include <iostream>
13 #include <stdexcept>
14 #include <string>
15 #include <vector>
16 #include <map>
17 #include <list>
18 #include <set>
20 /**
21 * Memory to allocate for controller frame.
23 #define MAXIMUM_CONTROLLER_FRAME_SIZE 128
24 /**
25 * Maximum amount of data controller_frame::display() can write.
27 #define MAX_DISPLAY_LENGTH 128
28 /**
29 * Maximum amount of data controller_frame::serialize() can write.
31 #define MAX_SERIALIZED_SIZE 256
32 /**
33 * Size of controller page.
35 #define CONTROLLER_PAGE_SIZE 65500
36 /**
37 * Special return value for deserialize() indicating no input was taken.
39 #define DESERIALIZE_SPECIAL_BLANK 0xFFFFFFFFUL
41 /**
42 * Is not field terminator.
44 * Parameter ch: The character.
45 * Returns: True if character is not terminator, false if character is terminator.
47 inline bool is_nonterminator(char ch) throw()
49 return (ch != '|' && ch != '\r' && ch != '\n' && ch != '\0');
52 /**
53 * Read button value.
55 * Parameter buf: Buffer to read from.
56 * Parameter idx: Index to buffer. Updated.
57 * Returns: The read value.
59 inline bool read_button_value(const char* buf, size_t& idx) throw()
61 char ch = buf[idx];
62 if(is_nonterminator(ch))
63 idx++;
64 return (ch != '|' && ch != '\r' && ch != '\n' && ch != '\0' && ch != '.' && ch != ' ' && ch != '\t');
67 /**
68 * Read axis value.
70 * Parameter buf: Buffer to read from.
71 * Parameter idx: Index to buffer. Updated.
72 * Returns: The read value.
74 short read_axis_value(const char* buf, size_t& idx) throw();
76 /**
77 * Skip whitespace.
79 * Parameter buf: Buffer to read from.
80 * Parameter idx: Index to buffer. Updated.
82 inline void skip_field_whitespace(const char* buf, size_t& idx) throw()
84 while(buf[idx] == ' ' || buf[idx] == '\t')
85 idx++;
88 /**
89 * Skip rest of the field.
91 * Parameter buf: Buffer to read from.
92 * Parameter idx: Index to buffer. Updated.
93 * Parameter include_pipe: If true, also skip the '|'.
95 inline void skip_rest_of_field(const char* buf, size_t& idx, bool include_pipe) throw()
97 while(is_nonterminator(buf[idx]))
98 idx++;
99 if(include_pipe && buf[idx] == '|')
100 idx++;
104 * Serialize short.
106 inline void serialize_short(unsigned char* buf, short val)
108 buf[0] = static_cast<unsigned short>(val) >> 8;
109 buf[1] = static_cast<unsigned short>(val);
113 * Serialize short.
115 inline short unserialize_short(const unsigned char* buf)
117 return static_cast<short>((static_cast<unsigned short>(buf[0]) << 8) | static_cast<unsigned short>(buf[1]));
120 class port_type;
123 * Index triple.
125 * Note: The index 0 has to be mapped to triple (0, 0, 0).
127 struct port_index_triple
130 * If true, the other parameters are valid. Otherwise this index doesn't correspond to anything valid, but still
131 * exists. The reason for having invalid entries is to be backward-compatible.
133 bool valid;
135 * The port number.
137 unsigned port;
139 * The controller number.
141 unsigned controller;
143 * The control number.
145 unsigned control;
149 * Controller index mappings
151 struct port_index_map
154 * The poll indices.
156 std::vector<port_index_triple> indices;
158 * The logical controller mappings.
160 std::vector<std::pair<unsigned, unsigned>> logical_map;
162 * Legacy PCID mappings.
164 std::vector<std::pair<unsigned, unsigned>> pcid_map;
168 class port_type_set;
171 * A button or axis on controller
173 struct port_controller_button
176 * Type of button
178 enum _type
180 TYPE_NULL, //Nothing (except takes the slot).
181 TYPE_BUTTON, //Button.
182 TYPE_AXIS, //Axis.
183 TYPE_RAXIS, //Relative Axis (mouse).
184 TYPE_TAXIS //Throttle Axis (does not pair).
186 enum _type type;
187 char32_t symbol;
188 const char* name;
189 bool shadow;
190 int16_t rmin; //Range min.
191 int16_t rmax; //Range max.
192 bool centers;
194 * Is analog?
196 bool is_analog() const throw() { return type == (TYPE_AXIS) || (type == TYPE_RAXIS) || (type == TYPE_TAXIS); }
200 * A controller.
202 struct port_controller
204 const char* cclass; //Controller class.
205 const char* type; //Controller type.
206 unsigned button_count; //Number of buttons / axes.
207 struct port_controller_button** buttons; //Buttons.
209 * Count number of analog actions on this controller.
211 unsigned analog_actions() const;
213 * Get the axis numbers of specified analog action. If no valid axis exists, returns UINT_MAX.
215 std::pair<unsigned, unsigned> analog_action(unsigned i) const;
217 * Get specified button, or NULL if it doesn't exist.
219 struct port_controller_button* get(unsigned i);
223 * A port controller set
225 struct port_controller_set
227 unsigned controller_count; //Number of controllers.
228 struct port_controller** controllers; //Controllers.
230 * Get specified controller, or NULL if it doesn't exist.
232 struct port_controller* get(unsigned c) throw();
234 * Get specified button, or NULL if it doesn't exist.
236 struct port_controller_button* get(unsigned c, unsigned i) throw();
240 * Type of controller.
242 class port_type
244 public:
246 * Create a new port type.
248 * Parameter iname: Internal name of the port type.
249 * Parameter hname: Human-readable name of the port type.
250 * Parameter id: Identifier.
251 * Parameter ssize: The storage size in bytes.
252 * Throws std::bad_alloc: Not enough memory.
254 port_type(const std::string& iname, const std::string& hname, unsigned id,
255 size_t ssize) throw(std::bad_alloc);
257 * Unregister a port type.
259 virtual ~port_type() throw();
261 * Writes controller data into compressed representation.
263 * Parameter buffer: The buffer storing compressed representation of controller state.
264 * Parameter idx: Index of controller.
265 * Parameter ctrl: The control to manipulate.
266 * Parameter x: New value for control. Only zero/nonzero matters for buttons.
268 void (*write)(unsigned char* buffer, unsigned idx, unsigned ctrl, short x);
270 * Read controller data from compressed representation.
272 * Parameter buffer: The buffer storing compressed representation of controller state.
273 * Parameter idx: Index of controller.
274 * Parameter ctrl: The control to query.
275 * Returns: The value of control. Buttons return 0 or 1.
277 short (*read)(const unsigned char* buffer, unsigned idx, unsigned ctrl);
279 * Take compressed controller data and serialize it into textual representation.
281 * - The initial '|' is also written.
283 * Parameter buffer: The buffer storing compressed representation of controller state.
284 * Parameter textbuf: The text buffer to write to.
285 * Returns: Number of bytes written.
287 size_t (*serialize)(const unsigned char* buffer, char* textbuf);
289 * Unserialize textual representation into compressed controller state.
291 * - Only stops reading on '|', NUL, CR or LF in the final read field. That byte is not read.
293 * Parameter buffer: The buffer storing compressed representation of controller state.
294 * Parameter textbuf: The text buffer to read.
295 * Returns: Number of bytes read.
296 * Throws std::runtime_error: Bad serialization.
298 size_t (*deserialize)(unsigned char* buffer, const char* textbuf);
300 * Is the device legal for port?
302 * Parameter port: Port to query.
303 * Returns: Nonzero if legal, zero if illegal.
305 int (*legal)(unsigned port);
307 * Controller info.
309 port_controller_set* controller_info;
311 * Get number of used control indices on controller.
313 * Parameter controller: Number of controller.
314 * Returns: Number of used control indices.
316 unsigned (*used_indices)(unsigned controller);
318 * Human-readable name.
320 std::string hname;
322 * Number of bytes it takes to store this.
324 size_t storage_size;
326 * Name of port type.
328 std::string name;
330 * Id of the port.
332 unsigned pt_id;
334 * Is given controller present?
336 bool is_present(unsigned controller) const throw();
337 private:
338 port_type(const port_type&);
339 port_type& operator=(const port_type&);
343 * A set of port types.
345 class port_type_set
347 public:
349 * Create empty port type set.
351 port_type_set() throw();
353 * Make a port type set with specified types. If called again with the same parameters, returns the same object.
355 * Parameter types: The types.
356 * Parameter control_map: The control map
357 * Throws std::bad_alloc: Not enough memory.
358 * Throws std::runtime_error: Illegal port types.
360 static port_type_set& make(std::vector<port_type*> types, struct port_index_map control_map)
361 throw(std::bad_alloc, std::runtime_error);
363 * Compare sets for equality.
365 bool operator==(const port_type_set& s) const throw() { return this == &s; }
367 * Compare sets for non-equality.
369 bool operator!=(const port_type_set& s) const throw() { return this != &s; }
371 * Get offset of specified port.
373 * Parameter port: The number of port.
374 * Returns: The offset of port.
375 * Throws std::runtime_error: Bad port number.
377 size_t port_offset(unsigned port) const throw(std::runtime_error)
379 if(port >= port_count)
380 throw std::runtime_error("Invalid port index");
381 return port_offsets[port];
384 * Get type of specified port.
386 * Parameter port: The number of port.
387 * Returns: The port type.
388 * Throws std::runtime_error: Bad port number.
390 const class port_type& port_type(unsigned port) const throw(std::runtime_error)
392 if(port >= port_count)
393 throw std::runtime_error("Invalid port index");
394 return *(port_types[port]);
397 * Get number of ports.
399 * Returns: The port count.
401 unsigned ports() const throw()
403 return port_count;
406 * Get total size of controller data.
408 * Returns the size.
410 unsigned size() const throw()
412 return total_size;
415 * Get total index count.
417 unsigned indices() const throw()
419 return _indices.size();
422 * Look up the triplet for given control.
424 * Parameter index: The index to look up.
425 * Returns: The triplet (may not be valid).
426 * Throws std::runtime_error: Index out of range.
428 port_index_triple index_to_triple(unsigned index) const throw(std::runtime_error)
430 if(index >= _indices.size())
431 throw std::runtime_error("Invalid index");
432 return _indices[index];
435 * Translate triplet into index.
437 * Parameter port: The port.
438 * Parameter controller: The controller.
439 * Parameter _index: The control index.
440 * Returns: The index, or 0xFFFFFFFFUL if specified triple is not valid.
442 unsigned triple_to_index(unsigned port, unsigned controller, unsigned _index) const throw(std::runtime_error)
444 size_t place = port * port_multiplier + controller * controller_multiplier + _index;
445 if(place >= indices_size)
446 return 0xFFFFFFFFUL;
447 unsigned pindex = indices_tab[place];
448 if(pindex == 0xFFFFFFFFUL)
449 return 0xFFFFFFFFUL;
450 const struct port_index_triple& t = _indices[pindex];
451 if(!t.valid || t.port != port || t.controller != controller || t.control != _index)
452 return 0xFFFFFFFFUL;
453 return pindex;
456 * Return number of controllers connected.
458 * Returns: Number of controllers.
460 unsigned number_of_controllers() const throw()
462 return controllers.size();
465 * Lookup physical controller index corresponding to logical one.
467 * Parameter lcid: Logical controller id.
468 * Returns: Physical controller index (port, controller).
469 * Throws std::runtime_error: No such controller.
471 std::pair<unsigned, unsigned> lcid_to_pcid(unsigned lcid) const throw(std::runtime_error)
473 if(lcid >= controllers.size())
474 throw std::runtime_error("Bad logical controller");
475 return controllers[lcid];
478 * Return number of legacy PCIDs.
480 unsigned number_of_legacy_pcids() const throw()
482 return legacy_pcids.size();
485 * Lookup (port,controller) pair corresponding to given legacy pcid.
487 * Parameter pcid: The legacy pcid.
488 * Returns: The controller index.
489 * Throws std::runtime_error: No such controller.
491 std::pair<unsigned, unsigned> legacy_pcid_to_pair(unsigned pcid) const throw(std::runtime_error)
493 if(pcid >= legacy_pcids.size())
494 throw std::runtime_error("Bad legacy PCID");
495 return legacy_pcids[pcid];
497 private:
498 port_type_set(std::vector<class port_type*> types, struct port_index_map control_map);
499 size_t* port_offsets;
500 class port_type** port_types;
501 unsigned port_count;
502 size_t total_size;
503 std::vector<port_index_triple> _indices;
504 std::vector<std::pair<unsigned, unsigned>> controllers;
505 std::vector<std::pair<unsigned, unsigned>> legacy_pcids;
507 size_t port_multiplier;
508 size_t controller_multiplier;
509 size_t indices_size;
510 unsigned* indices_tab;
514 * Poll counter vector.
516 class pollcounter_vector
518 public:
520 * Create new pollcounter vector filled with all zeroes and all DRDY bits clear.
522 * Throws std::bad_alloc: Not enough memory.
524 pollcounter_vector() throw(std::bad_alloc);
526 * Create new pollcounter vector suitably sized for given type set.
528 * Parameter p: The port types.
529 * Throws std::bad_alloc: Not enough memory.
531 pollcounter_vector(const port_type_set& p) throw(std::bad_alloc);
533 * Destructor.
535 ~pollcounter_vector() throw();
537 * Copy the pollcounter_vector.
539 pollcounter_vector(const pollcounter_vector& v) throw(std::bad_alloc);
541 * Assign the pollcounter_vector.
543 pollcounter_vector& operator=(const pollcounter_vector& v) throw(std::bad_alloc);
545 * Zero all poll counters and clear all DRDY bits. System flag is cleared.
547 void clear() throw();
549 * Set all DRDY bits.
551 void set_all_DRDY() throw();
553 * Clear specified DRDY bit.
555 * Parameter port: The port.
556 * Parameter controller: The controller
557 * Parameter ctrl: The control id.
559 void clear_DRDY(unsigned port, unsigned controller, unsigned ctrl) throw()
561 unsigned i = types->triple_to_index(port, controller, ctrl);
562 if(i != 0xFFFFFFFFU)
563 clear_DRDY(i);
566 * Clear state of DRDY bit.
568 * Parameter idx: The control index.
570 void clear_DRDY(unsigned idx) throw();
572 * Get state of DRDY bit.
574 * Parameter port: The port.
575 * Parameter controller: The controller
576 * Parameter ctrl: The control id.
577 * Returns: The DRDY state.
579 bool get_DRDY(unsigned port, unsigned controller, unsigned ctrl) throw()
581 unsigned i = types->triple_to_index(port, controller, ctrl);
582 if(i != 0xFFFFFFFFU)
583 return get_DRDY(i);
584 else
585 return true;
588 * Get state of DRDY bit.
590 * Parameter idx: The control index.
591 * Returns: The DRDY state.
593 bool get_DRDY(unsigned idx) throw();
595 * Is any poll count nonzero or is system flag set?
597 * Returns: True if at least one poll count is nonzero or if system flag is set. False otherwise.
599 bool has_polled() throw();
601 * Read the actual poll count on specified control.
603 * Parameter port: The port.
604 * Parameter controller: The controller
605 * Parameter ctrl: The control id.
606 * Return: The poll count.
608 uint32_t get_polls(unsigned port, unsigned controller, unsigned ctrl) throw()
610 unsigned i = types->triple_to_index(port, controller, ctrl);
611 if(i != 0xFFFFFFFFU)
612 return get_polls(i);
613 else
614 return 0;
617 * Read the actual poll count on specified control.
619 * Parameter idx: The control index.
620 * Return: The poll count.
622 uint32_t get_polls(unsigned idx) throw();
624 * Increment poll count on specified control.
626 * Parameter port: The port.
627 * Parameter controller: The controller
628 * Parameter ctrl: The control id.
629 * Return: The poll count pre-increment.
631 uint32_t increment_polls(unsigned port, unsigned controller, unsigned ctrl) throw()
633 unsigned i = types->triple_to_index(port, controller, ctrl);
634 if(i != 0xFFFFFFFFU)
635 return increment_polls(i);
636 else
637 return 0;
640 * Increment poll count on specified index.
642 * Parameter idx: The index.
643 * Return: The poll count pre-increment.
645 uint32_t increment_polls(unsigned idx) throw();
647 * Get highest poll counter value.
649 * - System flag counts as 1 poll.
651 * Returns: The maximum poll count (at least 1 if system flag is set).
653 uint32_t max_polls() throw();
655 * Save state to memory block.
657 * Parameter mem: The memory block to save to.
658 * Throws std::bad_alloc: Not enough memory.
660 void save_state(std::vector<uint32_t>& mem) throw(std::bad_alloc);
662 * Load state from memory block.
664 * Parameter mem: The block from restore from.
666 void load_state(const std::vector<uint32_t>& mem) throw();
668 * Check if state can be loaded without errors.
670 * Returns: True if load is possible, false otherwise.
672 bool check(const std::vector<uint32_t>& mem) throw();
673 private:
674 uint32_t* ctrs;
675 const port_type_set* types;
679 * Single (sub)frame of controls.
681 class controller_frame
683 public:
685 * Default constructor. Invalid port types, dedicated memory.
687 controller_frame() throw();
689 * Create subframe of controls with specified controller types and dedicated memory.
691 * Parameter p: Types of ports.
693 controller_frame(const port_type_set& p) throw(std::runtime_error);
695 * Create subframe of controls with specified controller types and specified memory.
697 * Parameter memory: The backing memory.
698 * Parameter p: Types of ports.
700 * Throws std::runtime_error: NULL memory.
702 controller_frame(unsigned char* memory, const port_type_set& p) throw(std::runtime_error);
704 * Copy construct a frame. The memory will be dedicated.
706 * Parameter obj: The object to copy.
708 controller_frame(const controller_frame& obj) throw();
710 * Assign a frame. The types must either match or memory must be dedicated.
712 * Parameter obj: The object to copy.
713 * Returns: Reference to this.
714 * Throws std::runtime_error: The types don't match and memory is not dedicated.
716 controller_frame& operator=(const controller_frame& obj) throw(std::runtime_error);
718 * Get type of port.
720 * Parameter port: Number of port.
721 * Returns: The type of port.
723 const port_type& get_port_type(unsigned port) throw()
725 return types->port_type(port);
728 * Get port count.
730 unsigned get_port_count() throw()
732 return types->ports();
735 * Get index count.
737 unsigned get_index_count() throw()
739 return types->indices();
742 * Set types of ports.
744 * Parameter ptype: New port types.
745 * Throws std::runtime_error: Memory is mapped.
747 void set_types(const port_type_set& ptype) throw(std::runtime_error)
749 if(memory != backing)
750 throw std::runtime_error("Can't change type of mapped controller_frame");
751 types = &ptype;
754 * Get blank dedicated frame of same port types.
756 * Return blank frame.
758 controller_frame blank_frame() throw()
760 return controller_frame(*types);
763 * Check that types match.
765 * Parameter obj: Another object.
766 * Returns: True if types match, false otherwise.
768 bool types_match(const controller_frame& obj) const throw()
770 return types == obj.types;
773 * Perform XOR between controller frames.
775 * Parameter another: The another object.
776 * Returns: The XOR result (dedicated memory).
777 * Throws std::runtime_error: Type mismatch.
779 controller_frame operator^(const controller_frame& another) throw(std::runtime_error)
781 controller_frame x(*this);
782 if(types != another.types)
783 throw std::runtime_error("controller_frame::operator^: Type mismatch");
784 for(size_t i = 0; i < types->size(); i++)
785 x.backing[i] ^= another.backing[i];
786 return x;
789 * Set the sync flag.
791 * Parameter x: The value to set the sync flag to.
793 void sync(bool x) throw()
795 if(x)
796 backing[0] |= 1;
797 else
798 backing[0] &= ~1;
801 * Get the sync flag.
803 * Return value: Value of sync flag.
805 bool sync() throw()
807 return ((backing[0] & 1) != 0);
810 * Quick get sync flag for buffer.
812 static bool sync(const unsigned char* mem) throw()
814 return ((mem[0] & 1) != 0);
817 * Get size of frame.
819 * Returns: The number of bytes it takes to store frame of this type.
821 size_t size()
823 return types->size();
826 * Set axis/button value.
828 * Parameter port: The port.
829 * Parameter controller: The controller
830 * Parameter ctrl: The control id.
831 * Parameter x: The new value.
833 void axis3(unsigned port, unsigned controller, unsigned ctrl, short x) throw()
835 if(port >= types->ports())
836 return;
837 types->port_type(port).write(backing + types->port_offset(port), controller, ctrl, x);
840 * Set axis/button value.
842 * Parameter idx: Control index.
843 * Parameter x: The new value.
845 void axis2(unsigned idx, short x) throw()
847 port_index_triple t = types->index_to_triple(idx);
848 if(t.valid)
849 axis3(t.port, t.controller, t.control, x);
852 * Get axis/button value.
854 * Parameter port: The port.
855 * Parameter controller: The controller
856 * Parameter ctrl: The control id.
857 * Return value: The axis value.
859 short axis3(unsigned port, unsigned controller, unsigned ctrl) throw()
861 if(port >= types->ports())
862 return 0;
863 return types->port_type(port).read(backing + types->port_offset(port), controller, ctrl);
867 * Get axis/button value.
869 * Parameter idx: Index of control.
870 * Return value: The axis value.
872 short axis2(unsigned idx) throw()
874 port_index_triple t = types->index_to_triple(idx);
875 if(t.valid)
876 return axis3(t.port, t.controller, t.control);
877 else
878 return 0;
881 * Get controller display.
883 * Parameter port: The port.
884 * Parameter controller: The controller
885 * Parameter buf: Buffer to write nul-terminated display to.
887 void display(unsigned port, unsigned controller, char32_t* buf) throw();
889 * Is device present?
891 * Parameter port: The port.
892 * Parameter controller: The controller
893 * Returns: True if present, false if not.
895 bool is_present(unsigned port, unsigned controller) throw()
897 if(port >= types->ports())
898 return false;
899 return types->port_type(port).is_present(controller);
902 * Deserialize frame from text format.
904 * Parameter buf: The buffer containing text representation. Terminated by NUL, CR or LF.
905 * Throws std::runtime_error: Bad serialized representation.
907 void deserialize(const char* buf) throw(std::runtime_error)
909 size_t offset = 0;
910 for(size_t i = 0; i < types->ports(); i++) {
911 size_t s;
912 s = types->port_type(i).deserialize(backing + types->port_offset(i), buf + offset);
913 if(s != DESERIALIZE_SPECIAL_BLANK) {
914 offset += s;
915 while(is_nonterminator(buf[offset]))
916 offset++;
917 if(buf[offset] == '|')
918 offset++;
923 * Serialize frame to text format.
925 * Parameter buf: The buffer to write NUL-terminated text representation to.
927 void serialize(char* buf) throw()
929 size_t offset = 0;
930 for(size_t i = 0; i < types->ports(); i++) {
931 offset += types->port_type(i).serialize(backing + types->port_offset(i), buf + offset);
933 buf[offset++] = '\0';
936 * Return copy with dedicated memory.
938 * Parameter sync: If set, the frame will have sync flag set, otherwise it will have sync flag clear.
939 * Returns: Copy of this frame.
941 controller_frame copy(bool sync)
943 controller_frame c(*this);
944 c.sync(sync);
945 return c;
948 * Compare two frames.
950 * Parameter obj: Another frame.
951 * Returns: True if equal, false if not.
953 bool operator==(const controller_frame& obj) const throw()
955 if(!types_match(obj))
956 return false;
957 return !memcmp(backing, obj.backing, types->size());
960 * Compare two frames.
962 * Parameter obj: Another frame.
963 * Returns: True if not equal, false if equal.
965 bool operator!=(const controller_frame& obj) const throw()
967 return !(*this == obj);
970 * Get the port type set.
972 const port_type_set& porttypes()
974 return *types;
976 private:
977 unsigned char memory[MAXIMUM_CONTROLLER_FRAME_SIZE];
978 unsigned char* backing;
979 const port_type_set* types;
983 * Vector of controller frames.
985 class controller_frame_vector
987 public:
989 * Construct new controller frame vector.
991 controller_frame_vector() throw();
993 * Construct new controller frame vector.
995 * Parameter p: The port types.
997 controller_frame_vector(const port_type_set& p) throw();
999 * Destroy controller frame vector
1001 ~controller_frame_vector() throw();
1003 * Copy controller frame vector.
1005 * Parameter obj: The object to copy.
1006 * Throws std::bad_alloc: Not enough memory.
1008 controller_frame_vector(const controller_frame_vector& vector) throw(std::bad_alloc);
1010 * Assign controller frame vector.
1012 * Parameter obj: The object to copy.
1013 * Returns: Reference to this.
1014 * Throws std::bad_alloc: Not enough memory.
1016 controller_frame_vector& operator=(const controller_frame_vector& vector) throw(std::bad_alloc);
1018 * Blank vector and change the type of ports.
1020 * Parameter p: The port types.
1022 void clear(const port_type_set& p) throw(std::runtime_error);
1024 * Blank vector.
1026 void clear() throw()
1028 clear(*types);
1031 * Get number of subframes.
1033 size_t size()
1035 return frames;
1038 * Get the typeset.
1040 const port_type_set& get_types()
1042 return *types;
1045 * Access specified subframe.
1047 * Parameter x: The frame number.
1048 * Returns: The controller frame.
1049 * Throws std::runtime_error: Invalid frame index.
1051 controller_frame operator[](size_t x)
1053 size_t page = x / frames_per_page;
1054 size_t pageoffset = frame_size * (x % frames_per_page);
1055 if(x >= frames)
1056 throw std::runtime_error("controller_frame_vector::operator[]: Illegal index");
1057 if(page != cache_page_num) {
1058 cache_page = &pages[page];
1059 cache_page_num = page;
1061 return controller_frame(cache_page->content + pageoffset, *types);
1064 * Append a subframe.
1066 * Parameter frame: The frame to append.
1067 * Throws std::bad_alloc: Not enough memory.
1068 * Throws std::runtime_error: Port type mismatch.
1070 void append(controller_frame frame) throw(std::bad_alloc, std::runtime_error);
1072 * Change length of vector.
1074 * - Reducing length of vector will discard extra elements.
1075 * - Extending length of vector will add all-zero elements.
1077 * Parameter newsize: New size of vector.
1078 * Throws std::bad_alloc: Not enough memory.
1080 void resize(size_t newsize) throw(std::bad_alloc);
1082 * Walk the indexes of sync subframes.
1084 * - If frame is in range and there is at least one more sync subframe after it, the index of first sync subframe
1085 * after given frame.
1086 * - If frame is in range, but there are no more sync subframes after it, the length of vector is returned.
1087 * - If frame is out of range, the given frame is returned.
1089 * Parameter frame: The frame number to start search from.
1090 * Returns: Index of next sync frame.
1092 size_t walk_sync(size_t frame) throw()
1094 return walk_helper(frame, true);
1097 * Get number of subframes in frame. The given subframe is assumed to be sync subframe.
1099 * - The return value is the same as (walk_sync(frame) - frame).
1101 * Parameter frame: The frame number to start search from.
1102 * Returns: Number of subframes in this frame.
1104 size_t subframe_count(size_t frame) throw()
1106 return walk_helper(frame, false);
1109 * Count number of subframes in vector with sync flag set.
1111 * Returns: The number of frames.
1113 size_t count_frames() throw();
1115 * Return blank controller frame with correct type and dedicated memory.
1117 * Parameter sync: If set, the frame will have sync flag set, otherwise it will have sync flag clear.
1118 * Returns: Blank frame.
1120 controller_frame blank_frame(bool sync)
1122 controller_frame c(*types);
1123 c.sync(sync);
1124 return c;
1126 private:
1127 class page
1129 public:
1130 page() { memset(content, 0, CONTROLLER_PAGE_SIZE); }
1131 unsigned char content[CONTROLLER_PAGE_SIZE];
1133 size_t frames_per_page;
1134 size_t frame_size;
1135 size_t frames;
1136 const port_type_set* types;
1137 size_t cache_page_num;
1138 page* cache_page;
1139 std::map<size_t, page> pages;
1140 size_t walk_helper(size_t frame, bool sflag) throw();
1141 void clear_cache()
1143 cache_page_num = 0;
1144 cache_page_num--;
1145 cache_page = NULL;
1150 * Get generic default system port type.
1152 port_type& get_default_system_port_type();
1154 #endif