nis-util  1.0.D108
lib/input/remove_hash_comments.cc
Go to the documentation of this file.
00001 //
00002 // nis-util - NIS Administration Utilities
00003 // Copyright (C) 2012 Peter Miller
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or (at
00008 // your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License along
00016 // with this program. If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 #include <lib/ac/string.h>
00020 
00021 #include <lib/input/remove_hash_comments.h>
00022 
00023 
00024 input_remove_hash_comments::~input_remove_hash_comments()
00025 {
00026 }
00027 
00028 
00029 input_remove_hash_comments::input_remove_hash_comments(
00030     const input::pointer &a_deeper
00031 ) :
00032     deeper(a_deeper),
00033     state(state_start_of_line)
00034 {
00035 }
00036 
00037 
00038 input_remove_hash_comments::pointer
00039 input_remove_hash_comments::create(const input::pointer &a_deeper)
00040 {
00041     return pointer(new input_remove_hash_comments(a_deeper));
00042 }
00043 
00044 
00045 size_t
00046 input_remove_hash_comments::read_inner(source_location &data_locn, void *vdata,
00047     size_t data_size)
00048 {
00049     data_locn = deeper->get_source_location();
00050     unsigned char *data = (unsigned char *)vdata;
00051     unsigned char *cp = data;
00052     unsigned char *end = data + data_size;
00053     while (cp < end)
00054     {
00055         int ic = deeper->get();
00056         if (ic == input::eof)
00057             break;
00058         unsigned char c = ic;
00059         switch (state)
00060         {
00061         case state_start_of_line:
00062             switch (c)
00063             {
00064             case ' ':
00065             case '\t':
00066                 whitespace.clear();
00067                 whitespace.push_back(c);
00068                 state = state_white_space;
00069                 break;
00070 
00071             case '\n':
00072                 *cp++ = '\n';
00073                 state = state_start_of_line;
00074                 goto end_of_line;
00075 
00076             case '#':
00077                 state = state_discarding;
00078                 break;
00079 
00080             default:
00081                 *cp++ = c;
00082                 state = state_content;
00083                 break;
00084             }
00085             break;
00086 
00087         case state_discarding:
00088             if (c == '\n')
00089             {
00090                 *cp++ = '\n';
00091                 state = state_start_of_line;
00092                 goto end_of_line;
00093             }
00094             break;
00095 
00096         case state_white_space:
00097             switch (c)
00098             {
00099             case ' ':
00100             case '\t':
00101                 whitespace.push_back(c);
00102                 state = state_white_space;
00103                 break;
00104 
00105             case '\n':
00106                 *cp++ = '\n';
00107                 state = state_start_of_line;
00108                 goto end_of_line;
00109 
00110             case '#':
00111                 whitespace.clear();
00112                 state = state_discarding;
00113                 break;
00114 
00115             default:
00116                 // what if whitespace doesn't fit?
00117                 // (the "or equal" is because we need room for 'c' as well)
00118                 if (cp + whitespace.size() >= end)
00119                 {
00120                     deeper->unget(c);
00121                     size_t nbytes = end - cp;
00122                     assert(nbytes <= whitespace.size());
00123                     memcpy(cp, whitespace.get_data(), nbytes);
00124                     cp += nbytes;
00125                     whitespace.pop_front(nbytes);
00126                     state = state_white_space;
00127                 }
00128                 else
00129                 {
00130                     memcpy(cp, whitespace.get_data(), whitespace.size());
00131                     cp += whitespace.size();
00132                     whitespace.clear();
00133                     *cp++ = c;
00134                     state = state_content;
00135                 }
00136                 break;
00137             }
00138             break;
00139 
00140         case state_content:
00141             switch (c)
00142             {
00143             case ' ':
00144             case '\t':
00145                 whitespace.clear();
00146                 whitespace.push_back(c);
00147                 state = state_white_space;
00148                 break;
00149 
00150             case '\n':
00151                 *cp++ = c;
00152                 state = state_start_of_line;
00153                 goto end_of_line;
00154 
00155             case '#':
00156                 // Note: a@b#c does not contain the start of a comment
00157             default:
00158                 *cp++ = c;
00159                 state = state_content;
00160                 break;
00161             }
00162             break;
00163         }
00164     }
00165     end_of_line:
00166     return (cp - data);
00167 }
00168 
00169 
00170 // vim: set ts=8 sw=4 et :