1 // SExp - A S-Expression Parser for C++
2 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //               2015 Ingo Ruhnke <grumbel@gmail.com>
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 #include "sexp/util.hpp"
19 
20 #include <sstream>
21 #include <stdexcept>
22 
23 #include "sexp/io.hpp"
24 
25 namespace sexp {
26 
27 bool
is_list(Value const & sx)28 is_list(Value const& sx)
29 {
30   if (sx.is_nil())
31   {
32     return true;
33   }
34   else if (sx.is_cons())
35   {
36     return is_list(sx.get_cdr());
37   }
38   else
39   {
40     return false;
41   }
42 }
43 
44 int
list_length(Value const & sx)45 list_length(Value const& sx)
46 {
47   if (sx.is_nil())
48   {
49     return 0;
50   }
51   else if (sx.is_cons())
52   {
53     return 1 + list_length(sx.get_cdr());
54   }
55   else
56   {
57     // silently ignoring malformed list content
58     return 0;
59   }
60 }
61 
62 Value const&
list_ref(Value const & sx,int index)63 list_ref(Value const& sx, int index)
64 {
65   if (index == 0)
66   {
67     return sx.get_car();
68   }
69   else
70   {
71     return list_ref(sx.get_cdr(), index - 1);
72   }
73 }
74 
75 Value const&
assoc_ref(Value const & sx,std::string const & key)76 assoc_ref(Value const& sx, std::string const& key)
77 {
78   if (sx.is_nil())
79   {
80     return Value::nil_ref();
81   }
82   else if (sx.is_cons())
83   {
84     Value const& pair = sx.get_car();
85     if (pair.is_cons() &&
86         pair.get_car().is_symbol() &&
87         pair.get_car().as_string() == key)
88     {
89       return pair.get_cdr();
90     }
91     else
92     {
93       return assoc_ref(sx.get_cdr(), key);
94     }
95   }
96   else
97   {
98     std::ostringstream msg;
99     msg << "malformed input to sexp::assoc_ref(): sx:\"" << sx << "\" key:\"" << key << "\"";
100     throw std::runtime_error(msg.str());
101   }
102 }
103 
104 } // namespace sexp
105 
106 /* EOF */
107