PhoenixGenerator  2.0.4
Set of tools to generate code
Loading...
Searching...
No Matches
WrapperTraitDataStream.cpp
Go to the documentation of this file.
1
2/***************************************
3 Auteur : Pierre Aubert
4 Mail : pierre.aubert@lapp.in2p3.fr
5 Licence : CeCILL-C
6****************************************/
7
9
11
17void data_stream_trait_wrapper_callAttributeCheck(std::ofstream & fs, const PString & className, const PClassAttribute & attr, const PString & moduleName, const PString & expectedType){
18 PString attrType(attr.getType()), attrName(attr.getName());
19 PString typeNameVar(attrName+"Name");
20 fs << "\tstd::string "+typeNameVar+"(_PyType_Name(Py_TYPE(obj."+attrName+")));\n";
21 fs << "\tif("+typeNameVar+" != \""+expectedType+"\"){\n";
22 fs << "\t\terror << \"- Type of attribute "+className+"::"+attrName+" is '\"<<"+typeNameVar+"<<\"' and not expected '"+expectedType+"'\\n\";\n";
23 fs << "\t\tb = false;\n";
24 fs << "\t}\n";
25}
26
28
32void data_stream_trait_wrapper_classImplCheck(std::ofstream & fs, const PClassConfig & classConfig, const PString & moduleName){
33 PString className(wrapper_getClassName(classConfig));
34 fs << "///Check if the "+className+" contains all the expected types\n";
35 fs << "/**\t@param[out] error : error to be set if there is one\n";
36 fs << " * \t@param obj : reference to the "+className+"\n";
37 fs << " * \t@return true if the class "+className+" contains expected types, false otherwise\n";
38 fs << "*/\n";
39 fs << "bool "+className+"_check(std::stringstream & error, const "+className+" & obj){\n";
40 fs << "\tbool b(true);\n";
41 if(classConfig.getIsEnum()){
42 fs << "\t//TODO : WrapperTraitDataStream data_stream_trait_wrapper_classImplCheck not implemented for enum" << std::endl;
43 std::cerr << "\t//TODO : WrapperTraitDataStream data_stream_trait_wrapper_classImplCheck not implemented for enum" << std::endl;
44 }else{
45 const PVecClassAttribute & vecAttr = classConfig.getListAttribute();
46 for(PVecClassAttribute::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
47 PString attrType(it->getType());
48 if(getIsSimpleType(attrType)){
49 continue;
50 }
51 PString attrName(it->getName());
52 fs << "\t//Check of the attribute "+attrName+" of type "+attrType+"\n";
53 if(attrType == "std::string"){
54 data_stream_trait_wrapper_callAttributeCheck(fs, className, *it, moduleName, "str");
55 }else if(attrType == "DataStreamMsg"){
56 data_stream_trait_wrapper_callAttributeCheck(fs, className, *it, moduleName, "bytearray");
57 }else if(generator_typeIsList(attrType)){
58 PString nestedType(generator_getListNestedType(attrType));
59 data_stream_trait_wrapper_callAttributeCheck(fs, className, *it, moduleName, "list");
60 fs << "\t//Now we have to check all elements of "+attrName+"\n";
61 fs << "\tif(b){\t//If obj."+attrName+" is not a list we will have a problem\n";
62 fs << "\t\tfor(long i(0l); i < PyList_Size(obj."+attrName+"); ++i){\n";
63 fs << "\t\t\tPyObject * el = PyList_GET_ITEM(obj."+attrName+", i);\n";
64 fs << "\t\t\tstd::string elType(_PyType_Name(Py_TYPE(el)));\n";
65 PString expectedType(moduleName + "." + nestedType);
66 if(getIsSimpleType(nestedType)){
67 expectedType = wrapper_getExpectedType(nestedType);
68 }else{
69 fs << "\t\t\t//TODO : For some reason python and ipython agree to tell type("+nestedType+") is "+expectedType+" but during my test I get "+nestedType+" so I add it but I don't know why\n";
70 }
71 fs << "\t\t\tif(elType != \""+expectedType+"\" && elType != \""+nestedType+"\"){\n";
72 fs << "\t\t\t\terror << \"- Type of element "+className+"::"+attrName+"[\"<<i<<\"] is '\"+elType+\"' and not expected '"+expectedType+"'\\n\";\n";
73 fs << "\t\t\t\tb = false;\n";
74 fs << "\t\t\t}\n";
75 fs << "\t\t}\n";
76 fs << "\t}\n";
77 }else if(it->getIsEnum()){
78 fs << "\t//Let's check the enum\n";
79 data_stream_trait_wrapper_callAttributeCheck(fs, className, *it, moduleName, it->getType());
80 }
81 }
82 }
83 fs << "\treturn b;\n";
84 fs << "}\n\n";
85}
86
88
92void data_stream_trait_wrapper_classPythonFromBytes(std::ofstream & fs, const PClassConfig & classConfig, const PString & className){
93 fs << "///Initialise a "+className+" with a ByteArray\n";
94 fs << "/**\t@param self : pointer to the "+className+"\n";
95 fs << " * \t@param args : PyByteArray to initialise the "+className+"\n";
96 fs << " * \t@return Py_RETURN_NONE\n";
97 fs << "*/\n";
98 fs << "PyObject * "+className+"_fromBytes(PyObject *self, PyObject *args){\n";
99 fs << "\t"+className+"* obj = ("+className+"*)self;\n";
100 fs << "\tPyObject * byteArray = NULL;\n";
101 fs << wrapper_getObjectParseTuple("byteArray");
102 fs << "\t//We have to check if byteArray is a 'bytearray'\n";
103 fs << "\tstd::string inputTypeName(_PyType_Name(Py_TYPE(byteArray)));\n";
104 fs << "\tif(inputTypeName != \"bytearray\"){\n";
105 fs << "\t\tstd::string error(\""+className+"_fromBytes : cannot load "+className+" with given '\"+inputTypeName+\"', expecting 'bytearray'\\n\");\n";
106 fs << "\t\tPyErr_SetString(PyExc_RuntimeError, error.c_str());\n";
107 fs << "\t\treturn NULL;\n";
108 fs << "\t}\n";
109 fs << "\tsize_t nbByte = PyByteArray_Size(byteArray);\n";
110 fs << "\tif(nbByte == 0lu){\n";
111 fs << "\t\tPy_RETURN_NONE;\n";
112 fs << "\t}\n";
113 fs << "\tDataStreamIter iter = (DataStreamIter)PyByteArray_AsString(byteArray);\n";
114 fs << "\tif(!"+className+"_fromMessage(*obj, iter)){\n";
115 fs << "\t\tPyErr_SetString(PyExc_RuntimeError, \""+className+"_fromBytes : cannot load "+className+" with given PyByteArray\\n\");\n";
116 fs << "\t\treturn NULL;\n";
117 fs << "\t}\n";
118 fs << "\tPy_RETURN_NONE;\n";
119 fs << "}\n\n";
120
121 fs << "///Load a "+className+" from a DataStreamIter\n";
122 fs << "/**\t@param obj : reference to the "+className+"\n";
123 fs << " * \t@param iter : DataStreamIter to be used\n";
124 fs << " * \t@return true on success, false otherwise\n";
125 fs << "*/\n";
126 fs << "size_t "+className+"_fromMessage("+className+" & obj, DataStreamIter & iter){\n";
127 fs << "\tbool b(true);\n";
128 if(classConfig.getIsEnum()){
129 fs << "\t//TODO : WrapperTraitDataStream data_stream_trait_wrapper_classPythonFromBytes to be implemented" << std::endl;
130 std::cerr << "\t//TODO : WrapperTraitDataStream data_stream_trait_wrapper_classPythonFromBytes to be implemented" << std::endl;
131 }else{
132 const PVecClassAttribute & vecAttr = classConfig.getListAttribute();
133 for(PVecClassAttribute::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
134 const PString & attrName = it->getName();
135 fs << "\tb &= "+className+"_"+attrName+"_fromMessage(obj, iter);\n";
136 }
137 }
138 fs << "\treturn b;\n";
139 fs << "}\n\n";
140}
141
143
147void data_stream_trait_wrapper_classCheckCall(std::ofstream & fs, const PString & className, const PString & functionName){
148 fs << "\t//In case of emergency : check the integrity of the types before getting the size of to ensure all attributes have to good type\n";
149 fs << "\tstd::stringstream error(\"\");\n";
150 fs << "\tif(!"+className+"_check(error, *obj)){\n";
151 fs << "\t\tstd::string errorText(\""+functionName+" : check of class "+className+" failled\\n\" + error.str());\n";
152 fs << "\t\tPyErr_SetString(PyExc_RuntimeError, errorText.c_str());\n";
153 fs << "\t\treturn NULL;\n";
154 fs << "\t}\n";
155}
156
158
162void data_stream_trait_wrapper_classPythonToBytes(std::ofstream & fs, const PClassConfig & classConfig, const PString & className){
163
164 fs << "///Convert a "+className+" to a ByteArray\n";
165 fs << "/**\t@param self : pointer to the "+className+"\n";
166 fs << " * \t@param args : not used\n";
167 fs << " * \t@return PyByteArray which contains data of the "+className+"\n";
168 fs << "*/\n";
169 fs << "PyObject * "+className+"_toBytes(PyObject *self, PyObject *args){\n";
170 fs << "\t"+className+"* obj = ("+className+"*)self;\n";
171 data_stream_trait_wrapper_classCheckCall(fs, className, className+"_toBytes");
172 fs << "\tsize_t nbByte = "+className+"_getSize(*obj);\n";
173 fs << "\tif(nbByte == 0lu){\n";
174 fs << "\t\tPyErr_SetString(PyExc_RuntimeError, \"data_stream_trait_wrapper_classPythonToBytes : cannot serialise "+className+" of size 0 into a PyByteArray\\n\");\n";
175 fs << "\t\treturn NULL;\n";
176 fs << "\t}\n";
177 fs << "\tDataStreamMsg msg(nbByte);\n";
178 fs << "\tDataStreamIter iter = msg.data();\n";
179 fs << "\t\n";
180 fs << "\tif(!"+className+"_toMessage(*obj, iter)){\n";
181 fs << "\t\tPyErr_SetString(PyExc_RuntimeError, \"data_stream_trait_wrapper_dataStreamMethod : cannot save "+className+" into a PyByteArray\\n\");\n";
182 fs << "\t\treturn NULL;\n";
183 fs << "\t}\n";
184 fs << "\treturn PyByteArray_FromStringAndSize((const char*)msg.data(), nbByte);\n";
185 fs << "}\n\n";
186
187 fs << "///Write a "+className+" in a DataStreamIter\n";
188 fs << "/**\t@param obj : reference to the "+className+"\n";
189 fs << " * \t@param iter : DataStreamIter to be used\n";
190 fs << " * \t@return true on success, false otherwise\n";
191 fs << "*/\n";
192 fs << "size_t "+className+"_toMessage("+className+" & obj, DataStreamIter & iter){\n";
193 fs << "\tbool b(true);\n";
194 if(classConfig.getIsEnum()){
195 fs << "\t//TODO : WrapperTraitDataStream data_stream_trait_wrapper_classPythonToBytes to be implemented" << std::endl;
196 std::cerr << "\t//TODO : WrapperTraitDataStream data_stream_trait_wrapper_classPythonToBytes to be implemented" << std::endl;
197 }else{
198 const PVecClassAttribute & vecAttr = classConfig.getListAttribute();
199 for(PVecClassAttribute::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
200 const PString & attrName = it->getName();
201 fs << "\tb &= "+className+"_"+attrName+"_toMessage(obj, iter);\n";
202 }
203 }
204 fs << "\treturn b;\n";
205 fs << "}\n\n";
206}
207
209
213void data_stream_trait_wrapper_classPythonGetSizeInBytes(std::ofstream & fs, const PClassConfig & classConfig, const PString & className){
214
215 fs << "///Get the size in bytes of "+className+" for Python API\n";
216 fs << "/**\t@param self : pointer to the "+className+"\n";
217 fs << " * \t@param args : not used\n";
218 fs << " * \t@return size of the "+className+" in bytes\n";
219 fs << "*/\n";
220 fs << "PyObject * "+className+"_getSizeInByte(PyObject *self, PyObject *args){\n";
221 fs << "\t"+className+"* obj = ("+className+"*)self;\n";
222 data_stream_trait_wrapper_classCheckCall(fs, className, className+"_getSizeInByte");
223 fs << "\tsize_t nbByte = "+className+"_getSize(*obj);\n";
224 fs << "\treturn Py_BuildValue(\"k\", nbByte);\n";
225 fs << "}\n\n";
226
227 fs << "///Get the size of a "+className+"\n";
228 fs << "/**\t@param obj : reference to the "+className+" to be used\n";
229 fs << " * \t@return size of the "+className+" in bytes\n";
230 fs << "*/\n";
231 fs << "size_t "+className+"_getSize("+className+" & obj){\n";
232 fs << "\tsize_t nbByte(0lu);\n";
233 if(classConfig.getIsEnum()){
234 fs << "\tnbByte += sizeof(int);" << std::endl;
235 }else{
236 const PVecClassAttribute & vecAttr = classConfig.getListAttribute();
237 for(PVecClassAttribute::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
238 const PString & attrName = it->getName();
239 fs << "\tnbByte += "+className+"_"+attrName+"_getSize(obj);\n";
240 }
241 }
242 fs << "\treturn nbByte;\n";
243 fs << "}\n\n";
244}
245
247
251void data_stream_trait_wrapper_classAttributeFromMessage(std::ofstream & fs, const PString & className, const PClassAttribute & attr){
252 const PString & attrName = attr.getName(), & type(attr.getType());
253 bool isSimpleType(getIsSimpleType(type));
254 PString callAttr("self."+attrName);
255 fs << "///Load a "+className+"."+attrName+" from a DataStreamMsg\n";
256 fs << "/**\t@param self : reference to the "+className+"\n";
257 fs << " * \t@param iter : DataStreamIter to be used\n";
258 fs << " * \t@return true on success, false otherwise\n";
259 fs << "*/\n";
260 PString functionName(className+"_" + attrName + "_fromMessage");
261 fs << "bool "+functionName + "("+className+" & self, DataStreamIter & iter){\n";
262 if(isSimpleType){
263 fs << "\treturn DataStream<DataStreamIter, DataStreamMode::READ, "+type+">::data_stream(iter, "+callAttr+");\n";
264 }else if(type == "std::string"){
265 fs << "\tstd::string tmpStr(\"\");\n";
266 fs << "\tif(!DataStream<DataStreamIter, DataStreamMode::READ, "+type+">::data_stream(iter, tmpStr)){return false;};\n";
267// fs << "\tself."+attrName+" = PyBytes_FromStringAndSize(tmpStr.c_str(), tmpStr.size());\n";
268// fs << "\tself."+attrName+" = PyUnicode_FromStringAndSize(tmpStr.c_str(), tmpStr.size());\n";
269 fs << "\tself."+attrName+" = PyUnicode_DecodeFSDefaultAndSize(tmpStr.c_str(), tmpStr.size());\n";
270 fs << "\treturn true;\n";
271 }else if(type == "DataStreamMsg"){
272 fs << "\tDataStreamMsg message;\n";
273 fs << "\tif(!DataStream<DataStreamIter, DataStreamMode::READ, "+type+">::data_stream(iter, message)){return false;};\n";
274 fs << "\tself."+attrName+" = PyByteArray_FromStringAndSize((const char*)message.data(), message.size());\n";
275 fs << "\treturn true;\n";
276 }else if(generator_typeIsList(type)){
277 fs << "\tsize_t nbElement(0lu);\n";
278 fs << "\tif(!DataStream<DataStreamIter, DataStreamMode::READ, size_t>::data_stream(iter, nbElement)){return false;};\n";
279 fs << "\tif(nbElement == 0lu){return true;}\t//The list can be empty\n";
280 fs << "\t"+callAttr+" = PyList_New(nbElement);\n";
281 fs << "\tfor(size_t i(0lu); i < nbElement; ++i){\t//Then we load the content of the list\n";
282 PString nestedType(generator_getListNestedType(type));
283 if(getIsSimpleType(nestedType)){
284 fs << "\t\t"+nestedType+" value = 0;\n";
285 fs << "\t\tif(!DataStream<DataStreamIter, DataStreamMode::READ, "+nestedType+">::data_stream(iter, value)){return false;};\n";
286 fs << "\t\tPyObject * el = "+wrapper_getValueToObject(nestedType)+"(value);\n";
287// fs << "\t\tPyObject * el = Py_BuildValue(\""+wrapper_getBuildValueStr(nestedType)+"\", value);\n";
288 fs << "\t\tPyList_SET_ITEM("+callAttr+", i, el);\n";
289 }else{
290 fs << "\t\t//If it is not a predefined type, we cannot deal with it\n";
291 fs << "\t\tWP"+nestedType+" * el = (WP"+nestedType+"*)WP"+nestedType+"_newC(&WP"+nestedType+"Type, NULL, NULL);\n";
292 fs << "\t\tif(!WP"+nestedType+"_fromMessage(*el, iter)){return false;}\n";
293 fs << "\t\tPyList_SET_ITEM("+callAttr+", i, el);\n";
294 }
295 fs << "\t}\n";
296 fs << "\treturn true;\n";
297 }else if(attr.getIsEnum()){
298 fs << "\t//TODO : implement the load from a message of type "+type+"\n";
299 fs << "\t//We know, for sure it is an Enum but we have to figure out how we are supposed to deal with it inside the wrapper\n";
300 fs << "\t//And I really wanted to avoid to call the interpreter once more each time we want to deserialise an Enum\n";
301 fs << "\tint enumValue = 0;\n";
302 fs << "\tif(!DataStream<DataStreamIter, DataStreamMode::READ, int>::data_stream(iter, enumValue)){\n";
303 fs << "\t\tstd::cerr << \""+functionName+" : cannot read enum value\" << std::endl;\n";
304 fs << "\t\treturn false;\n";
305 fs << "\t}\n";
306// fs << "\tif(PyObject_SetAttrString("+callAttr+", \"value\", PyLong_FromLong(enumValue)) != 0){\n";
307// fs << "\t\tstd::cerr << \""+functionName+" : cannot set enum value(\"<<enumValue<<\") in PyObject\" << std::endl;\n";
308// fs << "\t\treturn false;\n";
309// fs << "\t}\n";
310 fs << "\tstd::map<int, std::string>::const_iterator it = WP"+type+"EnumValue.find(enumValue);\n";
311 fs << "\tif(it == WP"+type+"EnumValue.end()){\n";
312 fs << "\t\tstd::cerr << \""+functionName+" : cannot find enum value \" << enumValue << \" in map WP"+type+"EnumValue\" << std::endl;\n";
313 fs << "\t\treturn false;\n";
314 fs << "\t}\n";
315
316 fs << "\tPy_DECREF("+callAttr+");\n";
317 fs << "\t"+callAttr+" = WP"+type+"_newGeneric(\"_var_______ = "+type+".\" + it->second, \"_var_______\");\n";
318 fs << "\treturn true;\n";
319
320// fs << "\treturn PyObject_SetAttrString("+callAttr+", \"name\", PyUnicode_FromStringAndSize(it->second.c_str(), it->second.size())) == 0;\n";
321 }else{
322 fs << "\t//TODO : implement the load from a message of type "+type+"\n";
323 fs << "\treturn true;\n";
324 }
325 fs << "}\n\n";
326}
327
329
333void data_stream_trait_wrapper_classAttributeToMessage(std::ofstream & fs, const PString & className, const PClassAttribute & attr){
334 const PString & attrName = attr.getName(), & type(attr.getType());
335 bool isSimpleType(getIsSimpleType(type));
336 PString callAttr("self."+attrName);
337 fs << "///Convert a "+className+"."+attrName+" to a DataStreamMsg\n";
338 fs << "/**\t@param self : reference to the "+className+"\n";
339 fs << " * \t@param iter : DataStreamIter to be used\n";
340 fs << " * \t@return true on success, false otherwise\n";
341 fs << "*/\n";
342 fs << "bool "+className+"_" + attrName + "_toMessage("+className+" & self, DataStreamIter & iter){\n";
343 if(isSimpleType){
344 fs << "\treturn DataStream<DataStreamIter, DataStreamMode::WRITE, "+type+">::data_stream(iter, "+callAttr+");\n";
345 }else if(type == "std::string"){
346// fs << "\tsize_t nbChar(PyUnicode_GetLength("+callAttr+"));\n"; //PyUnicode_GET_LENGTH
347 fs << "\tlong nbChar(0lu);\n";
348 fs << "\tconst char * ptr = PyUnicode_AsUTF8AndSize("+callAttr+", &nbChar);\n";
349
350 fs << "\tif(!DataStream<DataStreamIter, DataStreamMode::WRITE, long>::data_stream(iter, nbChar)){return false;}\n";
351// fs << "\tconst char * ptr = PyBytes_AsString("+callAttr+");\n"; //PyBytes_AsString
352 fs << "\treturn DataStream<DataStreamIter, DataStreamMode::WRITE, char>::data_stream(iter, (char*)ptr, nbChar);\n";
353 }else if(type == "DataStreamMsg"){
354 fs << "\tsize_t nbByte(PyByteArray_Size("+callAttr+"));\n";
355 fs << "\tif(!DataStream<DataStreamIter, DataStreamMode::WRITE, size_t>::data_stream(iter, nbByte)){return false;}\n";
356 fs << "\tif(nbByte == 0lu){return true;}\t//The bytearray can be empty\n";
357 fs << "\tDataStreamIter dataPtr = (DataStreamIter)PyByteArray_AsString("+callAttr+");\n";
358 fs << "\treturn DataStream<DataStreamIter, DataStreamMode::WRITE, DataStreamType>::data_stream(iter, dataPtr, nbByte);\n";
359 }else if(generator_typeIsList(type)){
360 fs << "\tsize_t nbElement(PyByteArray_Size("+callAttr+"));\n";
361 fs << "\tif(!DataStream<DataStreamIter, DataStreamMode::WRITE, size_t>::data_stream(iter, nbElement)){return false;}\n";
362 fs << "\tif(nbElement == 0lu){return true;}\t//The list can be empty\n";
363 fs << "\tfor(size_t i(0lu); i < nbElement; ++i){\t//Then the content of the list\n";
364 PString nestedType(generator_getListNestedType(type));
365 if(getIsSimpleType(nestedType)){
366 fs << "\t\tPyObject * el = PyList_GET_ITEM("+callAttr+", i);\n";
367 fs << "\t\t"+nestedType+" value = "+wrapper_getObjectToValue(nestedType)+"(el);\n";
368 fs << "\t\tif(!DataStream<DataStreamIter, DataStreamMode::WRITE, "+nestedType+">::data_stream(iter, value)){return false;}\n";
369 }else{
370 fs << "\t\t//If it is not a predefined type, we cannot deal with it\n";
371 fs << "\t\tPyObject * el = PyList_GET_ITEM("+callAttr+", i);\n";
372 fs << "\t\tif(!WP"+nestedType+"_toMessage((WP"+nestedType+"&)*el, iter)){return false;}\n";
373 }
374 fs << "\t}\n";
375 fs << "\treturn true;\n";
376 }else if(attr.getIsEnum()){
377 fs << "\t//TODO : implement the save to a message of type "+type+"\n";
378 fs << "\t//We know, for sure it is an Enum but we have to figure out how we are supposed to deal with it inside the wrapper\n";
379 fs << "\t//And I really wanted to avoid to call the interpreter once more each time we want to serialise an Enum\n";
380 fs << "\tPyObject * attrValue = PyObject_GetAttrString("+callAttr+", \"value\");\n";
381 fs << "\tif(attrValue == NULL){return false;}\n";
382 fs << "\t//Now we have to get the integer inside the attribute\n";
383 fs << "\tint enumValue = PyLong_AsInt(attrValue);\n";
384 fs << "\treturn DataStream<DataStreamIter, DataStreamMode::WRITE, int>::data_stream(iter, enumValue);\n";
385 }else{
386 fs << "\t//TODO : implement the save to a message of type "+type+"\n";
387 fs << "\treturn true;\n";
388 }
389 fs << "}\n\n";
390}
391
393
397void data_stream_trait_wrapper_classAttributeGetSize(std::ofstream & fs, const PString & className, const PClassAttribute & attr){
398 const PString & attrName = attr.getName(), & type(attr.getType());
399 bool isSimpleType(getIsSimpleType(type));
400 PString callAttr("self."+attrName);
401 fs << "///Get the size of "+className+"."+attrName+" in bytes\n";
402 fs << "/**\t@param self : reference to the "+className+"\n";
403 fs << " * \t@return size of "+className+"."+attrName+" in bytes\n";
404 fs << "*/\n";
405 fs << "size_t "+className+"_" + attrName + "_getSize("+className+" & self){\n";
406 fs << "\tsize_t nbByte(0lu);\n";
407 if(isSimpleType){
408 fs << "\tDataStream<size_t, DataStreamMode::WRITE, "+type+">::data_stream(nbByte, "+callAttr+");\n";
409 }else if(type == "std::string"){
410 fs << "\tnbByte += sizeof(size_t) + PyUnicode_GetLength("+callAttr+");\n"; //PyBytes_Size
411 }else if(type == "DataStreamMsg"){
412 fs << "\tnbByte += sizeof(size_t) + PyByteArray_Size("+callAttr+");\n"; //PyBytes_Size
413 }else if(generator_typeIsList(type)){
414 fs << "\tnbByte += sizeof(size_t);\t//First the size of the number of elements in the list\n";
415 PString nestedType(generator_getListNestedType(type));
416 if(getIsSimpleType(nestedType)){
417 fs << "\tnbByte += sizeof("+nestedType+")*PyList_Size("+callAttr+");\t//Then the content of the list\n";
418 }else{
419 fs << "\t//If it is not a predefined type, we cannot deal with it\n";
420 fs << "\tfor(long i(0l); i < PyList_Size("+callAttr+"); ++i){\t//Then the content of the list\n";
421 fs << "\t\tPyObject * el = PyList_GET_ITEM("+callAttr+", i);\n";
422 fs << "\t\tnbByte += WP"+nestedType+"_getSize((WP"+nestedType+"&)*el);\n";
423 fs << "\t}\n";
424 }
425 }else if(attr.getIsEnum()){
426 fs << "\t//The size of an Enum is the size of an integer\n";
427 fs << "\tnbByte += sizeof(int);\n";
428 }else{
429 fs << "\t//TODO : implement the get size of type "+type+"\n";
430 }
431 fs << "\treturn nbByte;\n";
432 fs << "}\n\n";
433}
434
436
439PString pythonGetDefaultTestValue(PString & type){
440 if(type == "int" || type == "long" || type == "long int" || type == "size_t" || type == "unsigned int" || type == "unsigned short" || type == "char" || type == "unsigned char" || type == "long unsigned int"){
441 return "42";
442 }else if(type == "float" || type == "double"){
443 return "42.0";
444 }else if(type == "std::string"){
445 return "\"Shadoko\"";
446 }else if(type == "DataStreamMsg"){
447 return "bytearray(b\"Shadoko\")";
448 }else if(generator_typeIsList(type)){
449 PString nestedType(generator_getListNestedType(type));
450 PString nestedDefaultValue(pythonGetDefaultTestValue(nestedType));
451 if(nestedDefaultValue != ""){
452 return "["+nestedDefaultValue+"]";
453 }else{
454 return "[]";
455 }
456 }
457
458 return "";
459}
460
462
469PString pythonDefaultTestValue(const PString & varName, const PClassAttribute & attr, const PString & moduleName, const PString & indentation,
470 const std::map<std::string, PClassConfig> & mapClass)
471{
472 PString type(attr.getType());
473 PString body(indentation);
474
475 PString initValue(pythonGetDefaultTestValue(type));
476 if(initValue != ""){
477 body += varName + "." + attr.getName() + " = "+initValue+"\n";
478 }else if(attr.getIsEnum()){
479 std::map<std::string, PClassConfig>::const_iterator it(mapClass.find(type));
480 if(it != mapClass.end()){
481 //Let's take the last value so we are sure this is not a 0 or a default value
482 body += varName + "." + attr.getName() + " = "+moduleName+"."+type+"."+it->second.getListAttribute().back().getName()+"\n";
483 }
484 }else{
485 return "";
486 }
487 return body;
488}
489
491
498PString pythonAssertTestValue(const PString & varName, const PClassAttribute & attr, const PString & moduleName, const PString & indentation,
499 const std::map<std::string, PClassConfig> & mapClass)
500{
501 PString type(attr.getType());
502 PString body(indentation);
503
504 PString initValue(pythonGetDefaultTestValue(type));
505 if(initValue != ""){
506 body += "assert " + varName + "." + attr.getName() + " == "+initValue+"\n";
507 }else if(attr.getIsEnum()){
508 std::map<std::string, PClassConfig>::const_iterator it(mapClass.find(type));
509 if(it != mapClass.end()){
510 body += "assert " + varName + "." + attr.getName() + ".value == "+moduleName+"."+type+"."+it->second.getListAttribute().back().getName()+".value\n";
511 }
512 }else{
513 return "";
514 }
515 return body;
516}
517
522
525
527
530void WrapperTraitDataStream::headerExtraInclude(std::ofstream & fs, const GeneratorMode & mode) const{
531 if(!mode.enableDataStream){return;}
532 fs << "#include \"phoenix_data_stream.h\"" << std::endl;
533}
534
536
540void WrapperTraitDataStream::classMethodDeclaration(std::ofstream & fs, const PClassConfig & classConfig, const GeneratorMode & mode) const{
541 if(!mode.enableDataStream){return;}
542 PString className(wrapper_getClassName(classConfig));
543 fs << "//Check function (used by data stream)\n";
544 fs << "bool "+className+"_check(std::string & error, const "+className+" & obj);\n";
545
546 fs << "//PhoenixDataStream interface\n";
547 fs << "PyObject * "+className+"_fromBytes(PyObject *self, PyObject *args);\n";
548 fs << "size_t "+className+"_fromMessage("+className+" & obj, DataStreamIter & iter);\n\n";
549
550 fs << "PyObject * "+className+"_toBytes(PyObject *self, PyObject *args);\n";
551 fs << "size_t "+className+"_toMessage("+className+" & obj, DataStreamIter & iter);\n\n";
552
553 fs << "PyObject * "+className+"_getSizeInByte(PyObject *self, PyObject *args);\n";
554 fs << "size_t "+className+"_getSize("+className+" & obj);\n\n";
555 if(!classConfig.getIsEnum()){
556 const PVecClassAttribute & vecAttr = classConfig.getListAttribute();
557 fs << "//PhoenixDataStream interface under the hood for all attributes\n";
558 for(PVecClassAttribute::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
559 fs << "//PhoenixDataStream interface under the hood for " + it->getName() + " attribute\n";
560 fs << "bool "+className+"_" + it->getName() + "_fromMessage("+className+" & self, DataStreamIter &iter);\n";
561 fs << "bool "+className+"_" + it->getName() + "_toMessage("+className+" & self, DataStreamIter &iter);\n";
562 fs << "size_t "+className+"_" + it->getName() + "_getSize("+className+" & self);\n\n";
563 }
564 }
565}
566
568
572void WrapperTraitDataStream::classMethodImplementation(std::ofstream & fs, const PClassConfig & classConfig, const GeneratorMode & mode) const{
573 if(!mode.enableDataStream){return;}
574 PString className(wrapper_getClassName(classConfig));
576 data_stream_trait_wrapper_classPythonFromBytes(fs, classConfig, className);
577 data_stream_trait_wrapper_classPythonToBytes(fs, classConfig, className);
578 data_stream_trait_wrapper_classPythonGetSizeInBytes(fs, classConfig, className);
579 if(!classConfig.getIsEnum()){
580 const PVecClassAttribute & vecAttr = classConfig.getListAttribute();
581 for(PVecClassAttribute::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
585 }
586 }
587}
588
590
594void WrapperTraitDataStream::registerClassGetterSetter(std::ofstream & fs, const PClassConfig & classConfig, const GeneratorMode & mode) const{
595 if(!mode.enableDataStream){return;}
596
597}
598
600
604void WrapperTraitDataStream::registerClassMethod(std::ofstream & fs, const PClassConfig & classConfig, const GeneratorMode & mode) const{
605 if(!mode.enableDataStream){return;}
606 PString className(wrapper_getClassName(classConfig));
607 fs << "\t{\"fromBytes\", (PyCFunction)"<<className<<"_fromBytes, METH_VARARGS, \"Doc : load a "<<className<<" from PyByteArray\"},\n";
608 fs << "\t{\"toBytes\", (PyCFunction)"<<className<<"_toBytes, METH_NOARGS, \"Doc : convert a "<<className<<" to PyByteArray\"},\n";
609 fs << "\t{\"getSize\", (PyCFunction)"<<className<<"_getSizeInByte, METH_NOARGS, \"Doc : Get the size of "<<className<<" in bytes\"},\n";
610}
611
613
617void WrapperTraitDataStream::testFunction(std::ofstream & fs, const PClassConfig & classConfig, const GeneratorMode & mode) const{
618 if(!mode.enableDataStream || classConfig.getIsEnum()){return;}
619 PString className(classConfig.getName()), moduleName(mode.moduleName);
620 fs << "#Unit Test of the " + className + "\n";
621 fs << "def test_datastream_"+className+"():\n";
622 fs << "\t#Let's test the stream now\n";
623 fs << "\tshadok = "+moduleName+"."+className+"()\n";
624 const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
625 for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
626 fs << pythonDefaultTestValue("shadok", *it, moduleName, "\t", mode.mapClass);
627 }
628 fs << "\tstream = shadok.toBytes()\n";
629 fs << "\tassert len(stream) != 0\n";
630 fs << "\t\n";
631 fs << "\tother = "+moduleName+"."+className+"()\n";
632 fs << "\tother.fromBytes(stream)\n";
633 for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
634 fs << pythonAssertTestValue("other", *it, moduleName, "\t", mode.mapClass);
635 }
636 fs << "\t\n";
637 fs << "\t\n";
638}
639
641
645void WrapperTraitDataStream::testCallFunction(std::ofstream & fs, const PClassConfig & classConfig, const GeneratorMode & mode) const{
646 if(!mode.enableDataStream){return;}
647
648}
649
651
654void WrapperTraitDataStream::setupAddDependency(std::ofstream & fs, const GeneratorMode & mode) const{
655 if(!mode.enableTypeStream){return;}
656 fs << "addWrapperDependency(listIncludeDir, listLibDir, listLib, \"phoenixdatastream-config\", [\"phoenix_data_stream\"])" << std::endl;
657}
658
659
std::vector< PClassAttribute > PVecClassAttribute
Definition PDataConfig.h:13
void data_stream_trait_wrapper_classPythonGetSizeInBytes(std::ofstream &fs, const PClassConfig &classConfig, const PString &className)
Do the implementation of data stream method _getSizeInByte for one class.
void data_stream_trait_wrapper_classImplCheck(std::ofstream &fs, const PClassConfig &classConfig, const PString &moduleName)
Do the check implementation of class.
void data_stream_trait_wrapper_classPythonToBytes(std::ofstream &fs, const PClassConfig &classConfig, const PString &className)
Do the implementation of data stream method _toBytes for one class.
void data_stream_trait_wrapper_callAttributeCheck(std::ofstream &fs, const PString &className, const PClassAttribute &attr, const PString &moduleName, const PString &expectedType)
Do the check call of an attribute of a given class.
PString pythonAssertTestValue(const PString &varName, const PClassAttribute &attr, const PString &moduleName, const PString &indentation, const std::map< std::string, PClassConfig > &mapClass)
Get the default set of given attribute for a test.
void data_stream_trait_wrapper_classAttributeFromMessage(std::ofstream &fs, const PString &className, const PClassAttribute &attr)
Do the implementation of from message of one attribute.
void data_stream_trait_wrapper_classPythonFromBytes(std::ofstream &fs, const PClassConfig &classConfig, const PString &className)
Do the implementation of data stream method _fromBytes for one class.
void data_stream_trait_wrapper_classAttributeToMessage(std::ofstream &fs, const PString &className, const PClassAttribute &attr)
Do the implementation of to message of one attribute.
PString pythonDefaultTestValue(const PString &varName, const PClassAttribute &attr, const PString &moduleName, const PString &indentation, const std::map< std::string, PClassConfig > &mapClass)
Get the default set of given attribute for a test.
void data_stream_trait_wrapper_classCheckCall(std::ofstream &fs, const PString &className, const PString &functionName)
Call the check of a class.
void data_stream_trait_wrapper_classAttributeGetSize(std::ofstream &fs, const PString &className, const PClassAttribute &attr)
Do the implementation of get size of one attribute.
PString pythonGetDefaultTestValue(PString &type)
Get the default of a given type for a test.
Describes a class attribute.
const PString & getType() const
Gets the type of the PClassAttribute.
bool getIsEnum() const
Gets the isEnum of the PClassAttribute.
const PString & getName() const
Gets the name of the PClassAttribute.
Class to describe a basic class.
const std::vector< PClassAttribute > & getListAttribute() const
Returns the list of attributes of the class.
const PString & getName() const
Returns the class name.
bool getIsEnum() const
Say if the current PClassConfig is an enum.
virtual void registerClassGetterSetter(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode) const
Register class getter and setter.
virtual void testFunction(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode) const
Implementation of test function.
virtual void registerClassMethod(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode) const
Register class method.
virtual void classMethodDeclaration(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode) const
Declaration of class method.
virtual ~WrapperTraitDataStream()
Desctructor of WrapperTraitDataStream.
virtual void headerExtraInclude(std::ofstream &fs, const GeneratorMode &mode) const
Add extra include on the header.
virtual void setupAddDependency(std::ofstream &fs, const GeneratorMode &mode) const
Add dependency in the setup.py.
virtual void classMethodImplementation(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode) const
Implementation of class method.
virtual void testCallFunction(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode) const
Call of the test function.
WrapperTraitDataStream()
Consctructor of WrapperTraitDataStream.
All the genertor modes.
std::map< std::string, PClassConfig > mapClass
Map of the generated class.
bool enableDataStream
True to enable data stream interface generator.
PString moduleName
Name of the wrapper python module.
bool enableTypeStream
True to enable type stream interface generator.
PString generator_getListNestedType(const PString &type)
Get the nested type inside a std::list.
bool generator_typeIsList(const PString &type)
Say if a given type is a std::list.
bool getIsSimpleType(const PString &varType)
Check if the given type is a simple type.
PString wrapper_getExpectedType(const PString &type)
Get the expected type of a given python type.
PString wrapper_getObjectToValue(const PString &type)
Get the function to convert the given object to a value.
PString wrapper_getObjectParseTuple(const PString &varName)
Get the proper code for PyArg_ParseTuple with one object.
PString wrapper_getValueToObject(const PString &type)
Get the function to convert the given value to a PyObject.
PString wrapper_getClassName(const PClassConfig &classConfig)
Get the corresponding wrapper class name.