2011-09-08 15:05:02 +00:00
/* Copyright 2010-2011 Florent Le Coz <louiz@louiz.org> */
/* This file is part of Poezio. */
/* Poezio is free software: you can redistribute it and/or modify */
2011-09-11 15:10:05 +00:00
/* it under the terms of the zlib license. See the COPYING file. */
2011-09-08 15:05:02 +00:00
/** The poopt python3 module
* */
/* This file is a python3 module for poezio, used to replace some time-critical
2011-09-14 11:59:25 +00:00
python functions that are too slow . */
2011-09-08 15:05:02 +00:00
# define PY_SSIZE_T_CLEAN
# include "Python.h"
PyObject * ErrorObject ;
/***
The module functions
* * */
/* cut_text: takes a string and returns a tuple of int.
Each two int tuple is a line , represented by the ending position it ( where it should be cut ) .
Not that this position is calculed using the position of the python string characters ,
not just the individual bytes .
For example , poopt_cut_text ( " vivent les frigidaires " , 6 ) ;
will return [ ( 0 , 6 ) , ( 7 , 10 ) , ( 11 , 17 ) , ( 17 , 22 ) ] , meaning that the lines are
" vivent " , " les " , " frigid " and " aires "
*/
2011-09-14 11:59:25 +00:00
PyDoc_STRVAR ( poopt_cut_text_doc , " cut_text(text, width) \n \n \n Return a list of two-tuple, the first int is the starting position of the line and the second is its end. " ) ;
2011-09-08 15:05:02 +00:00
static PyObject * poopt_cut_text ( PyObject * self , PyObject * args )
{
unsigned char * buffer ;
int width ;
2011-09-09 16:43:20 +00:00
if ( PyArg_ParseTuple ( args , " si " , & buffer , & width ) = = 0 )
2011-09-08 15:05:02 +00:00
return NULL ;
int bpos = 0 ; /* the real position in the char* */
int spos = 0 ; /* the position, considering UTF-8 chars */
int last_space = - 1 ;
int start_pos = 0 ;
2011-11-08 00:52:39 +00:00
int w = width ; /* this is a width that increases to make the length of char
of colors attribute be ignored */
2011-09-08 15:05:02 +00:00
PyObject * retlist = PyList_New ( 0 ) ;
2011-09-09 16:43:20 +00:00
while ( buffer [ bpos ] )
2011-09-08 15:05:02 +00:00
{
if ( buffer [ bpos ] = = ' ' )
last_space = spos ;
else if ( buffer [ bpos ] = = ' \n ' )
{
if ( PyList_Append ( retlist , Py_BuildValue ( " ii " , start_pos , spos ) ) = = - 1 )
return NULL ;
start_pos = spos + 1 ;
last_space = - 1 ;
}
2011-11-08 00:52:39 +00:00
else if ( ( spos - start_pos ) > = w )
2011-09-08 15:05:02 +00:00
{
if ( last_space = = - 1 )
{
if ( PyList_Append ( retlist , Py_BuildValue ( " ii " , start_pos , spos ) ) = = - 1 )
return NULL ;
start_pos = spos ;
}
else
{
if ( PyList_Append ( retlist , Py_BuildValue ( " ii " , start_pos , last_space ) ) = = - 1 )
return NULL ;
start_pos = last_space + 1 ;
last_space = - 1 ;
}
2011-11-08 00:52:39 +00:00
w = width ;
2011-09-08 15:05:02 +00:00
}
if ( buffer [ bpos ] = = 25 ) /* \x19 */
{
2011-11-08 00:52:39 +00:00
while ( buffer [ bpos ] & &
buffer [ bpos ] ! = ' u ' & &
buffer [ bpos ] ! = ' b ' & &
buffer [ bpos ] ! = ' o ' & &
buffer [ bpos ] ! = ' } ' )
{
bpos + + ;
spos + + ;
w + + ;
}
bpos + + ;
spos + + ;
w + + ;
spos - - ;
2011-09-08 15:05:02 +00:00
}
else
2011-09-09 16:43:20 +00:00
if ( buffer [ bpos ] < = 127 ) /* ASCII char on one byte */
bpos + = 1 ;
else if ( buffer [ bpos ] > = 194 & & buffer [ bpos ] < = 223 )
bpos + = 2 ;
else if ( buffer [ bpos ] > = 224 & & buffer [ bpos ] < = 239 )
bpos + = 3 ;
else if ( buffer [ bpos ] > = 240 & & buffer [ bpos ] < = 244 )
bpos + = 4 ;
else
return NULL ;
2011-09-08 15:05:02 +00:00
spos + + ;
}
if ( PyList_Append ( retlist , Py_BuildValue ( " (i,i) " , start_pos , spos ) ) = = - 1 )
return NULL ;
return retlist ;
}
/***
Module initialization . Just taken from the xxmodule . c template from the python sources .
* * */
static PyTypeObject Str_Type = {
PyVarObject_HEAD_INIT ( NULL , 0 )
" pooptmodule.Str " , /*tp_name*/
0 , /*tp_basicsize*/
0 , /*tp_itemsize*/
/* methods */
0 , /*tp_dealloc*/
0 , /*tp_print*/
0 , /*tp_getattr*/
0 , /*tp_setattr*/
0 , /*tp_reserved*/
0 , /*tp_repr*/
0 , /*tp_as_number*/
0 , /*tp_as_sequence*/
0 , /*tp_as_mapping*/
0 , /*tp_hash*/
0 , /*tp_call*/
0 , /*tp_str*/
0 , /*tp_getattro*/
0 , /*tp_setattro*/
0 , /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /*tp_flags*/
0 , /*tp_doc*/
0 , /*tp_traverse*/
0 , /*tp_clear*/
0 , /*tp_richcompare*/
0 , /*tp_weaklistoffset*/
0 , /*tp_iter*/
0 , /*tp_iternext*/
0 , /*tp_methods*/
0 , /*tp_members*/
0 , /*tp_getset*/
0 , /* see PyInit_xx */ /*tp_base*/
0 , /*tp_dict*/
0 , /*tp_descr_get*/
0 , /*tp_descr_set*/
0 , /*tp_dictoffset*/
0 , /*tp_init*/
0 , /*tp_alloc*/
0 , /*tp_new*/
0 , /*tp_free*/
0 , /*tp_is_gc*/
} ;
static PyObject *
null_richcompare ( PyObject * self , PyObject * other , int op )
{
Py_INCREF ( Py_NotImplemented ) ;
return Py_NotImplemented ;
}
static PyTypeObject Null_Type = {
PyVarObject_HEAD_INIT ( NULL , 0 )
" pooptmodule.Null " , /*tp_name*/
0 , /*tp_basicsize*/
0 , /*tp_itemsize*/
/* methods */
0 , /*tp_dealloc*/
0 , /*tp_print*/
0 , /*tp_getattr*/
0 , /*tp_setattr*/
0 , /*tp_reserved*/
0 , /*tp_repr*/
0 , /*tp_as_number*/
0 , /*tp_as_sequence*/
0 , /*tp_as_mapping*/
0 , /*tp_hash*/
0 , /*tp_call*/
0 , /*tp_str*/
0 , /*tp_getattro*/
0 , /*tp_setattro*/
0 , /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /*tp_flags*/
0 , /*tp_doc*/
0 , /*tp_traverse*/
0 , /*tp_clear*/
null_richcompare , /*tp_richcompare*/
0 , /*tp_weaklistoffset*/
0 , /*tp_iter*/
0 , /*tp_iternext*/
0 , /*tp_methods*/
0 , /*tp_members*/
0 , /*tp_getset*/
0 , /* see PyInit_xx */ /*tp_base*/
0 , /*tp_dict*/
0 , /*tp_descr_get*/
0 , /*tp_descr_set*/
0 , /*tp_dictoffset*/
0 , /*tp_init*/
0 , /*tp_alloc*/
0 , /* see PyInit_xx */ /*tp_new*/
0 , /*tp_free*/
0 , /*tp_is_gc*/
} ;
/* List of functions defined in the module */
static PyMethodDef poopt_methods [ ] = {
{ " cut_text " , poopt_cut_text , METH_VARARGS ,
poopt_cut_text_doc } ,
{ NULL , NULL } /* sentinel */
} ;
PyDoc_STRVAR ( module_doc ,
" This is a template module just for instruction. And poopt. " ) ;
/* Initialization function for the module (*must* be called PyInit_xx) */
static struct PyModuleDef pooptmodule = {
PyModuleDef_HEAD_INIT ,
" poopt " ,
module_doc ,
- 1 ,
poopt_methods ,
NULL ,
NULL ,
NULL ,
NULL
} ;
PyMODINIT_FUNC
PyInit_poopt ( void )
{
PyObject * m = NULL ;
/* Due to cross platform compiler issues the slots must be filled
* here . It ' s required for portability to Windows without requiring
* C + + . */
Null_Type . tp_base = & PyBaseObject_Type ;
Null_Type . tp_new = PyType_GenericNew ;
Str_Type . tp_base = & PyUnicode_Type ;
/* Finalize the type object including setting type of the new type
* object ; doing it here is required for portability , too . */
/* if (PyType_Ready(&Xxo_Type) < 0) */
/* goto fail; */
/* Create the module and add the functions */
m = PyModule_Create ( & pooptmodule ) ;
if ( m = = NULL )
goto fail ;
/* Add some symbolic constants to the module */
if ( ErrorObject = = NULL ) {
ErrorObject = PyErr_NewException ( " poopt.error " , NULL , NULL ) ;
if ( ErrorObject = = NULL )
goto fail ;
}
Py_INCREF ( ErrorObject ) ;
PyModule_AddObject ( m , " error " , ErrorObject ) ;
/* Add Str */
if ( PyType_Ready ( & Str_Type ) < 0 )
goto fail ;
PyModule_AddObject ( m , " Str " , ( PyObject * ) & Str_Type ) ;
/* Add Null */
if ( PyType_Ready ( & Null_Type ) < 0 )
goto fail ;
PyModule_AddObject ( m , " Null " , ( PyObject * ) & Null_Type ) ;
return m ;
fail :
Py_XDECREF ( m ) ;
return NULL ;
}