Commit | Line | Data |
---|---|---|
c295905f AW |
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 "ConfigValue.h" | |
10 | #include "FileConfigSource.h" | |
11 | #include "ConfigCache.h" | |
a39e1557 AW |
12 | #include <malloc.h> |
13 | ||
c295905f AW |
14 | |
15 | using namespace std; | |
16 | #include <string> | |
17 | ||
18 | ||
32891c60 L |
19 | FileConfigSource::FileConfigSource(string config_file, uint16_t name_checksum){ |
20 | this->name_checksum = name_checksum; | |
8d857d2e | 21 | this->config_file = config_file; |
c295905f AW |
22 | this->config_file_found = false; |
23 | } | |
24 | ||
25 | // Transfer all values found in the file to the passed cache | |
26 | void FileConfigSource::transfer_values_to_cache( ConfigCache* cache ){ | |
a39e1557 | 27 | |
c295905f AW |
28 | // Default empty value |
29 | ConfigValue* result = new ConfigValue; | |
30 | ||
31 | if( this->has_config_file() == false ){return;} | |
32 | // Open the config file ( find it if we haven't already found it ) | |
33 | FILE *lp = fopen(this->get_config_file().c_str(), "r"); | |
34 | string buffer; | |
35 | int c; | |
36 | // For each line | |
37 | do { | |
38 | c = fgetc (lp); | |
39 | if (c == '\n' || c == EOF){ | |
a39e1557 | 40 | |
c295905f AW |
41 | // We have a new line |
42 | if( buffer[0] == '#' ){ buffer.clear(); continue; } // Ignore comments | |
43 | if( buffer.length() < 3 ){ buffer.clear(); continue; } //Ignore empty lines | |
44 | size_t begin_key = buffer.find_first_not_of(" "); | |
45 | size_t begin_value = buffer.find_first_not_of(" ", buffer.find_first_of(" ", begin_key)); | |
a39e1557 | 46 | |
4464301d AW |
47 | uint16_t check_sums[3]; |
48 | get_checksums(check_sums, buffer.substr(begin_key, buffer.find_first_of(" ", begin_key) - begin_key).append(" ")); | |
750277f8 | 49 | |
c295905f | 50 | result = new ConfigValue; |
4464301d | 51 | |
c295905f | 52 | result->found = true; |
4464301d AW |
53 | result->check_sums[0] = check_sums[0]; |
54 | result->check_sums[1] = check_sums[1]; | |
55 | result->check_sums[2] = check_sums[2]; | |
a39e1557 | 56 | |
c295905f | 57 | result->value = buffer.substr(begin_value, buffer.find_first_of("\r\n# ", begin_value+1)-begin_value); |
c295905f AW |
58 | // Append the newly found value to the cache we were passed |
59 | cache->replace_or_push_back(result); | |
a39e1557 | 60 | |
c295905f | 61 | buffer.clear(); |
a39e1557 | 62 | |
c295905f AW |
63 | }else{ |
64 | buffer += c; | |
65 | } | |
66 | } while (c != EOF); | |
67 | fclose(lp); | |
c295905f AW |
68 | } |
69 | ||
5913c006 | 70 | // Return true if the check_sums match |
5efaa1b1 L |
71 | bool FileConfigSource::is_named( uint16_t check_sum ){ |
72 | return check_sum == this->name_checksum; | |
73 | } | |
74 | ||
5913c006 L |
75 | // Write a config setting to the file |
76 | void FileConfigSource::write( string setting, string value ){ | |
77 | // Open the config file ( find it if we haven't already found it ) | |
78 | FILE *lp = fopen(this->get_config_file().c_str(), "r+"); | |
79 | string buffer; | |
80 | int c; | |
81 | // For each line | |
82 | do { | |
83 | c = fgetc (lp); | |
84 | if (c == '\n' || c == EOF){ | |
85 | // We have a new line | |
86 | if( buffer[0] == '#' ){ buffer.clear(); continue; } // Ignore comments | |
87 | if( buffer.length() < 3 ){ buffer.clear(); continue; } //Ignore empty lines | |
88 | size_t begin_key = buffer.find_first_not_of(" "); | |
89 | size_t begin_value = buffer.find_first_not_of(" ", buffer.find_first_of(" ", begin_key)); | |
90 | // If this line matches the checksum | |
91 | string candidate = buffer.substr(begin_key, buffer.find_first_of(" ", begin_key) - begin_key); | |
92 | if( candidate.compare(setting) != 0 ){ buffer.clear(); continue; } | |
93 | int free_space = int(int(buffer.find_first_of("\r\n#", begin_value+1))-begin_value); | |
94 | if( int(value.length()) >= free_space ){ | |
38d375e7 | 95 | //this->kernel->streams->printf("ERROR: Not enough room for value\r\n"); |
5913c006 L |
96 | fclose(lp); |
97 | return; | |
98 | } | |
99 | // Update value | |
100 | for( int i = value.length(); i < free_space; i++){ value += " "; } | |
101 | fpos_t pos; | |
102 | fgetpos( lp, &pos ); | |
103 | int start = pos - buffer.length() + begin_value - 1; | |
104 | fseek(lp, start, SEEK_SET); | |
105 | fputs(value.c_str(), lp); | |
106 | fclose(lp); | |
107 | return; | |
108 | }else{ | |
109 | buffer += c; | |
110 | } | |
111 | } while (c != EOF); | |
112 | fclose(lp); | |
38d375e7 | 113 | //this->kernel->streams->printf("ERROR: configuration key not found\r\n"); |
5913c006 | 114 | } |
5efaa1b1 | 115 | |
5761c645 | 116 | // Return the value for a specific checksum |
4464301d | 117 | string FileConfigSource::read( uint16_t check_sums[3] ){ |
5761c645 L |
118 | |
119 | string value = ""; | |
120 | ||
121 | if( this->has_config_file() == false ){return value;} | |
122 | // Open the config file ( find it if we haven't already found it ) | |
123 | FILE *lp = fopen(this->get_config_file().c_str(), "r"); | |
124 | string buffer; | |
125 | int c; | |
126 | // For each line | |
127 | do { | |
128 | c = fgetc (lp); | |
129 | if (c == '\n' || c == EOF){ | |
130 | // We have a new line | |
131 | if( buffer[0] == '#' ){ buffer.clear(); continue; } // Ignore comments | |
132 | if( buffer.length() < 3 ){ buffer.clear(); continue; } //Ignore empty lines | |
133 | size_t begin_key = buffer.find_first_not_of(" "); | |
134 | size_t begin_value = buffer.find_first_not_of(" ", buffer.find_first_of(" ", begin_key)); | |
135 | string key = buffer.substr(begin_key, buffer.find_first_of(" ", begin_key) - begin_key).append(" "); | |
5761c645 | 136 | |
4464301d AW |
137 | uint16_t line_checksums[3]; |
138 | get_checksums(line_checksums, key); | |
139 | ||
140 | if(check_sums[0] == line_checksums[0] && check_sums[1] == line_checksums[1] && check_sums[2] == line_checksums[2] ){ | |
5761c645 L |
141 | value = buffer.substr(begin_value, buffer.find_first_of("\r\n# ", begin_value+1)-begin_value); |
142 | break; | |
143 | } | |
144 | ||
145 | buffer.clear(); | |
146 | }else{ | |
147 | buffer += c; | |
148 | } | |
149 | } while (c != EOF); | |
150 | fclose(lp); | |
151 | ||
152 | return value; | |
153 | } | |
5efaa1b1 | 154 | |
c295905f AW |
155 | // Return wether or not we have a readable config file |
156 | bool FileConfigSource::has_config_file(){ | |
157 | if( this->config_file_found ){ return true; } | |
8d857d2e | 158 | this->try_config_file(this->config_file); |
c295905f AW |
159 | if( this->config_file_found ){ |
160 | return true; | |
161 | }else{ | |
162 | return false; | |
163 | } | |
164 | ||
165 | } | |
166 | ||
167 | // Tool function for get_config_file | |
168 | inline void FileConfigSource::try_config_file(string candidate){ | |
8d857d2e | 169 | if(file_exists(candidate)){ this->config_file_found = true; } |
c295905f AW |
170 | } |
171 | ||
172 | // Get the filename for the config file | |
173 | string FileConfigSource::get_config_file(){ | |
174 | if( this->config_file_found ){ return this->config_file; } | |
175 | if( this->has_config_file() ){ | |
176 | return this->config_file; | |
177 | }else{ | |
178 | printf("ERROR: no config file found\r\n"); | |
179 | } | |
180 | } | |
181 | ||
182 | ||
183 | ||
184 | ||
185 | ||
186 |