123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- #include <shell/shell_history.h>
- #include <string.h>
- struct shell_history_item {
- sys_dnode_t dnode;
- uint16_t len;
- uint16_t padding;
- char data[0];
- };
- void z_shell_history_mode_exit(struct shell_history *history)
- {
- history->current = NULL;
- }
- bool z_shell_history_get(struct shell_history *history, bool up,
- uint8_t *dst, uint16_t *len)
- {
- struct shell_history_item *h_item;
- sys_dnode_t *l_item;
- if (sys_dlist_is_empty(&history->list)) {
- *len = 0U;
- return false;
- }
- if (!up) {
- if (history->current == NULL) {
-
- *len = 0U;
- return false;
- }
- l_item = sys_dlist_peek_prev_no_check(&history->list,
- history->current);
- } else {
- l_item = (history->current == NULL) ?
- sys_dlist_peek_head_not_empty(&history->list) :
- sys_dlist_peek_next_no_check(&history->list, history->current);
- }
- history->current = l_item;
- h_item = CONTAINER_OF(l_item, struct shell_history_item, dnode);
- if (l_item) {
- memcpy(dst, h_item->data, h_item->len);
- *len = h_item->len;
- dst[*len] = '\0';
- return true;
- }
- *len = 0U;
- return false;
- }
- static void add_to_head(struct shell_history *history,
- struct shell_history_item *item,
- uint8_t *src, size_t len, uint16_t padding)
- {
- item->len = len;
- item->padding = padding;
- memcpy(item->data, src, len);
- sys_dlist_prepend(&history->list, &item->dnode);
- }
- static bool remove_from_tail(struct shell_history *history)
- {
- sys_dnode_t *l_item;
- struct shell_history_item *h_item;
- uint32_t total_len;
- if (sys_dlist_is_empty(&history->list)) {
- return false;
- }
- l_item = sys_dlist_peek_tail(&history->list);
- sys_dlist_remove(l_item);
- h_item = CONTAINER_OF(l_item, struct shell_history_item, dnode);
- total_len = offsetof(struct shell_history_item, data) +
- h_item->len + h_item->padding;
- ring_buf_get_finish(history->ring_buf, total_len);
- return true;
- }
- void z_shell_history_purge(struct shell_history *history)
- {
- while (remove_from_tail(history)) {
- }
- }
- void z_shell_history_put(struct shell_history *history, uint8_t *line,
- size_t len)
- {
- sys_dnode_t *l_item;
- struct shell_history_item *h_item;
- uint32_t total_len = len + offsetof(struct shell_history_item, data);
- uint32_t claim_len;
- uint32_t claim2_len;
- uint16_t padding = (~total_len + 1) & (sizeof(void *) - 1);
-
- total_len += padding;
- if (total_len > ring_buf_capacity_get(history->ring_buf)) {
- return;
- }
- z_shell_history_mode_exit(history);
- if (len == 0) {
- return;
- }
- l_item = sys_dlist_peek_head(&history->list);
- h_item = CONTAINER_OF(l_item, struct shell_history_item, dnode);
- if (l_item &&
- (h_item->len == len) &&
- (memcmp(h_item->data, line, len) == 0)) {
-
- return;
- }
- do {
- claim_len = ring_buf_put_claim(history->ring_buf,
- (uint8_t **)&h_item, total_len);
-
- if (claim_len < total_len) {
- claim2_len =
- ring_buf_put_claim(history->ring_buf,
- (uint8_t **)&h_item, total_len);
- if (claim2_len == total_len) {
- ring_buf_put_finish(history->ring_buf,
- claim_len);
- padding += claim_len;
- claim_len = total_len;
- }
- }
- if (claim_len == total_len) {
- add_to_head(history, h_item, line, len, padding);
- ring_buf_put_finish(history->ring_buf, claim_len);
- break;
- }
- ring_buf_put_finish(history->ring_buf, 0);
- if (remove_from_tail(history) == false) {
- __ASSERT_NO_MSG(ring_buf_is_empty(history->ring_buf));
-
- ring_buf_reset(history->ring_buf);
- }
- } while (1);
- }
- void z_shell_history_init(struct shell_history *history)
- {
- sys_dlist_init(&history->list);
- history->current = NULL;
- }
|