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