Imported Upstream version 15.0.0
[platform/upstream/libzypp.git] / zypp / parser / IniParser.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/parser/IniParser.cc
10  *
11 */
12 #include <iostream>
13 #include <sstream>
14
15 #include "zypp/base/Logger.h"
16 #include "zypp/base/String.h"
17 #include "zypp/base/IOStream.h"
18 #include "zypp/base/UserRequestException.h"
19
20 #include "zypp/parser/ParseException.h"
21 #include "zypp/parser/IniParser.h"
22 #include "zypp/ProgressData.h"
23
24 using std::endl;
25
26 ///////////////////////////////////////////////////////////////////
27 namespace zypp
28 { /////////////////////////////////////////////////////////////////
29 ///////////////////////////////////////////////////////////////////
30 namespace parser
31 { /////////////////////////////////////////////////////////////////
32
33   namespace {
34     inline const std::string & keyGarbage()
35     {
36       static const std::string & _val( ",|/\\" );
37       return _val;
38     }
39   } //namespace
40
41 ///////////////////////////////////////////////////////////////////
42 //
43 //      METHOD NAME : IniParser::IniParser
44 //      METHOD TYPE : Ctor
45 //
46 IniParser::IniParser()
47   : _line_nr(0)
48 {}
49
50 ///////////////////////////////////////////////////////////////////
51 //
52 //      METHOD NAME : IniParser::~IniParser
53 //      METHOD TYPE : Dtor
54 //
55 IniParser::~IniParser()
56 {}
57
58 void IniParser::beginParse()
59 {}
60
61 void IniParser::consume( const std::string &section, const std::string &key, const std::string &value )
62 {}
63
64 void IniParser::consume( const std::string &section )
65 {}
66
67 void IniParser::endParse()
68 {}
69
70 void IniParser::garbageLine( const std::string &section, const std::string &line )
71 {
72   std::string msg = str::form("%s: Section [%s]: Line %d contains garbage (no '=' or '%s' in key)",
73                               _inputname.c_str(), section.c_str(), _line_nr, keyGarbage().c_str());
74   ZYPP_THROW(ParseException(msg));
75 }
76
77 ///////////////////////////////////////////////////////////////////
78 //
79 //      METHOD NAME : IniParser::parse
80 //      METHOD TYPE : void
81 //
82 void IniParser::parse( const InputStream & input_r, const ProgressData::ReceiverFnc & progress )
83 {
84   MIL << "Start parsing " << input_r << endl;
85   _inputname = input_r.name();
86   beginParse();
87
88   ProgressData ticks( makeProgressData( input_r ) );
89   ticks.sendTo(progress);
90   ticks.toMin();
91
92   iostr::EachLine line( input_r );
93   for ( ; line; line.next() )
94   {
95     std::string trimmed = str::trim(*line);
96
97     if (trimmed.empty() || trimmed[0] == ';' || trimmed[0] == '#')
98       continue ; /* Comment lines */
99
100     if (trimmed[0] == '[')
101     {
102       std::string::size_type pos = trimmed.find(']');
103       if ( pos != std::string::npos )
104       {
105         std::string section = trimmed.substr(1, pos-1);
106         consume(section);
107         section.swap(_current_section);
108       }
109       else
110       {
111         _line_nr = line.lineNo();
112         garbageLine( _current_section, trimmed );
113       }
114       continue;
115     }
116
117     std::string::size_type pos = trimmed.find('=');
118     if ( pos == std::string::npos || trimmed.find_first_of( keyGarbage() ) < pos )
119     {
120       _line_nr = line.lineNo();
121       garbageLine( _current_section, trimmed ); // may or may not throw
122     }
123     else
124     {
125       std::string key = str::rtrim(trimmed.substr(0, pos));
126       std::string value = str::ltrim(trimmed.substr(pos+1));
127       consume( _current_section, key, value);
128     }
129
130     // set progress and allow cancel
131     if ( ! ticks.set( input_r.stream().tellg() ) )
132       ZYPP_THROW(AbortRequestException());
133   }
134   ticks.toMax();
135
136   endParse();
137   _inputname.clear();
138   MIL << "Done parsing " << input_r << endl;
139 }
140
141 /////////////////////////////////////////////////////////////////
142 } // namespace parser
143 ///////////////////////////////////////////////////////////////////
144 /////////////////////////////////////////////////////////////////
145 } // namespace zypp
146 ///////////////////////////////////////////////////////////////////