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
Ben Blazak 2013-04-18 17:12:58 -07:00
parent e4b1717657
commit a5e2c20a84
4 changed files with 128 additions and 44 deletions

View File

@ -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]

View File

@ -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)
*/

View File

@ -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)
*/

View File

@ -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;
}