1 //
2 // aegis - project change supervisor
3 // Copyright (C) 1995, 1996, 1999, 2002-2008, 2012 Peter Miller
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
7 // by 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 GNU
13 // 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
19 #include <common/ac/assert.h>
20
21 #include <common/mem.h>
22 #include <libaegis/aer/expr.h>
23 #include <libaegis/aer/func/substr.h>
24 #include <libaegis/aer/value/error.h>
25 #include <libaegis/aer/value/integer.h>
26 #include <libaegis/aer/value/string.h>
27 #include <libaegis/sub.h>
28
29
~rpt_func_substr()30 rpt_func_substr::~rpt_func_substr()
31 {
32 }
33
34
rpt_func_substr()35 rpt_func_substr::rpt_func_substr()
36 {
37 }
38
39
40 rpt_func::pointer
create()41 rpt_func_substr::create()
42 {
43 return pointer(new rpt_func_substr());
44 }
45
46
47 const char *
name() const48 rpt_func_substr::name()
49 const
50 {
51 return "substr";
52 }
53
54
55 bool
optimizable() const56 rpt_func_substr::optimizable()
57 const
58 {
59 return true;
60 }
61
62
63 bool
verify(const rpt_expr::pointer & ep) const64 rpt_func_substr::verify(const rpt_expr::pointer &ep)
65 const
66 {
67 return (ep->get_nchildren() == 3);
68 }
69
70
71 rpt_value::pointer
run(const rpt_expr::pointer & ep,size_t,rpt_value::pointer * argv) const72 rpt_func_substr::run(const rpt_expr::pointer &ep, size_t,
73 rpt_value::pointer *argv) const
74 {
75 rpt_value::pointer arg = argv[0];
76 assert(!arg->is_an_error());
77 arg = rpt_value::stringize(arg);
78 rpt_value_string *a1sp = dynamic_cast<rpt_value_string *>(arg.get());
79 if (!a1sp)
80 {
81 sub_context_ty sc;
82 sc.var_set_charstar("Function", "substr");
83 sc.var_set_long("Number", 1);
84 sc.var_set_charstar("Name", argv[0]->name());
85 nstring s
86 (
87 sc.subst_intl
88 (
89 i18n("$function: argument $number: string value required "
90 "(was given $name)")
91 )
92 );
93 return rpt_value_error::create(ep->get_pos(), s);
94 }
95 nstring subject(a1sp->query());
96
97 arg = argv[1];
98 assert(!arg->is_an_error());
99 arg = rpt_value::integerize(arg);
100 rpt_value_integer *a2ip = dynamic_cast<rpt_value_integer *>(arg.get());
101 if (!a2ip)
102 {
103 sub_context_ty sc;
104 sc.var_set_charstar("Function", "substr");
105 sc.var_set_long("Number", 2);
106 sc.var_set_charstar("Name", argv[1]->name());
107 nstring s
108 (
109 sc.subst_intl
110 (
111 i18n("$function: argument $number: integer value "
112 "required (was given $name)")
113 )
114 );
115 return rpt_value_error::create(ep->get_pos(), s);
116 }
117 long start = a2ip->query();
118
119 arg = argv[2];
120 assert(!arg->is_an_error());
121 arg = rpt_value::integerize(arg);
122 rpt_value_integer *a3ip = dynamic_cast<rpt_value_integer *>(arg.get());
123 if (!a3ip)
124 {
125 sub_context_ty sc;
126 sc.var_set_charstar("Function", "substr");
127 sc.var_set_long("Number", 3);
128 sc.var_set_charstar("Name", argv[2]->name());
129 nstring s
130 (
131 sc.subst_intl
132 (
133 i18n("$function: argument $number: integer value "
134 "required (was given $name)")
135 )
136 );
137 return rpt_value_error::create(ep->get_pos(), s);
138 }
139 long length = a3ip->query();
140
141 //
142 // clip the start and end to conform to the string
143 //
144 long end = start + length;
145 if (start < 0)
146 start = 0;
147 if (end < 0)
148 end = 0;
149 if (start > (long)subject.size())
150 start = subject.size();
151 if (end > (long)subject.size())
152 end = subject.size();
153 if (end < start)
154 {
155 start = 0;
156 end = 0;
157 }
158
159 //
160 // build the result
161 //
162 nstring s(subject.c_str() + start, end - start);
163 return rpt_value_string::create(s);
164 }
165
166
167 // vim: set ts=8 sw=4 et :
168