root/trunk/whisperlib/net/rpc/parser/rpc-ptypes-check.cc

Revision 7, 11.4 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2009, Whispersoft s.r.l.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Whispersoft s.r.l. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Cosmin Tudorache
31
32 #include "net/rpc/parser/rpc-ptypes-check.h"
33 #include <algorithm>
34 #include "net/rpc/parser/export/rpc-base-types.h"
35 #include "common/base/types.h"
36 #include "common/base/log.h"
37
38
39 #define LOG_LOCATION(fileInfo) \
40   (fileInfo).filename_.c_str() << ":" << (fileInfo).lineno_ << " "
41
42 bool Contains(const vector<string>& array,
43               const string& item) {
44   return find(array.begin(), array.end(), item) != array.end();
45 }
46
47 bool Contains(const map<string, const PCustomType*>& stringMap,
48               const string& name) {
49   return stringMap.find(name) != stringMap.end();
50 }
51
52 bool Contains(const Keywords& keywords, const string& item) {
53   return keywords.ContainsKeyword(item);
54 }
55
56 bool IsKnownType(const PType& type,
57                  const vector<string>  rpcBaseTypes,
58                  const map<string, const PCustomType*>& customTypes) {
59   if ( type.name_ == RPC_ARRAY ) {
60     CHECK_NOT_NULL(type.subtype1_);
61     return IsKnownType(*type.subtype1_, rpcBaseTypes, customTypes);
62   }
63   if ( type.name_ == RPC_MAP ) {
64     CHECK_NOT_NULL(type.subtype1_);
65     CHECK_NOT_NULL(type.subtype2_);
66     return IsKnownType(*type.subtype1_, rpcBaseTypes, customTypes) &&
67            IsKnownType(*type.subtype2_, rpcBaseTypes, customTypes);
68   }
69   return Contains(rpcBaseTypes, type.name_) ||  // RPC base type.
70          Contains(customTypes, type.name_);     // previously defined customType
71 }
72
73 bool VerifyPTypesCorrectenss(const PCustomTypeArray customTypes,
74                              const PServiceArray services,
75                              const Keywords& restrictedKeywords) {
76   // make a vector of base types.
77   const vector<string>& rpcBaseTypes = rpc::BaseTypeArray();
78
79   bool bErrorFound = false;
80
81   // verify types
82   //
83   // a list of found types:
84   map<string, const PCustomType*> definedCustomTypes;
85   for ( PCustomTypeArray::const_iterator it = customTypes.begin();
86         it != customTypes.end(); ++it ) {
87     const PCustomType& customType = *it;
88     const string& customTypeName = customType.name_;
89
90     // check not an rpcBaseType
91     //
92     if ( Contains(rpcBaseTypes, customTypeName) ) {
93       LOG_ERROR << LOG_LOCATION(customType)
94                 << "You cannot redefine a base type";
95       bErrorFound = true;
96     }
97
98     // check not a restricted keyword
99     //
100     if ( Contains(restrictedKeywords, customTypeName) ) {
101       LOG_ERROR << LOG_LOCATION(customType)
102                 << "Type '" << customTypeName << "'"
103                 << " is a restricted keyword in "
104                 << restrictedKeywords.LanguageName() << ".";
105       bErrorFound = true;
106     }
107
108     // check not a duplicate
109     //
110     map<string, const PCustomType*>::iterator
111       itDup = definedCustomTypes.find(customType.name_);
112     if ( itDup != definedCustomTypes.end() ) {
113       const PCustomType& previousType = *itDup->second;
114       LOG_ERROR << LOG_LOCATION(customType)
115                 << "Duplicate type " << customType.name_
116                 << " already defined at "
117                 << LOG_LOCATION(previousType);
118       bErrorFound = true;
119     }
120
121     // check all attributes are known types
122     //
123     const PAttributeArray& attributes = customType.attributes_;
124     for ( PAttributeArray::const_iterator it = attributes.begin();
125           it != attributes.end(); ++it ) {
126       const PAttribute& attribute = *it;
127       const PType& attributeType = attribute.type_;
128
129       //
130       // attributeType must be a base type or a previous defined custom type
131       //
132
133       if ( !IsKnownType(attributeType, rpcBaseTypes, definedCustomTypes) ) {
134         // undefied attribute type
135         LOG_WARNING << LOG_LOCATION(attribute)
136                     << "Undefined type " << attributeType;
137         //bErrorFound = true;
138       }
139     }
140     definedCustomTypes[customTypeName] = &customType;
141   }
142
143   vector<string> foundServiceNames;
144
145   // verify services
146   //
147   for ( PServiceArray::const_iterator it = services.begin();
148         it != services.end(); ++it) {
149     const PService& service = *it;
150     const string& serviceName = service.name_;
151     const PFunctionArray& functions = service.functions_;
152
153     //
154     // check service name is not a known type
155     //
156     if ( Contains(rpcBaseTypes, serviceName) ) {
157       LOG_ERROR << LOG_LOCATION(service)
158                 << "Illegal service name. " << serviceName
159                 << " is a RPC base type.";
160       bErrorFound = true;
161     }
162     if ( Contains(restrictedKeywords, serviceName) ) {
163       LOG_ERROR << LOG_LOCATION(service)
164                 << "Illegal service name. '" << serviceName << "'"
165                 << " is a restricted keyword in "
166                 << restrictedKeywords.LanguageName() << ".";
167       bErrorFound = true;
168     }
169
170     map<string, const PCustomType*>::iterator
171       itDup = definedCustomTypes.find(serviceName);
172     if ( itDup != definedCustomTypes.end() ) {
173       const PCustomType& previousType = *itDup->second;
174       LOG_ERROR << LOG_LOCATION(service)
175                 << "Illegal service name. " << serviceName
176                 << " is already defined as typename at "
177                 << LOG_LOCATION(previousType);
178       bErrorFound = true;
179     }
180
181     // check service name is not duplicate
182     //
183     PServiceArray::const_iterator itPreviousSameNameService = services.begin();
184     for ( ; itPreviousSameNameService != it &&
185             itPreviousSameNameService->name_ != serviceName;
186           ++itPreviousSameNameService) {
187     }
188     if ( itPreviousSameNameService != it ) {
189       LOG_ERROR << LOG_LOCATION(service)
190                 << "Duplicate service name \"" << serviceName
191                 << "\". First defined at: "
192                 << LOG_LOCATION(*itPreviousSameNameService);
193       bErrorFound = true;
194     }
195
196     // check functions
197     //
198     for ( PFunctionArray::const_iterator it = functions.begin();
199           it != functions.end(); ++it ) {
200       const PFunction& function = *it;
201       const string& functionName = function.name_;
202       const PParamArray& args = function.input_;
203       const PType& ret = function.output_;
204
205       //
206       // check function name is not a known type
207       //
208       if ( Contains(rpcBaseTypes, functionName) ) {
209         LOG_ERROR << LOG_LOCATION(function)
210                   << "Illegal function name. " << functionName
211                   << " is a RPC base type.";
212         bErrorFound = true;
213       }
214       if ( Contains(restrictedKeywords, functionName) ) {
215         LOG_ERROR << LOG_LOCATION(function)
216                   << "Illegal function name. '" << functionName << "'"
217                   << " is a restricted keyword in "
218                   << restrictedKeywords.LanguageName() << ".";
219         bErrorFound = true;
220       }
221       map<string, const PCustomType*>::iterator
222         itDup = definedCustomTypes.find(functionName);
223       if ( itDup != definedCustomTypes.end() ) {
224         const PCustomType& previousType = *itDup->second;
225         LOG_ERROR << LOG_LOCATION(function)
226                   << "Illegal function name. " << functionName
227                   << " is already defined as typename at "
228                   << LOG_LOCATION(previousType);
229       }
230
231       // check function name is not duplicate
232       //
233       PFunctionArray::const_iterator
234         itPreviousSameNameFunction = functions.begin();
235       for ( ; itPreviousSameNameFunction != it &&
236               itPreviousSameNameFunction->name_ != functionName;
237             ++itPreviousSameNameFunction) {
238       }
239       if ( itPreviousSameNameFunction != it ) {
240         LOG_ERROR << LOG_LOCATION(function)
241                   << "Duplicate function name \"" << functionName
242                   << "\". First defined at: "
243                   << LOG_LOCATION(*itPreviousSameNameFunction);
244         bErrorFound = true;
245       }
246
247       // check function arguments
248       //
249       for ( PParamArray::const_iterator it = args.begin();
250             it != args.end(); ++it ) {
251         // every argument should be a known type
252         //
253         const PParam& arg = *it;
254         if ( !IsKnownType(arg.type_, rpcBaseTypes, definedCustomTypes) ) {
255           // undefined type
256           LOG_WARNING << LOG_LOCATION(function)
257                       << "Undefined type " << arg.type_;
258           //bErrorFound = true;
259         }
260
261         //
262         // check argument name is not identical with a type
263         //
264         if ( Contains(rpcBaseTypes, arg.name_) ) {
265           LOG_ERROR << LOG_LOCATION(function)
266                     << "Illegal argument name. " << arg.name_
267                     << " is a RPC base type.";
268           bErrorFound = true;
269         }
270         if ( Contains(restrictedKeywords, arg.name_) ) {
271           LOG_ERROR << LOG_LOCATION(function)
272                     << "Illegal argument name. '" << arg.name_ << "'"
273                     << " is a restricted keyword in "
274                     << restrictedKeywords.LanguageName() << ".";
275           bErrorFound = true;
276         }
277         map<string, const PCustomType*>::iterator
278           itDup = definedCustomTypes.find(arg.name_);
279         if ( itDup != definedCustomTypes.end() ) {
280           const PCustomType& previousType = *itDup->second;
281           LOG_ERROR << LOG_LOCATION(function)
282                     << "Illegal argument name. " << arg.name_
283                     << " is already defined as typename at "
284                     << LOG_LOCATION(previousType);
285         }
286
287         // check argument name is not duplicate
288         //
289         PParamArray::const_iterator itPreviousSameNameArgument = args.begin();
290         for ( ; itPreviousSameNameArgument != it &&
291                   itPreviousSameNameArgument->name_ != arg.name_;
292               ++itPreviousSameNameArgument) {
293         }
294         if ( itPreviousSameNameArgument != it ) {
295           LOG_ERROR << LOG_LOCATION(function)
296                     << "Duplicate argument name \"" << arg.name_
297                     << "\".";
298           bErrorFound = true;
299         }
300       }
301
302       // check function return is a known type
303       //
304       if ( !IsKnownType(ret, rpcBaseTypes, definedCustomTypes) ) {
305         // undefied type
306         LOG_WARNING << LOG_LOCATION(function) << "Undefined type " << ret;
307         // bErrorFound = true;
308       }
309     }
310   }
311
312   return !bErrorFound;
313 }
Note: See TracBrowser for help on using the browser.