Switched to deque to avoid invalid iterator
[clinton/Smoothieware.git] / src / libs / utils.cpp
1 /*
2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
3 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
6 */
7
8 #include "libs/Kernel.h"
9 #include "libs/utils.h"
10 #include "system_LPC17xx.h"
11 #include "LPC17xx.h"
12 #include "utils.h"
13
14 #include <string>
15 #include <cstring>
16 #include <stdio.h>
17 #include <cstdlib>
18 using std::string;
19
20 uint16_t get_checksum(const string &to_check)
21 {
22 return get_checksum(to_check.c_str());
23 }
24
25 uint16_t get_checksum(const char *to_check)
26 {
27 // From: http://en.wikipedia.org/wiki/Fletcher%27s_checksum
28 uint16_t sum1 = 0;
29 uint16_t sum2 = 0;
30 const char *p = to_check;
31 char c;
32 while((c = *p++) != 0) {
33 sum1 = (sum1 + c) % 255;
34 sum2 = (sum2 + sum1) % 255;
35 }
36 return (sum2 << 8) | sum1;
37 }
38
39 void get_checksums(uint16_t check_sums[], const string &key)
40 {
41 check_sums[0] = 0x0000;
42 check_sums[1] = 0x0000;
43 check_sums[2] = 0x0000;
44 size_t begin_key = 0;
45 unsigned int counter = 0;
46 while( begin_key < key.size() && counter < 3 ) {
47 size_t end_key = key.find_first_of(".", begin_key);
48 string key_node;
49 if(end_key == string::npos) {
50 key_node = key.substr(begin_key);
51 } else {
52 key_node = key.substr(begin_key, end_key - begin_key);
53 }
54
55 check_sums[counter] = get_checksum(key_node);
56 if(end_key == string::npos) break;
57 begin_key = end_key + 1;
58 counter++;
59 }
60 }
61
62 bool is_alpha(int c)
63 {
64 if ((c >= 'a') && (c <= 'z')) return true;
65 if ((c >= 'A') && (c <= 'Z')) return true;
66 if ((c == '_')) return true;
67 return false;
68 }
69
70 bool is_digit(int c)
71 {
72 if ((c >= '0') && (c <= '9')) return true;
73 return false;
74 }
75
76 bool is_numeric(int c)
77 {
78 if (is_digit(c)) return true;
79 if ((c == '.') || (c == '-')) return true;
80 if ((c == 'e')) return true;
81 return false;
82 }
83
84 bool is_alphanum(int c)
85 {
86 return is_alpha(c) || is_numeric(c);
87 }
88
89 bool is_whitespace(int c)
90 {
91 if ((c == ' ') || (c == '\t')) return true;
92 return false;
93 }
94
95 // Convert to lowercase
96 string lc(const string &str)
97 {
98 string lcstr;
99 for (auto c : str) {
100 lcstr.append(1, ::tolower(c));
101 }
102 return lcstr;
103 }
104
105 // Remove non-number characters
106 string remove_non_number( string str )
107 {
108 string number_mask = "0123456789-.abcdefpxABCDEFPX";
109 size_t found = str.find_first_not_of(number_mask);
110 while (found != string::npos) {
111 //str[found]='*';
112 str.replace(found, 1, "");
113 found = str.find_first_not_of(number_mask);
114 }
115 return str;
116 }
117
118 // Get the first parameter, and remove it from the original string
119 string shift_parameter( string &parameters )
120 {
121 size_t beginning = parameters.find_first_of(" ");
122 if( beginning == string::npos ) {
123 string temp = parameters;
124 parameters = "";
125 return temp;
126 }
127 string temp = parameters.substr( 0, beginning );
128 parameters = parameters.substr(beginning + 1, parameters.size());
129 return temp;
130 }
131
132 // Separate command from arguments
133 string get_arguments( string possible_command )
134 {
135 size_t beginning = possible_command.find_first_of(" ");
136 if( beginning == string::npos ) {
137 return "";
138 }
139 return possible_command.substr( beginning + 1, possible_command.size() - beginning + 1);
140 }
141
142 // Returns true if the file exists
143 bool file_exists( const string file_name )
144 {
145 bool exists = false;
146 FILE *lp = fopen(file_name.c_str(), "r");
147 if(lp) {
148 exists = true;
149 }
150 fclose(lp);
151 return exists;
152 }
153
154 // Prepares and executes a watchdog reset for dfu or reboot
155 void system_reset( bool dfu )
156 {
157 if(dfu) {
158 LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK
159 uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4
160 LPC_WDT->WDTC = 1 * (float)clk; // Reset in 1 second
161 LPC_WDT->WDMOD = 0x3; // Enabled and Reset
162 LPC_WDT->WDFEED = 0xAA; // Kick the dog!
163 LPC_WDT->WDFEED = 0x55;
164 } else {
165 NVIC_SystemReset();
166 }
167 }
168
169 // Convert a path indication ( absolute or relative ) into a path ( absolute )
170 // TODO: Combine with plan9 absolute_path, current_path as argument?
171 string absolute_from_relative( string path )
172 {
173 string cwd = THEKERNEL->current_path;
174
175 if ( path.empty() ) {
176 return THEKERNEL->current_path;
177 }
178
179 if ( path[0] == '/' ) {
180 return path;
181 }
182
183 while ( path.substr(0, 3) == "../" ) {
184 path = path.substr(3);
185 unsigned found = cwd.find_last_of("/");
186 cwd = cwd.substr(0, found);
187 }
188
189 if ( path.substr(0, 2) == ".." ) {
190 path = path.substr(2);
191 unsigned found = cwd.find_last_of("/");
192 cwd = cwd.substr(0, found);
193 }
194
195 if ( cwd[cwd.length() - 1] == '/' ) {
196 return cwd + path;
197 }
198
199 return cwd + '/' + path;
200 }
201
202 //split a string on a delimiter, return a vector of the split tokens
203 vector<string> split(const char *str, char c)
204 {
205 vector<string> result;
206
207 do {
208 const char *begin = str;
209
210 while(*str != c && *str)
211 str++;
212
213 result.push_back(string(begin, str));
214 } while (0 != *str++);
215
216 return result;
217 }
218
219 // parse a number list "1.1,2.2,3.3" and return the numbers in a vector of floats
220 vector<float> parse_number_list(const char *str)
221 {
222 vector<string> l= split(str, ',');
223 vector<float> r;
224 for(auto& s : l) {
225 float x = strtof(s.c_str(), nullptr);
226 r.push_back(x);
227 }
228 return r;
229 }