You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2019/12/05 12:36:19 UTC
[mynewt-core] 02/06: sys/console: Add in-RAM implementation of
history
This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit ecc5cfee49fd54039f458b8b382b61d5ea3ae92a
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Wed Nov 13 15:34:41 2019 +0100
sys/console: Add in-RAM implementation of history
Code is mostly copied from existing console.c file.
---
sys/console/full/history_ram/pkg.yml | 32 ++++
sys/console/full/history_ram/src/history_ram.c | 234 +++++++++++++++++++++++++
sys/console/full/history_ram/syscfg.yml | 27 +++
3 files changed, 293 insertions(+)
diff --git a/sys/console/full/history_ram/pkg.yml b/sys/console/full/history_ram/pkg.yml
new file mode 100644
index 0000000..870da71
--- /dev/null
+++ b/sys/console/full/history_ram/pkg.yml
@@ -0,0 +1,32 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: sys/console/full/history_ram
+pkg.description: RAM only console history.
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - "@apache-mynewt-core/hw/hal"
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/sys/console/full"
+
+pkg.init:
+ console_history_ram_pkg_init: 'MYNEWT_VAL(CONSOLE_HISTORY_RAM_SYSINIT_STAGE)'
diff --git a/sys/console/full/history_ram/src/history_ram.c b/sys/console/full/history_ram/src/history_ram.c
new file mode 100644
index 0000000..e08fda0
--- /dev/null
+++ b/sys/console/full/history_ram/src/history_ram.c
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stdint.h>
+#include <ctype.h>
+#include <os/mynewt.h>
+#include <console/history.h>
+
+#ifndef bssnz_t
+/* Just in case bsp.h does not define it, in this case console history will
+ * not be preserved across software resets
+ */
+#define bssnz_t
+#endif
+
+#define HISTORY_SIZE MYNEWT_VAL(CONSOLE_HISTORY_RAM_HISTORY_SIZE)
+
+bssnz_t static char console_hist_lines[HISTORY_SIZE][ MYNEWT_VAL(CONSOLE_MAX_INPUT_LEN) ];
+
+bssnz_t static struct console_hist {
+ uint32_t magic;
+ uint8_t head;
+ uint8_t count;
+ char *lines[HISTORY_SIZE + 1];
+} console_hist;
+
+static size_t
+trim_whitespace(const char *str, char *out, size_t out_size)
+{
+ const char *end;
+ size_t len;
+
+ if (out_size == 0) {
+ return 0;
+ }
+
+ /* Skip leading space */
+ while (isspace((unsigned char)*str)) {
+ str++;
+ }
+
+ if (*str == 0) { /* All spaces? */
+ *out = 0;
+ return 0;
+ }
+
+ /* Skip trailing space */
+ end = str + strlen(str) - 1;
+ while (isspace((unsigned char)*end)) {
+ end--;
+ }
+
+ end++;
+
+ /* Set output size to minimum of trimmed string length and buffer size minus 1 */
+ len = min(end - str, out_size - 1);
+
+ /* Copy trimmed string and add null terminator */
+ memcpy(out, str, len);
+ out[len] = 0;
+
+ return len;
+}
+
+static uint8_t
+ring_buf_next(uint8_t i)
+{
+ return (uint8_t) ((i + 1) % HISTORY_SIZE);
+}
+
+static uint8_t
+ring_buf_prev(uint8_t i)
+{
+ return i == 0 ? HISTORY_SIZE - 1 : i - 1;
+}
+
+static bool
+console_hist_is_full(void)
+{
+ return console_hist.count == HISTORY_SIZE;
+}
+
+static bool
+console_hist_move_to_head(char *line)
+{
+ struct console_hist *sh = &console_hist;
+ char *match = NULL;
+ uint8_t prev;
+ uint8_t curr;
+ uint8_t left;
+
+ left = sh->count;
+ curr = ring_buf_prev(sh->head);
+ while (left) {
+ if (strcmp(sh->lines[curr], line) == 0) {
+ match = sh->lines[curr];
+ break;
+ }
+ curr = ring_buf_next(curr);
+ left--;
+ }
+
+ if (!match) {
+ return false;
+ }
+
+ prev = curr;
+ curr = ring_buf_next(curr);
+ while (curr != sh->head) {
+ sh->lines[prev] = sh->lines[curr];
+ prev = curr;
+ curr = ring_buf_next(curr);
+ }
+
+ sh->lines[prev] = match;
+
+ return true;
+}
+
+history_handle_t
+console_history_add(const char *line)
+{
+ struct console_hist *sh = &console_hist;
+ char buf[MYNEWT_VAL(CONSOLE_MAX_INPUT_LEN)];
+ size_t len;
+
+ len = trim_whitespace(line, buf, sizeof(buf));
+ if (len == 0) {
+ return 0;
+ }
+
+ if (console_hist_move_to_head(buf)) {
+ return 1;
+ }
+
+ strcpy(sh->lines[sh->head], buf);
+ sh->head = ring_buf_next(sh->head);
+ if (!console_hist_is_full()) {
+ sh->count++;
+ }
+ return 1;
+}
+
+history_handle_t
+console_history_find(history_handle_t start, history_find_type_t search_type,
+ void *arg)
+{
+ int num;
+
+ switch (search_type) {
+ case HFT_PREV:
+ num = start + (arg ? *(int *)arg : 1);
+ if (num > console_hist.count) {
+ return 0;
+ }
+ return num;
+ case HFT_NEXT:
+ num = start - (arg ? *(int *)arg : 1);
+ if (num <= 0) {
+ return 0;
+ }
+ return num;
+ default:
+ return 0;
+ }
+}
+
+int
+console_history_get(history_handle_t handle, size_t offset, char *buf,
+ size_t buf_size)
+{
+ const char *line;
+ size_t line_len;
+ int num = (int)handle;
+
+ if (num > console_hist.count || num < 1) {
+ return SYS_EINVAL;
+ }
+
+ if (num <= console_hist.head) {
+ line = console_hist.lines[console_hist.head - num];
+ } else {
+ line = console_hist.lines[console_hist.head + HISTORY_SIZE - num];
+ }
+
+ line_len = strlen(line);
+ if (line_len <= offset) {
+ return 0;
+ }
+ line += offset;
+ line_len -= offset;
+
+ if (line_len > buf_size) {
+ line_len = buf_size;
+ }
+ memcpy(buf, line, line_len);
+
+ return line_len;
+}
+
+int
+console_history_ram_pkg_init(void)
+{
+ struct console_hist *sh = &console_hist;
+ int i;
+
+ if (sh->magic != 0xBABEFACE) {
+ memset(console_hist_lines, 0, sizeof(console_hist_lines));
+ memset(&console_hist, 0, sizeof(console_hist));
+
+ for (i = 0; i < HISTORY_SIZE; i++) {
+ sh->lines[i] = console_hist_lines[i];
+ }
+ sh->magic = 0xBABEFACE;
+ }
+
+ return 0;
+}
diff --git a/sys/console/full/history_ram/syscfg.yml b/sys/console/full/history_ram/syscfg.yml
new file mode 100644
index 0000000..5fdb86a
--- /dev/null
+++ b/sys/console/full/history_ram/syscfg.yml
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+syscfg.defs:
+ CONSOLE_HISTORY_RAM_HISTORY_SIZE:
+ description: >
+ Number of lines to be stored in console history.
+ value: 10
+ CONSOLE_HISTORY_RAM_SYSINIT_STAGE:
+ description: >
+ Sysinit stage for the in ram console history.
+ value: 1000