Ken Yourek / ucmd

Dependents:   nucleo_ucmd_helloworld

Committer:
kyourek
Date:
Mon Oct 12 21:09:07 2015 +0000
Revision:
0:9e2fc73e5a12
Initial commit of the ucmd library for mbed.; https://github.com/kyourek/ucmd

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kyourek 0:9e2fc73e5a12 1 #include <stdlib.h>
kyourek 0:9e2fc73e5a12 2 #include <string.h>
kyourek 0:9e2fc73e5a12 3 #include "ucmd_internal.h"
kyourek 0:9e2fc73e5a12 4
kyourek 0:9e2fc73e5a12 5 const char ucTok_separator = '\0';
kyourek 0:9e2fc73e5a12 6 const char uc_cmd_terminator = '\n';
kyourek 0:9e2fc73e5a12 7
kyourek 0:9e2fc73e5a12 8 static ucBool is_char_digit(char c) {
kyourek 0:9e2fc73e5a12 9 /* The native isdigit function in ctype.h was giving some weird behavior in the uVision simulator. */
kyourek 0:9e2fc73e5a12 10 static const char *digits = "0123456789";
kyourek 0:9e2fc73e5a12 11 const char *d;
kyourek 0:9e2fc73e5a12 12 for (d = digits; *d; d++) {
kyourek 0:9e2fc73e5a12 13 if (*d == c) {
kyourek 0:9e2fc73e5a12 14 return ucBool_TRUE;
kyourek 0:9e2fc73e5a12 15 }
kyourek 0:9e2fc73e5a12 16 }
kyourek 0:9e2fc73e5a12 17 return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 18 }
kyourek 0:9e2fc73e5a12 19
kyourek 0:9e2fc73e5a12 20 int ucTok_get_length(ucTok *p) {
kyourek 0:9e2fc73e5a12 21 int length;
kyourek 0:9e2fc73e5a12 22 if (NULL == p) return 0;
kyourek 0:9e2fc73e5a12 23
kyourek 0:9e2fc73e5a12 24 for (length = 0; *p != ucTok_separator; length++, p++);
kyourek 0:9e2fc73e5a12 25
kyourek 0:9e2fc73e5a12 26 return length;
kyourek 0:9e2fc73e5a12 27 }
kyourek 0:9e2fc73e5a12 28
kyourek 0:9e2fc73e5a12 29 const char *ucTok_get_value(ucTok *p) {
kyourek 0:9e2fc73e5a12 30 if (NULL == p) return NULL;
kyourek 0:9e2fc73e5a12 31 return (const char*)p;
kyourek 0:9e2fc73e5a12 32 }
kyourek 0:9e2fc73e5a12 33
kyourek 0:9e2fc73e5a12 34 ucBool ucTok_equals(ucTok *p, const char *value) {
kyourek 0:9e2fc73e5a12 35 int i, len;
kyourek 0:9e2fc73e5a12 36
kyourek 0:9e2fc73e5a12 37 /* check if these pointers are the same */
kyourek 0:9e2fc73e5a12 38 if (value == p) return ucBool_TRUE;
kyourek 0:9e2fc73e5a12 39
kyourek 0:9e2fc73e5a12 40 /* make sure neither arg is null */
kyourek 0:9e2fc73e5a12 41 if (NULL == p) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 42 if (NULL == value) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 43
kyourek 0:9e2fc73e5a12 44 /* check if the string lengths are the same */
kyourek 0:9e2fc73e5a12 45 len = ucTok_get_length(p);
kyourek 0:9e2fc73e5a12 46 if (strlen(value) != len) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 47
kyourek 0:9e2fc73e5a12 48 /* check for character equality */
kyourek 0:9e2fc73e5a12 49 for (i = 0; i < len; i++) {
kyourek 0:9e2fc73e5a12 50 if (p[i] != value[i]) {
kyourek 0:9e2fc73e5a12 51 return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 52 }
kyourek 0:9e2fc73e5a12 53 }
kyourek 0:9e2fc73e5a12 54
kyourek 0:9e2fc73e5a12 55 /* if we got here, then the strings are equal */
kyourek 0:9e2fc73e5a12 56 return ucBool_TRUE;
kyourek 0:9e2fc73e5a12 57 }
kyourek 0:9e2fc73e5a12 58
kyourek 0:9e2fc73e5a12 59 ucBool ucTok_is_numeric(ucTok *p) {
kyourek 0:9e2fc73e5a12 60 int i, len;
kyourek 0:9e2fc73e5a12 61 ucBool dec_found;
kyourek 0:9e2fc73e5a12 62
kyourek 0:9e2fc73e5a12 63 /* check if p is NULL */
kyourek 0:9e2fc73e5a12 64 if (NULL == p) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 65
kyourek 0:9e2fc73e5a12 66 /* get the length of the string */
kyourek 0:9e2fc73e5a12 67 len = ucTok_get_length(p);
kyourek 0:9e2fc73e5a12 68
kyourek 0:9e2fc73e5a12 69 /* numbers need to have at least 1 character */
kyourek 0:9e2fc73e5a12 70 if (len < 1) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 71
kyourek 0:9e2fc73e5a12 72 /* we are allowed to start with a '-' or '.' for negative numbers and decimals */
kyourek 0:9e2fc73e5a12 73 if ((p[0] == '-') || (p[0] == '.')) {
kyourek 0:9e2fc73e5a12 74
kyourek 0:9e2fc73e5a12 75 /* but we need more than 1 char if we do */
kyourek 0:9e2fc73e5a12 76 if (len < 2) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 77 }
kyourek 0:9e2fc73e5a12 78
kyourek 0:9e2fc73e5a12 79 // initialize vars
kyourek 0:9e2fc73e5a12 80 dec_found = ucBool_FALSE;
kyourek 0:9e2fc73e5a12 81
kyourek 0:9e2fc73e5a12 82 /* loop through the chars */
kyourek 0:9e2fc73e5a12 83 for (i = 0; i < len; i++) {
kyourek 0:9e2fc73e5a12 84
kyourek 0:9e2fc73e5a12 85 switch(p[i]) {
kyourek 0:9e2fc73e5a12 86
kyourek 0:9e2fc73e5a12 87 /* allow a dash only at the beginning */
kyourek 0:9e2fc73e5a12 88 case '-':
kyourek 0:9e2fc73e5a12 89 if (i != 0) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 90 break;
kyourek 0:9e2fc73e5a12 91
kyourek 0:9e2fc73e5a12 92 /* allow only 1 dot */
kyourek 0:9e2fc73e5a12 93 case '.':
kyourek 0:9e2fc73e5a12 94 if (dec_found) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 95 dec_found = ucBool_TRUE;
kyourek 0:9e2fc73e5a12 96 break;
kyourek 0:9e2fc73e5a12 97
kyourek 0:9e2fc73e5a12 98 /* everything else has to be a number */
kyourek 0:9e2fc73e5a12 99 default:
kyourek 0:9e2fc73e5a12 100 if (is_char_digit(p[i]) == ucBool_FALSE) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 101 break;
kyourek 0:9e2fc73e5a12 102 }
kyourek 0:9e2fc73e5a12 103 }
kyourek 0:9e2fc73e5a12 104
kyourek 0:9e2fc73e5a12 105 /* if we got here, it's a number */
kyourek 0:9e2fc73e5a12 106 return ucBool_TRUE;
kyourek 0:9e2fc73e5a12 107 }
kyourek 0:9e2fc73e5a12 108
kyourek 0:9e2fc73e5a12 109 ucBool ucTok_try_parse_numeric(ucTok *p, double *value) {
kyourek 0:9e2fc73e5a12 110 if (ucTok_is_numeric(p)) {
kyourek 0:9e2fc73e5a12 111 if (value) {
kyourek 0:9e2fc73e5a12 112 *value = atof(ucTok_get_value(p));
kyourek 0:9e2fc73e5a12 113 }
kyourek 0:9e2fc73e5a12 114 return ucBool_TRUE;
kyourek 0:9e2fc73e5a12 115 }
kyourek 0:9e2fc73e5a12 116 return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 117 }
kyourek 0:9e2fc73e5a12 118
kyourek 0:9e2fc73e5a12 119 double ucTok_parse_numeric(ucTok *p) {
kyourek 0:9e2fc73e5a12 120 double value = 0;
kyourek 0:9e2fc73e5a12 121 ucTok_try_parse_numeric(p, &value);
kyourek 0:9e2fc73e5a12 122 return value;
kyourek 0:9e2fc73e5a12 123 }
kyourek 0:9e2fc73e5a12 124
kyourek 0:9e2fc73e5a12 125 ucBool ucTok_is_boolean(ucTok *p) {
kyourek 0:9e2fc73e5a12 126 int i, len;
kyourek 0:9e2fc73e5a12 127 const char *b[] = { ucTok_BOOLEAN_FALSE, ucTok_BOOLEAN_TRUE };
kyourek 0:9e2fc73e5a12 128 if (NULL == p) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 129 len = sizeof(b) / sizeof(b[0]);
kyourek 0:9e2fc73e5a12 130 for (i = 0; i < len; i++) {
kyourek 0:9e2fc73e5a12 131 if (ucTok_equals(p, b[i])) {
kyourek 0:9e2fc73e5a12 132 return ucBool_TRUE;
kyourek 0:9e2fc73e5a12 133 }
kyourek 0:9e2fc73e5a12 134 }
kyourek 0:9e2fc73e5a12 135 return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 136 }
kyourek 0:9e2fc73e5a12 137
kyourek 0:9e2fc73e5a12 138 ucBool ucTok_try_parse_boolean(ucTok *p, ucBool *value) {
kyourek 0:9e2fc73e5a12 139 int i, len;
kyourek 0:9e2fc73e5a12 140 const char *t[] = { ucTok_BOOLEAN_TRUE };
kyourek 0:9e2fc73e5a12 141 const char *f[] = { ucTok_BOOLEAN_FALSE };
kyourek 0:9e2fc73e5a12 142 len = sizeof(t) / sizeof(t[0]);
kyourek 0:9e2fc73e5a12 143 for (i = 0; i < len; i++) {
kyourek 0:9e2fc73e5a12 144 if (ucTok_equals(p, t[i])) {
kyourek 0:9e2fc73e5a12 145 if (value) {
kyourek 0:9e2fc73e5a12 146 *value = ucBool_TRUE;
kyourek 0:9e2fc73e5a12 147 }
kyourek 0:9e2fc73e5a12 148 return ucBool_TRUE;
kyourek 0:9e2fc73e5a12 149 }
kyourek 0:9e2fc73e5a12 150 }
kyourek 0:9e2fc73e5a12 151 len = sizeof(f) / sizeof(f[0]);
kyourek 0:9e2fc73e5a12 152 for (i = 0; i < len; i++) {
kyourek 0:9e2fc73e5a12 153 if (ucTok_equals(p, f[i])) {
kyourek 0:9e2fc73e5a12 154 if (value) {
kyourek 0:9e2fc73e5a12 155 *value = ucBool_FALSE;
kyourek 0:9e2fc73e5a12 156 }
kyourek 0:9e2fc73e5a12 157 return ucBool_TRUE;
kyourek 0:9e2fc73e5a12 158 }
kyourek 0:9e2fc73e5a12 159 }
kyourek 0:9e2fc73e5a12 160 return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 161 }
kyourek 0:9e2fc73e5a12 162
kyourek 0:9e2fc73e5a12 163 ucBool ucTok_parse_boolean(ucTok *p) {
kyourek 0:9e2fc73e5a12 164 ucBool value = ucBool_FALSE;
kyourek 0:9e2fc73e5a12 165 ucTok_try_parse_boolean(p, &value);
kyourek 0:9e2fc73e5a12 166 return value;
kyourek 0:9e2fc73e5a12 167 }
kyourek 0:9e2fc73e5a12 168
kyourek 0:9e2fc73e5a12 169 ucBool ucTok_is_switch(ucTok* p) {
kyourek 0:9e2fc73e5a12 170 int len = 0;
kyourek 0:9e2fc73e5a12 171
kyourek 0:9e2fc73e5a12 172 /* check for a null pointer */
kyourek 0:9e2fc73e5a12 173 if (NULL == p) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 174
kyourek 0:9e2fc73e5a12 175 /* get the length so we can use it */
kyourek 0:9e2fc73e5a12 176 len = ucTok_get_length(p);
kyourek 0:9e2fc73e5a12 177
kyourek 0:9e2fc73e5a12 178 /* check for at least 2 characters (one '-' and at least another char) */
kyourek 0:9e2fc73e5a12 179 if (len < 2) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 180
kyourek 0:9e2fc73e5a12 181 /* check if it starts with a '-' */
kyourek 0:9e2fc73e5a12 182 if (p[0] != '-') return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 183
kyourek 0:9e2fc73e5a12 184 /* check if this is a numeric argument (negative numbers aren't switches) */
kyourek 0:9e2fc73e5a12 185 if (ucTok_is_numeric(p)) return ucBool_FALSE;
kyourek 0:9e2fc73e5a12 186
kyourek 0:9e2fc73e5a12 187 /* ok, it's a switch */
kyourek 0:9e2fc73e5a12 188 return ucBool_TRUE;
kyourek 0:9e2fc73e5a12 189 }
kyourek 0:9e2fc73e5a12 190
kyourek 0:9e2fc73e5a12 191 ucTok *ucTok_get_next(ucTok *p) {
kyourek 0:9e2fc73e5a12 192 int i;
kyourek 0:9e2fc73e5a12 193 if (NULL == p) return NULL;
kyourek 0:9e2fc73e5a12 194
kyourek 0:9e2fc73e5a12 195 /* loop until we've hit the max length */
kyourek 0:9e2fc73e5a12 196 i = 0;
kyourek 0:9e2fc73e5a12 197 while (ucTok_LENGTH_MAX > ++i) {
kyourek 0:9e2fc73e5a12 198
kyourek 0:9e2fc73e5a12 199 /* check if the previous character was a separator */
kyourek 0:9e2fc73e5a12 200 if (ucTok_separator == p[i - 1]) {
kyourek 0:9e2fc73e5a12 201
kyourek 0:9e2fc73e5a12 202 /* check if this character is the terminator */
kyourek 0:9e2fc73e5a12 203 if (uc_cmd_terminator == p[i]) {
kyourek 0:9e2fc73e5a12 204
kyourek 0:9e2fc73e5a12 205 /* it is, so no more tokens exist */
kyourek 0:9e2fc73e5a12 206 return NULL;
kyourek 0:9e2fc73e5a12 207 }
kyourek 0:9e2fc73e5a12 208
kyourek 0:9e2fc73e5a12 209 /* make sure this character isn't another separator */
kyourek 0:9e2fc73e5a12 210 if (ucTok_separator == p[i]) {
kyourek 0:9e2fc73e5a12 211 continue;
kyourek 0:9e2fc73e5a12 212 }
kyourek 0:9e2fc73e5a12 213
kyourek 0:9e2fc73e5a12 214 /* the previous character was a separator,
kyourek 0:9e2fc73e5a12 215 and this character is NOT the terminator,
kyourek 0:9e2fc73e5a12 216 OR another separator, so this character is
kyourek 0:9e2fc73e5a12 217 the start of a new token */
kyourek 0:9e2fc73e5a12 218 return (ucTok*)&p[i];
kyourek 0:9e2fc73e5a12 219 }
kyourek 0:9e2fc73e5a12 220 }
kyourek 0:9e2fc73e5a12 221
kyourek 0:9e2fc73e5a12 222 /* the max length was exceeded,
kyourek 0:9e2fc73e5a12 223 which probably means something
kyourek 0:9e2fc73e5a12 224 went wrong. */
kyourek 0:9e2fc73e5a12 225 return NULL;
kyourek 0:9e2fc73e5a12 226 }
kyourek 0:9e2fc73e5a12 227
kyourek 0:9e2fc73e5a12 228 int ucTok_count(ucTok *p) {
kyourek 0:9e2fc73e5a12 229 int count;
kyourek 0:9e2fc73e5a12 230
kyourek 0:9e2fc73e5a12 231 /* make sure we have a pointer */
kyourek 0:9e2fc73e5a12 232 if (NULL == p) return 0;
kyourek 0:9e2fc73e5a12 233
kyourek 0:9e2fc73e5a12 234 /* if the first character is the terminator, then we have no tokens */
kyourek 0:9e2fc73e5a12 235 if (p[0] == uc_cmd_terminator) return 0;
kyourek 0:9e2fc73e5a12 236
kyourek 0:9e2fc73e5a12 237 /* start off the count according to whether or not
kyourek 0:9e2fc73e5a12 238 we're starting at a token */
kyourek 0:9e2fc73e5a12 239 count = ucTok_separator == p[0] ? -1 : 0;
kyourek 0:9e2fc73e5a12 240
kyourek 0:9e2fc73e5a12 241 /* count the tokens in the chain */
kyourek 0:9e2fc73e5a12 242 while (NULL != p) {
kyourek 0:9e2fc73e5a12 243 count++;
kyourek 0:9e2fc73e5a12 244 p = ucTok_get_next(p);
kyourek 0:9e2fc73e5a12 245 }
kyourek 0:9e2fc73e5a12 246 return count;
kyourek 0:9e2fc73e5a12 247 }
kyourek 0:9e2fc73e5a12 248