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