Merge remote-tracking branch 'origin/edge' into local-firmconfig
[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 if( this->has_config_file() == false ){return;}
29 // Open the config file ( find it if we haven't already found it )
30 FILE *lp = fopen(this->get_config_file().c_str(), "r");
31 int c;
32 // For each line
33 do {
34 process_char_from_ascii_config(c = fgetc(lp), cache);
35 } while (c != EOF);
36 fclose(lp);
37 }
38
39 // Return true if the check_sums match
40 bool FileConfigSource::is_named( uint16_t check_sum ){
41 return check_sum == this->name_checksum;
42 }
43
44 // Write a config setting to the file
45 void FileConfigSource::write( string setting, string value ){
46 // Open the config file ( find it if we haven't already found it )
47 FILE *lp = fopen(this->get_config_file().c_str(), "r+");
48 string buffer;
49 int c;
50 // For each line
51 do {
52 c = fgetc (lp);
53 if (c == '\n' || c == EOF){
54 // We have a new line
55 if( buffer[0] == '#' ){ buffer.clear(); continue; } // Ignore comments
56 if( buffer.length() < 3 ){ buffer.clear(); continue; } //Ignore empty lines
57 size_t begin_key = buffer.find_first_not_of(" \t");
58 size_t begin_value = buffer.find_first_not_of(" \t", buffer.find_first_of(" \t", begin_key));
59 // If this line matches the checksum
60 string candidate = buffer.substr(begin_key, buffer.find_first_of(" \t", begin_key) - begin_key);
61 if( candidate.compare(setting) != 0 ){ buffer.clear(); continue; }
62 int free_space = int(int(buffer.find_first_of("\r\n#", begin_value+1))-begin_value);
63 if( int(value.length()) >= free_space ){
64 //this->kernel->streams->printf("ERROR: Not enough room for value\r\n");
65 fclose(lp);
66 return;
67 }
68 // Update value
69 for( int i = value.length(); i < free_space; i++){ value += " "; }
70 fpos_t pos;
71 fgetpos( lp, &pos );
72 int start = pos - buffer.length() + begin_value - 1;
73 fseek(lp, start, SEEK_SET);
74 fputs(value.c_str(), lp);
75 fclose(lp);
76 return;
77 }else{
78 buffer += c;
79 }
80 } while (c != EOF);
81 fclose(lp);
82 //this->kernel->streams->printf("ERROR: configuration key not found\r\n");
83 }
84
85 // Return the value for a specific checksum
86 string FileConfigSource::read( uint16_t check_sums[3] ){
87
88 string value = "";
89
90 if( this->has_config_file() == false ){return value;}
91 // Open the config file ( find it if we haven't already found it )
92 FILE *lp = fopen(this->get_config_file().c_str(), "r");
93 int c;
94 // For each line
95 do {
96 c = fgetc (lp);
97 process_char_from_ascii_config(c, check_sums);
98 } while (c != EOF);
99 fclose(lp);
100
101 return value;
102 }
103
104 // Return wether or not we have a readable config file
105 bool FileConfigSource::has_config_file(){
106 if( this->config_file_found ){ return true; }
107 this->try_config_file(this->config_file);
108 if( this->config_file_found ){
109 return true;
110 }else{
111 return false;
112 }
113
114 }
115
116 // Tool function for get_config_file
117 inline void FileConfigSource::try_config_file(string candidate){
118 if(file_exists(candidate)){ this->config_file_found = true; }
119 }
120
121 // Get the filename for the config file
122 string FileConfigSource::get_config_file(){
123 if( this->config_file_found ){ return this->config_file; }
124 if( this->has_config_file() ){
125 return this->config_file;
126 }else{
127 printf("ERROR: no config file found\r\n");
128 return "";
129 }
130 }
131
132
133
134
135
136