Merge pull request #114 from orcinus/HomingDirection
[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 #include <malloc.h>
13
14
15 using namespace std;
16 #include <string>
17
18
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;
23 }
24
25 // Transfer all values found in the file to the passed cache
26 void FileConfigSource::transfer_values_to_cache( ConfigCache* cache ){
27
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){
40
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));
46
47 uint16_t check_sums[3];
48 get_checksums(check_sums, buffer.substr(begin_key, buffer.find_first_of(" ", begin_key) - begin_key).append(" "));
49
50 result = new ConfigValue;
51
52 result->found = true;
53 result->check_sums[0] = check_sums[0];
54 result->check_sums[1] = check_sums[1];
55 result->check_sums[2] = check_sums[2];
56
57 result->value = buffer.substr(begin_value, buffer.find_first_of("\r\n# ", begin_value+1)-begin_value);
58 // Append the newly found value to the cache we were passed
59 cache->replace_or_push_back(result);
60
61 buffer.clear();
62
63 }else{
64 buffer += c;
65 }
66 } while (c != EOF);
67 fclose(lp);
68 }
69
70 // Return true if the check_sums match
71 bool FileConfigSource::is_named( uint16_t check_sum ){
72 return check_sum == this->name_checksum;
73 }
74
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(" \t");
89 size_t begin_value = buffer.find_first_not_of(" \t", buffer.find_first_of(" \t", begin_key));
90 // If this line matches the checksum
91 string candidate = buffer.substr(begin_key, buffer.find_first_of(" \t", 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 ){
95 //this->kernel->streams->printf("ERROR: Not enough room for value\r\n");
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);
113 //this->kernel->streams->printf("ERROR: configuration key not found\r\n");
114 }
115
116 // Return the value for a specific checksum
117 string FileConfigSource::read( uint16_t check_sums[3] ){
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(" \t");
134 size_t begin_value = buffer.find_first_not_of(" \t", buffer.find_first_of(" \t", begin_key));
135 string key = buffer.substr(begin_key, buffer.find_first_of(" \t", begin_key) - begin_key).append(" ");
136
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] ){
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 }
154
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; }
158 this->try_config_file(this->config_file);
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){
169 if(file_exists(candidate)){ this->config_file_found = true; }
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 return "";
180 }
181 }
182
183
184
185
186
187