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/>.
8 #include "libs/Kernel.h"
9 #include "ConfigValue.h"
10 #include "FileConfigSource.h"
11 #include "ConfigCache.h"
19 FileConfigSource::FileConfigSource(string config_file
, uint16_t name_checksum
){
20 this->name_checksum
= name_checksum
;
21 this->config_file
= config_file
;
22 this->config_file_found
= false;
25 // Transfer all values found in the file to the passed cache
26 void FileConfigSource::transfer_values_to_cache( ConfigCache
* cache
){
29 printf("Before file reading\n");
34 // Default empty value
35 ConfigValue
* result
= new ConfigValue
;
37 if( this->has_config_file() == false ){return;}
38 // Open the config file ( find it if we haven't already found it )
39 FILE *lp
= fopen(this->get_config_file().c_str(), "r");
48 if (c
== '\n' || c
== EOF
){
50 printf("key:<%s> \r\n", buffer
.c_str());
53 if( buffer
[0] == '#' ){ buffer
.clear(); continue; } // Ignore comments
54 if( buffer
.length() < 3 ){ buffer
.clear(); continue; } //Ignore empty lines
55 size_t begin_key
= buffer
.find_first_not_of(" ");
56 size_t begin_value
= buffer
.find_first_not_of(" ", buffer
.find_first_of(" ", begin_key
));
58 vector
<uint16_t> check_sums
= get_checksums(buffer
.substr(begin_key
, buffer
.find_first_of(" ", begin_key
) - begin_key
).append(" "));
60 printf("before trouble\r\n");
61 printf("sizeof(ConfigValue): %u\r\n", sizeof(ConfigValue
));
64 printf("trouble \r\n");
65 result
= new ConfigValue
;
68 printf("after trouble\r\n");
72 result
->check_sums
= check_sums
;
74 result
->value
= buffer
.substr(begin_value
, buffer
.find_first_of("\r\n# ", begin_value
+1)-begin_value
);
76 debug_total
+= result
->value
.size();
78 printf("value:<%s> %d \r\n", result
->value
.c_str(), debug_total
);
80 // Append the newly found value to the cache we were passed
81 cache
->replace_or_push_back(result
);
93 printf("After file reading config\n");
100 // Return true if the check_sums match
101 bool FileConfigSource::is_named( uint16_t check_sum
){
102 return check_sum
== this->name_checksum
;
105 // Write a config setting to the file
106 void FileConfigSource::write( string setting
, string value
){
107 // Open the config file ( find it if we haven't already found it )
108 FILE *lp
= fopen(this->get_config_file().c_str(), "r+");
114 if (c
== '\n' || c
== EOF
){
115 // We have a new line
116 if( buffer
[0] == '#' ){ buffer
.clear(); continue; } // Ignore comments
117 if( buffer
.length() < 3 ){ buffer
.clear(); continue; } //Ignore empty lines
118 size_t begin_key
= buffer
.find_first_not_of(" ");
119 size_t begin_value
= buffer
.find_first_not_of(" ", buffer
.find_first_of(" ", begin_key
));
120 // If this line matches the checksum
121 string candidate
= buffer
.substr(begin_key
, buffer
.find_first_of(" ", begin_key
) - begin_key
);
122 if( candidate
.compare(setting
) != 0 ){ buffer
.clear(); continue; }
123 int free_space
= int(int(buffer
.find_first_of("\r\n#", begin_value
+1))-begin_value
);
124 if( int(value
.length()) >= free_space
){
125 //this->kernel->streams->printf("ERROR: Not enough room for value\r\n");
130 for( int i
= value
.length(); i
< free_space
; i
++){ value
+= " "; }
133 int start
= pos
- buffer
.length() + begin_value
- 1;
134 fseek(lp
, start
, SEEK_SET
);
135 fputs(value
.c_str(), lp
);
143 //this->kernel->streams->printf("ERROR: configuration key not found\r\n");
146 // Return the value for a specific checksum
147 string
FileConfigSource::read( vector
<uint16_t> check_sums
){
151 if( this->has_config_file() == false ){return value
;}
152 // Open the config file ( find it if we haven't already found it )
153 FILE *lp
= fopen(this->get_config_file().c_str(), "r");
159 if (c
== '\n' || c
== EOF
){
160 // We have a new line
161 if( buffer
[0] == '#' ){ buffer
.clear(); continue; } // Ignore comments
162 if( buffer
.length() < 3 ){ buffer
.clear(); continue; } //Ignore empty lines
163 size_t begin_key
= buffer
.find_first_not_of(" ");
164 size_t begin_value
= buffer
.find_first_not_of(" ", buffer
.find_first_of(" ", begin_key
));
165 string key
= buffer
.substr(begin_key
, buffer
.find_first_of(" ", begin_key
) - begin_key
).append(" ");
166 vector
<uint16_t> line_checksums
= get_checksums(key
);
168 if(check_sums
== line_checksums
){
169 value
= buffer
.substr(begin_value
, buffer
.find_first_of("\r\n# ", begin_value
+1)-begin_value
);
183 // Return wether or not we have a readable config file
184 bool FileConfigSource::has_config_file(){
185 if( this->config_file_found
){ return true; }
186 this->try_config_file(this->config_file
);
187 if( this->config_file_found
){
195 // Tool function for get_config_file
196 inline void FileConfigSource::try_config_file(string candidate
){
197 if(file_exists(candidate
)){ this->config_file_found
= true; }
200 // Get the filename for the config file
201 string
FileConfigSource::get_config_file(){
202 if( this->config_file_found
){ return this->config_file
; }
203 if( this->has_config_file() ){
204 return this->config_file
;
206 printf("ERROR: no config file found\r\n");