* Bug 16358 fixed: isdef([],..) yielded an error
[scilab.git] / scilab / modules / core / sci_gateway / cpp / sci_exists.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
4  *  Copyright (C) 2013 - Scilab Enterprises - Cedric Delamarre
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #include "core_gw.hxx"
18 #include "function.hxx"
19 #include "context.hxx"
20 #include "string.hxx"
21 #include "bool.hxx"
22 #include "double.hxx"
23
24 extern "C"
25 {
26 #include "localization.h"
27 #include "Scierror.h"
28 }
29
30 enum ScopeRange
31 {
32     Local,
33     NoLocal,
34     All,
35     UnknownRange
36 };
37
38 static ScopeRange getScopeFromOption(const wchar_t *_psScope)
39 {
40     if (wcscmp(_psScope, L"all") == 0 || wcscmp(_psScope, L"a") == 0)
41     {
42         return All;
43     }
44     if (wcscmp(_psScope, L"local") == 0 || wcscmp(_psScope, L"l") == 0)
45     {
46         return Local;
47     }
48     if (wcscmp(_psScope, L"nolocal") == 0 || wcscmp(_psScope, L"n") == 0)
49     {
50         return NoLocal;
51     }
52
53     return UnknownRange;
54 }
55
56 static types::Function::ReturnValue isdef(types::typed_list& in, int _iRetCount, types::typed_list& out, const char* fname)
57 {
58     types::String* pStrIn = NULL;
59
60     if (in.size() != 1 && in.size() != 2)
61     {
62         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected."), fname, 1, 2);
63         return types::Function::Error;
64     }
65
66     if (in[0]->isDouble() && in[0]->getAs<types::Double>()->isEmpty())
67     {
68         out.push_back(types::Double::Empty());
69         return types::Function::OK;
70     }
71
72     if (!in[0]->isString())
73     {
74         Scierror(999, _("%s: Wrong type for argument #%d: Matrix of strings expected.\n"), fname, 1);
75         return types::Function::Error;
76     }
77
78     if (in.size() == 2 && (!in[1]->isString() || in[1]->getAs<types::String>()->getSize() != 1))
79     {
80         Scierror(999, _("%s: Wrong type for input argument #%d: A single string expected.\n"), fname, 2);
81         return types::Function::Error;
82     }
83
84     const wchar_t *psScope = L"all"; // Default option is "all"
85     if (in.size() == 2)
86     {
87         psScope = in[1]->getAs<types::String>()->get(0);
88     }
89
90     pStrIn = in[0]->getAs<types::String>();
91
92     types::InternalType *pIT;
93     types::Bool* pBOut = new types::Bool(pStrIn->getDims(), pStrIn->getDimsArray());
94
95     switch (getScopeFromOption(psScope))
96     {
97         case All:
98             for (int i = 0; i < pStrIn->getSize(); i++)
99             {
100                 pIT = symbol::Context::getInstance()->get(symbol::Symbol(pStrIn->get(i)));
101                 pBOut->set(i, pIT != NULL && pIT->getType() != types::InternalType::ScilabVoid);
102             }
103             break;
104         case Local:
105             for (int i = 0; i < pStrIn->getSize(); i++)
106             {
107                 pIT = symbol::Context::getInstance()->getCurrentLevel(symbol::Symbol(pStrIn->get(i)));
108                 pBOut->set(i, pIT != NULL && pIT->getType() != types::InternalType::ScilabVoid);
109             }
110             break;
111         case NoLocal:
112             for (int i = 0; i < pStrIn->getSize(); i++)
113             {
114                 pIT = symbol::Context::getInstance()->getAllButCurrentLevel(symbol::Symbol(pStrIn->get(i)));
115                 pBOut->set(i, pIT != NULL && pIT->getType() != types::InternalType::ScilabVoid);
116             }
117             break;
118         default:
119             Scierror(36, _("%s: Wrong input argument %d.\n"), fname, 2);
120             return types::Function::Error;
121     }
122
123     out.push_back(pBOut);
124
125     return types::Function::OK;
126 }
127
128 types::Function::ReturnValue sci_isdef(types::typed_list &in, int _iRetCount, types::typed_list &out)
129 {
130     return isdef(in, _iRetCount, out, "isdef");
131 }
132
133 types::Function::ReturnValue sci_exists(types::typed_list &in, int _iRetCount, types::typed_list &out)
134 {
135     types::Function::ReturnValue retVal = isdef(in, _iRetCount, out, "exists");
136
137     if (retVal == types::Function::OK)
138     {
139         if (out[0]->isDouble() == false)
140         {
141             types::Bool* pBOut = out[0]->getAs<types::Bool>();
142             types::Double* pDblOut = new types::Double(pBOut->getDims(), pBOut->getDimsArray());
143             for (int i = 0; i < pBOut->getSize(); i++)
144             {
145                 pDblOut->set(i, (double)pBOut->get(i));
146             }
147             pBOut->killMe();
148             out.pop_back();
149
150             out.push_back(pDblOut);
151         }
152     }
153     return retVal;
154 }