working on the layer-stack; finished! (for now)
- did not move any of the layer-stack code into code for a 'flex-array' type, or something similar. i'm thinking that most of the things the layer-stack does aren't sufficiently generalizable. for instance, one of the biggest general functions in the layer-stack implementation is `_shift_elements()`; but shifing elements is only something you want to do when you're messing with elements not on the the top of the stack (which breaks the definition of a general stack). so i think i'll leave things as they are for now. the functionality can always be split out later if it turns out to be needed elsewhere.partial-rewrite
parent
e4b1717657
commit
a5e2c20a84
|
@ -125,6 +125,15 @@
|
|||
according to the C standard, and I didn't see AVRs mentioned; and AVRs don't
|
||||
typically run an OS anyway), but still quite interesting.
|
||||
|
||||
* [integral conversion from negative signed to unsigned integer]
|
||||
(http://www.rhinocerus.net/forum/language-c-moderated/649336-integral-conversion-negative-signed-unsigned-integer.html)
|
||||
What happens if you return `-1` from a `uint8_t` function (or assign `-1` to
|
||||
a `uint8_t`)?
|
||||
|
||||
* [Mod Function and Negative Numbers]
|
||||
(http://mathforum.org/library/drmath/view/52343.html)
|
||||
`(-1)%5` in python returns `4` (just like it should)
|
||||
|
||||
### C++ Stuff
|
||||
|
||||
* [Google C++ Style Guide]
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
* Prefixes: `keys__`, [none]
|
||||
*
|
||||
* Usage: `#define` `KEYS__DEFAULT` and `KEYS__SHIFTED` before `#include`ing.
|
||||
*
|
||||
* TODO: add media and mouse keys (after i figure out which OSs are supposed to
|
||||
* support which keys)
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -11,10 +11,6 @@
|
|||
*
|
||||
* This file is meant to be included and used by the keyboard layout
|
||||
* implemenmtation.
|
||||
*
|
||||
* TODO: add
|
||||
* - `layer_stack__find_id()`
|
||||
* - `uint8_t offset` as an argument to ...push()
|
||||
*/
|
||||
|
||||
|
||||
|
@ -24,10 +20,13 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
uint8_t layer_stack__peek (uint8_t offset);
|
||||
uint8_t layer_stack__push (uint8_t layer_id, uint8_t layer_number);
|
||||
uint8_t layer_stack__pop_id (uint8_t layer_id);
|
||||
uint8_t layer_stack__size (void);
|
||||
uint8_t layer_stack__peek (uint8_t offset);
|
||||
uint8_t layer_stack__push ( uint8_t offset,
|
||||
uint8_t layer_id,
|
||||
uint8_t layer_number );
|
||||
uint8_t layer_stack__pop_id (uint8_t layer_id);
|
||||
uint8_t layer_stack__find_id (uint8_t layer_id);
|
||||
uint8_t layer_stack__size (void);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -42,11 +41,11 @@ uint8_t layer_stack__size (void);
|
|||
|
||||
// === layer_stack__peek() ===
|
||||
/** functions/layer_stack__peek/description
|
||||
* Return the `offset`th element of the layer stack
|
||||
* Return the layer-number of the `offset`th element of the layer-stack
|
||||
*
|
||||
* Arguments:
|
||||
* - `offset`: the offset of the element to return (with the top element being
|
||||
* `offset = 0`)
|
||||
* - `offset`: the `offset` of the element to return (with the top element
|
||||
* being `offset = 0`)
|
||||
*
|
||||
* Returns:
|
||||
* - success: the layer-number of the `offset`th element (which may be `0`), or
|
||||
|
@ -55,39 +54,59 @@ uint8_t layer_stack__size (void);
|
|||
|
||||
// === layer_stack__push() ===
|
||||
/** functions/layer_stack__push/description
|
||||
* Push the given element onto the top of the layer stack (or update the
|
||||
* element if it already exists)
|
||||
* Push the given element into the layer-stack on top of the element with the
|
||||
* given `offset` (or update the element with the given layer-id, if it already
|
||||
* exists)
|
||||
*
|
||||
* Arguments:
|
||||
* - `layer_id`: the ID of the layer to push
|
||||
* - `offset`: the `offset` of the element on top of which to push the given
|
||||
* element (with the top element being `offset = 0`)
|
||||
* - `layer_id`: the layer-id of the layer to push
|
||||
* - `layer_number`: the layer-number of the layer to push
|
||||
*
|
||||
* Returns:
|
||||
* - success: the offset of the element that was pushed (or updated)
|
||||
* - success: the `offset` of the element that was pushed (or updated)
|
||||
* - failure: an invalid `offset`
|
||||
*
|
||||
* Notes:
|
||||
* - If the given layer-id is not present in the stack, a new element is
|
||||
* created and placed on the top of the stack (as expected)
|
||||
* - If the given layer-id is present in the stack, the element with that ID is
|
||||
* updated
|
||||
* - If the given layer-id is not present in the stack, and a new element is
|
||||
* created and pushed on top of the element with the given `offset`, the new
|
||||
* element will now be at position `offset`, since `offset` is the distance
|
||||
* from the top of the stack
|
||||
* - If the given layer-id is present in the stack, the element with that
|
||||
* layer-id is updated; this preserves the expectation that all layer-id's in
|
||||
* the stack will be unique
|
||||
*/
|
||||
|
||||
// === layer_stack__pop_id() ===
|
||||
/** functions/layer_stack__pop_id/description
|
||||
* Pop the given element (by ID) out from the layer stack
|
||||
* Pop the given element (by ID) out from the layer-stack
|
||||
*
|
||||
* Arguments:
|
||||
* - `layer_id`: the ID of the layer to pop (remove)
|
||||
* - `layer_id`: the layer-id of the layer to pop (remove)
|
||||
*
|
||||
* Returns:
|
||||
* - success: the offset of the element that was popped (removed)
|
||||
* - success: the `offset` of the element that was popped (removed)
|
||||
* - failure: an invalid `offset`
|
||||
*/
|
||||
|
||||
// === layer_stack__find_id() ===
|
||||
/** functions/layer_stack__find_id/description
|
||||
* Find an element element by ID
|
||||
*
|
||||
* Arguments:
|
||||
* - `layer_id`: the layer-id of the layer to find
|
||||
*
|
||||
* Returns:
|
||||
* - success: the `offset` of the element that was found
|
||||
* - failure: an invalid `offset`
|
||||
*/
|
||||
|
||||
// === layer_stack__size ===
|
||||
/** functions/layer_stack__size/description
|
||||
* Return the current size (height) of the layer stack
|
||||
* Return the current size (height) of the layer-stack
|
||||
*
|
||||
* Returns:
|
||||
* - success: the current size (height) of the layer stack (`0` if empty)
|
||||
* - success: the current size (height) of the layer-stack (`0` if empty)
|
||||
*/
|
||||
|
||||
|
|
|
@ -6,17 +6,13 @@
|
|||
|
||||
/** description
|
||||
* Implements the layer-stack defined in "../layer-stack.h"
|
||||
*
|
||||
* TODO:
|
||||
* - see the '.h' for interface TODOs
|
||||
* - should we split most of this functionality into a general 'flex_array' or
|
||||
* something? we probably should... think about how to do that.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "../layer-stack.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -43,6 +39,21 @@ element_t * _stack = NULL; // (to be used as an array)
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** functions/_is_valid_offset/description
|
||||
* Predicate indicating whether the given offset is valid
|
||||
*
|
||||
* Arguments:
|
||||
* - `offset`: the offset to test
|
||||
*
|
||||
* Returns:
|
||||
* - `true`: if the offset is valid
|
||||
* - `false`: if the offset is not valid
|
||||
*/
|
||||
static bool _is_valid_offset(uint8_t offset) {
|
||||
// both values are `uint8_t`, so no need to check `offset >= 0`
|
||||
return ( offset < _filled );
|
||||
}
|
||||
|
||||
/** functions/_resize_stack/description
|
||||
* Resize the stack (in increments of `BLOCK_SIZE` positions) so that at least
|
||||
* 1 and no more than `MARGIN + BLOCK_SIZE - 1` positions are unused.
|
||||
|
@ -71,9 +82,9 @@ static uint8_t _resize_stack(void) {
|
|||
* Shift the elements above the given location either up or down by one.
|
||||
*
|
||||
* Arguments:
|
||||
* - `offset`: The offset of the element above which to operate (with the top
|
||||
* - `offset`: the offset of the element above which to operate (with the top
|
||||
* element being `offset = 0`)
|
||||
* - `up` : Whether to shift the elements "up" or "down" the stack
|
||||
* - `up` : whether to shift the elements "up" or "down" the stack
|
||||
*
|
||||
* Returns:
|
||||
* - success: `0`
|
||||
|
@ -100,7 +111,7 @@ static uint8_t _resize_stack(void) {
|
|||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | allocated = 7 filled = 5
|
||||
* +---+---+---+---+---+---+---+
|
||||
* ^
|
||||
* ` offset = 3
|
||||
* `- offset = 3
|
||||
*
|
||||
*
|
||||
* copy up: start = 4 = top = filled-1
|
||||
|
@ -114,7 +125,7 @@ static uint8_t _resize_stack(void) {
|
|||
*/
|
||||
static uint8_t _shift_elements(uint8_t offset, bool up) {
|
||||
uint8_t margin = _allocated - _filled;
|
||||
if ( offset < 0 || offset > _filled-1 || (up && (margin==0)) )
|
||||
if ( (!_is_valid_offset(offset)) || (up && (margin==0)) )
|
||||
return 1; // failure
|
||||
|
||||
uint8_t start = (up) ? _filled-1 : _filled-offset ;
|
||||
|
@ -131,26 +142,68 @@ static uint8_t _shift_elements(uint8_t offset, bool up) {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t layer_stack__peek (uint8_t offset) {
|
||||
if ( offset < 0 || offset > _filled-1 )
|
||||
uint8_t layer_stack__peek(uint8_t offset) {
|
||||
if (! _is_valid_offset(offset) )
|
||||
return 0; // default
|
||||
|
||||
return _stack[filled-1-offset].number;
|
||||
return _stack[_filled-1-offset].number;
|
||||
}
|
||||
|
||||
// note: must resize before shifting up, otherwise there may not be enough room
|
||||
// for the new element
|
||||
uint8_t layer_stack__push (uint8_t layer_id, uint8_t layer_number) {
|
||||
// need to add `offset` as an argument; see '.h'
|
||||
// for the new element; should resize before incrementing `_filled`, so as not
|
||||
// to grow the stack unless we actually need to
|
||||
uint8_t layer_stack__push( uint8_t offset,
|
||||
uint8_t layer_id,
|
||||
uint8_t layer_number ) {
|
||||
|
||||
uint8_t ret = 0;
|
||||
uint8_t existing_element_offset = layer_stack__find_id(layer_id);
|
||||
|
||||
if ( _is_valid_offset(existing_element_offset) ) {
|
||||
offset = existing_element_offset;
|
||||
|
||||
} else {
|
||||
_resize_stack(); // at least 1 element will be open after this
|
||||
|
||||
if (offset != 0)
|
||||
// this will catch invalid offsets
|
||||
ret = _shift_elements(offset-1, true);
|
||||
|
||||
if (!ret)
|
||||
_filled++; // (effects the meaning of `offset` below)
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
return -1; // failure: return an invalid offset
|
||||
} else {
|
||||
_stack[_filled-1-offset].id = layer_id;
|
||||
_stack[_filled-1-offset].number = layer_number;
|
||||
return offset; // success
|
||||
}
|
||||
}
|
||||
|
||||
// note: should resize after shifting down, so as to only leave `MARGIN`
|
||||
// elements free in the stack
|
||||
uint8_t layer_stack__pop_id (uint8_t layer_id) {
|
||||
// will use find_id(), which isn't written yet; see '.h'
|
||||
// note: should resize after shifting down and decrementing `_filled`, so as to
|
||||
// only leave `MARGIN` elements free in the stack
|
||||
uint8_t layer_stack__pop_id(uint8_t layer_id) {
|
||||
uint8_t offset = layer_stack__find_id(layer_id);
|
||||
uint8_t ret = _shift_elements(offset, false); // will catch invalid offsets
|
||||
if (ret) {
|
||||
return -1; // failure: return an invalid offset
|
||||
} else {
|
||||
_filled--;
|
||||
_resize_stack();
|
||||
return offset; // success
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t layer_stack__size (void) {
|
||||
uint8_t layer_stack__find_id(uint8_t layer_id) {
|
||||
for(uint8_t i=0; i<_filled; i++)
|
||||
if (_stack[i].id == layer_id)
|
||||
return _filled-1-i; // offset
|
||||
return -1; // failure: return an invalid offset
|
||||
}
|
||||
|
||||
uint8_t layer_stack__size(void) {
|
||||
return _filled;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue