solved the block end problem, commiting mostly to save all those neat debug statement...
[clinton/Smoothieware.git] / src / libs / ConfigSources / FileConfigSource.cpp
CommitLineData
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
15using namespace std;
16#include <string>
17
18
32891c60
L
19FileConfigSource::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
26void 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
71bool 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
76void 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 117string 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
156bool 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
168inline 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
173string 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