3636 'cells' : 'ScintillaCells' ,
3737 'colour' : 'boost::python::tuple' ,
3838 'keymod' : 'int' # Temporary hack - need this to be a real type
39- }
39+ }
4040
4141castsL = {
4242 'boost::python::str' : lambda name : "reinterpret_cast<LPARAM>(static_cast<const char*>(boost::python::extract<const char *>(" + name + ")))" ,
4343 # Hack - assume a tuple is a colour
4444 'boost::python::tuple' : lambda name : "MAKECOLOUR(" + name + ")" .format (name )
45- }
46-
45+ }
46+
4747castsW = {
4848 'boost::python::str' : lambda name : "reinterpret_cast<WPARAM>(static_cast<const char*>(boost::python::extract<const char *>(" + name + ")))" ,
4949 # Hack - assume a tuple is a colour
5050 'boost::python::tuple' : lambda name : "MAKECOLOUR(" + name + ")" .format (name )
51- }
52-
51+ }
52+
5353castsRet = {
5454 'bool' : lambda val : 'return 0 != (' + val + ')' ,
5555 'boost::python::tuple' : lambda val : 'int retVal = callScintilla(' + val + ');\n \t return boost::python::make_tuple(COLOUR_RED(retVal), COLOUR_GREEN(retVal), COLOUR_BLUE(retVal))'
56-
57- }
58-
56+ }
57+
5958# Must be kept in sync with pythonTypeExplosions
6059typeExplosions = {
6160 #'colour' : lambda name: 'int {0}Red, int {0}Green, int {0}Blue'.format(name),
@@ -90,19 +89,14 @@ def castReturn(ty, val):
9089def cellsBody (v , out ):
9190 out .write ("\t return callScintilla(" + symbolName (v ) + ", " + v ["Param2Name" ] + ".length(), reinterpret_cast<LPARAM>(" + v ["Param2Name" ] + ".cells()));\n " )
9291
93-
9492def constString (v , out ):
9593 out .write ("\t const char *raw = boost::python::extract<const char *>(" + v ["Param2Name" ] + ".attr(\" __str__\" )());\n " )
9694 out .write ("\t return callScintilla(" + symbolName (v ) + ", len(" + v ["Param2Name" ] + "), reinterpret_cast<LPARAM>(raw));\n " );
9795
9896def retString (v , out ):
99- out .write ("\t int resultLength = callScintilla(" + symbolName (v ) + ");\n " )
100- out .write ("\t char *result = new char[resultLength + 1];\n " )
101- out .write ("\t callScintilla(" + symbolName (v ) + ", resultLength + 1, reinterpret_cast<LPARAM>(result));\n " )
102- out .write ("\t result[resultLength] = '\\ 0';\n " )
103- out .write ("\t boost::python::str o = boost::python::str(const_cast<const char *>(result));\n " )
104- out .write ("\t delete [] result;\n " )
105- out .write ("\t return o;\n " )
97+ out .write ("\t PythonCompatibleStrBuffer result(callScintilla(" + symbolName (v ) + ") + 1);\n " )
98+ out .write ("\t callScintilla(" + symbolName (v ) + ", result.size(), reinterpret_cast<LPARAM>(*result));\n " )
99+ out .write ("\t return boost::python::str(result.c_str());\n " )
106100
107101def getLineBody (v , out ):
108102 out .write ("\t int lineCount = callScintilla(SCI_GETLINECOUNT);\n " )
@@ -112,29 +106,23 @@ def getLineBody(v, out):
112106 out .write ("\t }\n " )
113107 out .write ("\t else\n " )
114108 out .write ("\t {\n " )
115- out .write ("\t \t int resultLength = callScintilla(" + symbolName (v ) + ", line);\n " )
116- out .write ("\t \t char *result = new char[resultLength + 1];\n " )
117- out .write ("\t \t callScintilla(" + symbolName (v ) + ", line, reinterpret_cast<LPARAM>(result));\n " )
118- out .write ("\t \t result[resultLength] = '\\ 0';\n " )
119- out .write ("\t \t boost::python::str o = boost::python::str((const char *)result);\n " )
120- out .write ("\t \t delete [] result;\n " )
121- out .write ("\t \t return o;\n " )
109+ out .write ("\t \t PythonCompatibleStrBuffer result(callScintilla(SCI_LINELENGTH, line) + 1);\n " )
110+ out .write ("\t \t callScintilla(" + symbolName (v ) + ", line, reinterpret_cast<LPARAM>(*result));\n " )
111+ out .write ("\t \t return boost::python::str(result.c_str());\n " )
122112 out .write ("\t }\n " )
123113
124-
125114def retStringNoLength (v , out ):
126- out .write ("\t int resultLength = callScintilla(" + symbolName (v ))
115+ out .write ("\t PythonCompatibleStrBuffer result( callScintilla(" + symbolName (v ))
127116 if v ["Param1Type" ] != '' or v ["Param2Type" ] != '' :
128117 out .write (", " )
129118 if v ["Param1Type" ] != '' :
130119 out .write (v ["Param1Name" ]);
131-
120+
132121 if v ["Param2Type" ] != '' :
133122 out .write (v ["Param2Name" ]);
123+
124+ out .write ("));\n " )
134125
135- out .write (");\n " )
136-
137- out .write ("\t char *result = new char[resultLength + 1];\n " )
138126 out .write ("\t callScintilla(" + symbolName (v ) + ", " )
139127
140128 if v ["Param1Type" ] or v ["Param2Type" ]:
@@ -144,13 +132,9 @@ def retStringNoLength(v, out):
144132 out .write (v ["Param2Name" ]);
145133 else :
146134 out .write ("0" );
147-
148-
149- out .write (", reinterpret_cast<LPARAM>(result));\n " )
150- out .write ("\t result[resultLength] = '\\ 0';\n " )
151- out .write ("\t boost::python::str o = boost::python::str(const_cast<const char *>(result));\n " )
152- out .write ("\t delete [] result;\n " )
153- out .write ("\t return o;\n " )
135+
136+ out .write (", reinterpret_cast<LPARAM>(*result));\n " )
137+ out .write ("\t return boost::python::str(result.c_str());\n " )
154138
155139def findTextBody (v , out ):
156140 out .write ('\t Sci_TextToFind src;\n ' )
@@ -162,7 +146,6 @@ def findTextBody(v, out):
162146 out .write ('\t {\n \t \t return boost::python::object();\n \t }\n ' )
163147 out .write ('\t else\n \t {\n \t \t return boost::python::make_tuple(src.chrgText.cpMin, src.chrgText.cpMax);\n \t }\n ' )
164148
165-
166149def getTextRangeBody (v , out ):
167150 out .write ('\t Sci_TextRange src;\n ' )
168151 out .write ('\t if (end < start)\n ' )
@@ -171,15 +154,13 @@ def getTextRangeBody(v, out):
171154 out .write ('\t \t start = end;\n ' )
172155 out .write ('\t \t end = temp;\n ' )
173156 out .write ('\t }\n ' )
157+ out .write ("\t PythonCompatibleStrBuffer result((end-start) + 1);\n " )
174158 out .write ('\t src.chrg.cpMin = start;\n ' )
175159 out .write ('\t src.chrg.cpMax = end;\n ' )
176- out .write ('\t src.lpstrText = new char[(end-start) + 1] ;\n ' )
160+ out .write ('\t src.lpstrText = *result ;\n ' )
177161 out .write ('\t callScintilla({0}, 0, reinterpret_cast<LPARAM>(&src));\n ' .format (symbolName (v )))
178- out .write ('\t boost::python::str ret(const_cast<const char*>(src.lpstrText));\n ' )
179- out .write ('\t delete [] src.lpstrText;\n ' )
180- out .write ('\t return ret;\n ' )
162+ out .write ('\t return boost::python::str(result.c_str());\n ' )
181163
182-
183164def getStyledTextBody (v , out ):
184165 out .write ('\t Sci_TextRange src;\n ' )
185166 out .write ('\t if (end < start)\n ' )
@@ -193,20 +174,16 @@ def getStyledTextBody(v, out):
193174 out .write ('\t src.lpstrText = new char[((end-start) * 2) + 2];\n ' )
194175 out .write ('\t callScintilla({0}, 0, reinterpret_cast<LPARAM>(&src));\n ' .format (symbolName (v )))
195176 out .write ('\t boost::python::list styles;\n ' )
196- out .write (' \t char * result = new char[( end-start) + 1] ;\n ' )
197- out .write ('\t for(int pos = 0; pos < (end - start) ; pos++)\n ' )
177+ out .write (" \t PythonCompatibleStrBuffer result(( end-start) + 1) ;\n " )
178+ out .write ('\t for(int pos = 0; pos < result.size() - 1 ; pos++)\n ' )
198179 out .write ('\t {\n ' )
199- out .write ('\t \t result [pos] = src.lpstrText[pos * 2];\n ' )
180+ out .write ('\t \t (*result) [pos] = src.lpstrText[pos * 2];\n ' )
200181 out .write ('\t \t styles.append((int)(src.lpstrText[(pos * 2) + 1]));\n ' )
201182 out .write ('\t }\n ' )
202- out .write ("\t result[end-start] = '\\ 0';\n " )
203- out .write ('\t boost::python::str resultStr(const_cast<const char*>(result));\n ' )
183+ out .write ('\t boost::python::str resultStr(result.c_str());\n ' )
204184 out .write ('\t delete [] src.lpstrText;\n ' )
205- out .write ('\t delete [] result;\n ' )
206185 out .write ('\t return boost::python::make_tuple(resultStr, styles);\n ' )
207186
208-
209-
210187def standardBody (v , out ):
211188 call = 'callScintilla(' + symbolName (v )
212189
@@ -220,16 +197,13 @@ def standardBody(v, out):
220197 call += ', ' + castLparam (v ["Param2Type" ], v ["Param2Name" ])
221198 call += ")"
222199
223-
224200 if (v ["ReturnType" ] != 'void' ):
225201 out .write ('\t ' )
226202 out .write (castReturn (v ["ReturnType" ], call ))
227203 else :
228204 out .write ('\t ' + call )
229205
230206 out .write (";\n " )
231-
232-
233207
234208def mapType (t ):
235209 return types .get (t , t )
@@ -254,7 +228,6 @@ def explodeType(ty, name):
254228def explodePythonType (ty , name ):
255229 return pythonTypeExplosions .get (ty , lambda name : name )(name )
256230
257-
258231def writeParams (param1Type , param1Name , param2Type , param2Name ):
259232 retVal = ""
260233 if param1Type :
@@ -266,7 +239,6 @@ def writeParams(param1Type, param1Name, param2Type, param2Name):
266239 retVal += explodeType (param2Type , param2Name )
267240
268241 return retVal
269-
270242
271243def writePythonParams (param1Type , param1Name , param2Type , param2Name ):
272244 retVal = ""
@@ -280,7 +252,6 @@ def writePythonParams(param1Type, param1Name, param2Type, param2Name):
280252
281253 return retVal
282254
283-
284255argumentMap = {
285256# (firstParamType, firstParamName, secondParamType, secondParamName) : ( returnType, FirstParamType, SecondParamType, bodyFunction)
286257 ('int' , 'length' , 'string' , '' ) : ('int' , '' , 'boost::python::object' , constString ),
@@ -290,7 +261,6 @@ def writePythonParams(param1Type, param1Name, param2Type, param2Name):
290261 ('int' , 'length' , 'cells' , '' ) : ('int' , '' , 'ScintillaCells' , cellsBody ),
291262 ('int' , '' , 'findtext' , 'ft' ) : ('boost::python::object' , 'int' , 'findtext' , findTextBody ),
292263 ('' , '' , 'textrange' , 'tr' ) : ('boost::python::str' , '' , 'textrange' , getTextRangeBody )
293-
294264}
295265
296266specialCases = {
@@ -307,7 +277,6 @@ def getSignature(v):
307277def formatPythonName (name ):
308278 return name [0 :1 ].lower () + name [1 :]
309279
310-
311280def getPythonSignature (v ):
312281 sig = "{0}(" .format (formatPythonName (v ["Name" ]))
313282
@@ -316,15 +285,33 @@ def getPythonSignature(v):
316285 if v ["ReturnType" ] and v ["ReturnType" ] != "void" :
317286 sig += " -> " + v ["ReturnType" ].replace ("boost::python::" , "" )
318287
319-
320288 return sig
321289
322-
323290def writeCppFile (f ,out ):
324291 out .write ('#include "stdafx.h"\n ' )
325292 out .write ('#include "ScintillaWrapper.h"\n ' )
326293 out .write ('#include "Scintilla.h"\n ' )
327- out .write ('\n \n ' )
294+ out .write ('\n ' )
295+ out .write ('// Helper class\n ' )
296+ out .write ('class PythonCompatibleStrBuffer\n ' )
297+ out .write ('{\n ' )
298+ out .write ('public:\n ' )
299+ out .write ('\t inline PythonCompatibleStrBuffer(int length) :\n ' )
300+ out .write ('\t \t m_bufferPtr(new char[length]),\n ' )
301+ out .write ('\t \t m_bufferLen(length)\n ' )
302+ out .write ('\t {\n ' )
303+ out .write ('\t \t m_bufferPtr[length-1] = \' \\ 0\' ;\n ' )
304+ out .write ('\t }\n ' )
305+ out .write ('\t inline ~PythonCompatibleStrBuffer() { delete [] m_bufferPtr; }\n ' )
306+ out .write ('\t inline char* operator*() const { return m_bufferPtr; }\n ' )
307+ out .write ('\t inline const char* c_str() const { return m_bufferPtr; }\n ' )
308+ out .write ('\t inline int size() const { return m_bufferLen; }\n ' )
309+ out .write ('private:\n ' )
310+ out .write ('\t PythonCompatibleStrBuffer(); // default constructor disabled\n ' )
311+ out .write ('\t char* m_bufferPtr;\n ' )
312+ out .write ('\t int m_bufferLen;\n ' )
313+ out .write ('};\n ' )
314+ out .write ('\n ' )
328315
329316 for name in f .order :
330317 v = f .features [name ]
@@ -357,9 +344,6 @@ def writeCppFile(f,out):
357344 body (v , out )
358345 out .write ("}\n \n " )
359346
360-
361-
362-
363347def writeHFile (f ,out ):
364348 for name in f .order :
365349 v = f .features [name ]
@@ -387,7 +371,6 @@ def writeHFile(f,out):
387371 out .write ("\t " );
388372 out .write (getSignature (v ).replace (' ScintillaWrapper::' , ' ' ))
389373 out .write (";\n \n " )
390-
391374
392375def writeBoostWrapFile (f ,out ):
393376 for name in f .order :
@@ -445,8 +428,6 @@ def writeEnumsHFile(f, out):
445428 join = ","
446429 out .write ("\n };\n " )
447430
448-
449-
450431def writeEnumsWrapperFile (f , out ):
451432 for name in f .enums :
452433 v = f .enums [name ]
@@ -473,7 +454,7 @@ def writeEnumsWrapperFile(f, out):
473454 out .write ('\n \t \t .value("SCI_{0}", PYSCR_SCI_{1})' .format (name .upper (), name .upper ()))
474455
475456 out .write (';\n \n ' )
476-
457+
477458def writeScintillaDoc (f , out ):
478459 oldCat = ""
479460
@@ -508,7 +489,6 @@ def writeScintillaDoc(f, out):
508489 out .write ("\n \n " )
509490 out .write ("\n " .join (v ["Comment" ]))
510491 out .write ("\n \n See Scintilla documentation for `{0} <http://www.scintilla.org/ScintillaDoc.html#{0}>`_\n \n " .format (symbolName (v )))
511-
512492
513493def writeScintillaEnums (f , out ):
514494 out .write ("\n \n " )
@@ -521,16 +501,12 @@ def writeScintillaEnums(f, out):
521501 for val in v ['Values' ]:
522502 out .write ('.. attribute:: {0}.{1}\n \n ' .format (name .upper (), val [0 ][len (v ['Value' ]):].upper ()))
523503
524-
525-
526-
527504def findEnum (f , name ):
528505 for e in f .enums :
529506 l = len (f .enums [e ]["Value" ])
530507 if f .enums [e ]["Value" ] == name [:l ]:
531508 return e
532509 return None
533-
534510
535511def findEnumValues (f ):
536512 f .enums = {}
@@ -545,13 +521,10 @@ def findEnumValues(f):
545521 if v ["FeatureType" ] == 'val' :
546522 enum = findEnum (f , name )
547523
548-
549524 if enum is not None :
550525 if f .enums [enum ].get ("Values" , None ) == None :
551526 f .enums [enum ]["Values" ] = []
552527 f .enums [enum ]["Values" ] += [(name , v ["Value" ])]
553-
554-
555528
556529def CopyWithInsertion (input , output , genfn , definition ):
557530 copying = 1
0 commit comments