diff options
Diffstat (limited to 'python/tag.cc')
| -rw-r--r-- | python/tag.cc | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/python/tag.cc b/python/tag.cc new file mode 100644 index 00000000..da151832 --- /dev/null +++ b/python/tag.cc @@ -0,0 +1,445 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: tag.cc,v 1.1 2001/02/20 06:32:01 jgg Exp $ +/* ###################################################################### + + Tag - Binding for the RFC 822 tag file parser + + Upon reflection I have make the TagSection wrapper look like a map.. + The other option was to use a sequence (which nicely matches the internal + storage) but really makes no sense to a Python Programmer.. One + specialized lookup is provided, the FindFlag lookup - as well as the + usual set of duplicate things to match the C++ interface. + + The TagFile interface is also slightly different, it has a built in + internal TagSection object that is used. Do not hold onto a reference + to a TagSection and let TagFile go out of scope! The underlying storage + for the section will go away and it will seg. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#define _GNU_SOURCE +#include "generic.h" +#include "apt_pkgmodule.h" + +#include <apt-pkg/tagfile.h> + +#include <stdio.h> +#include <python/Python.h> + /*}}}*/ +static PyMethodDef TagSecMethods[]; +static PyMethodDef TagFileMethods[]; + +/* We need to keep a private copy of the data.. */ +struct TagSecData : public CppPyObject<pkgTagSection> +{ + char *Data; +}; + +struct TagFileData : public PyObject +{ + pkgTagFile Object; + PyObject *File; + TagSecData *Section; + FileFd Fd; +}; + +// TagSecGetAttr - Get an attribute - variable/method /*{{{*/ +// --------------------------------------------------------------------- +/* */ +static PyObject *TagSecGetAttr(PyObject *Self,char *Name) +{ + return Py_FindMethod(TagSecMethods,Self,Name); +} + /*}}}*/ +// TagFileGetAttr - Get an attribute - variable/method /*{{{*/ +// --------------------------------------------------------------------- +/* */ +static PyObject *TagFileGetAttr(PyObject *Self,char *Name) +{ + if (strcmp("Section",Name) == 0) + { + PyObject *Obj = ((TagFileData *)Self)->Section; + Py_INCREF(Obj); + return Obj; + } + + return Py_FindMethod(TagFileMethods,Self,Name); +} + /*}}}*/ +// TagSecFree - Free a Tag Section /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void TagSecFree(PyObject *Obj) +{ + TagSecData *Self = (TagSecData *)Obj; + delete [] Self->Data; + CppDealloc<pkgTagSection>(Obj); +} + /*}}}*/ +// TagFileFree - Free a Tag File /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void TagFileFree(PyObject *Obj) +{ + TagFileData *Self = (TagFileData *)Obj; + Py_DECREF((PyObject *)Self->Section); + Self->Object.~pkgTagFile(); + Self->Fd.~FileFd(); + Py_DECREF(Self->File); + PyMem_DEL(Obj); +} + /*}}}*/ + +// Tag Section Wrappers /*{{{*/ +static char *doc_Find = "Find(Name) -> String/None"; +static PyObject *TagSecFind(PyObject *Self,PyObject *Args) +{ + char *Name = 0; + char *Default = 0; + if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0) + return 0; + + const char *Start; + const char *Stop; + if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false) + { + if (Default == 0) + { + Py_INCREF(Py_None); + return Py_None; + } + return PyString_FromString(Default); + } + return PyString_FromStringAndSize(Start,Stop-Start); +} + +static char *doc_FindFlag = "FindFlag(Name) -> integer/none"; +static PyObject *TagSecFindFlag(PyObject *Self,PyObject *Args) +{ + char *Name = 0; + if (PyArg_ParseTuple(Args,"s",&Name) == 0) + return 0; + + unsigned long Flag = 0; + if (GetCpp<pkgTagSection>(Self).FindFlag(Name,Flag,1) == false) + { + Py_INCREF(Py_None); + return Py_None; + } + return Py_BuildValue("i",Flag); +} + +// Map access, operator [] +static PyObject *TagSecMap(PyObject *Self,PyObject *Arg) +{ + if (PyString_Check(Arg) == 0) + { + PyErr_SetNone(PyExc_TypeError); + return 0; + } + + const char *Start; + const char *Stop; + if (GetCpp<pkgTagSection>(Self).Find(PyString_AsString(Arg),Start,Stop) == false) + { + PyErr_SetString(PyExc_KeyError,PyString_AsString(Arg)); + return 0; + } + + return PyString_FromStringAndSize(Start,Stop-Start); +} + +// len() operation +static int TagSecLength(PyObject *Self) +{ + pkgTagSection &Sec = GetCpp<pkgTagSection>(Self); + return Sec.Count(); +} + +// Look like a mapping +static char *doc_Keys = "keys() -> List"; +static PyObject *TagSecKeys(PyObject *Self,PyObject *Args) +{ + pkgTagSection &Tags = GetCpp<pkgTagSection>(Self); + if (PyArg_ParseTuple(Args,"") == 0) + return 0; + + // Convert the whole configuration space into a list + PyObject *List = PyList_New(0); + for (unsigned int I = 0; I != Tags.Count(); I++) + { + const char *Start; + const char *Stop; + Tags.Get(Start,Stop,I); + const char *End = Start; + for (; End < Stop && *End != ':'; End++); + + PyObject *Obj; + PyList_Append(List,Obj = PyString_FromStringAndSize(Start,End-Start)); + Py_DECREF(Obj); + } + return List; +} + +static char *doc_Exists = "Exists(Name) -> integer"; +static PyObject *TagSecExists(PyObject *Self,PyObject *Args) +{ + char *Name = 0; + if (PyArg_ParseTuple(Args,"s",&Name) == 0) + return 0; + + const char *Start; + const char *Stop; + if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false) + return Py_BuildValue("i",0); + return Py_BuildValue("i",1); +} + +static char *doc_Bytes = "Bytes() -> integer"; +static PyObject *TagSecBytes(PyObject *Self,PyObject *Args) +{ + if (PyArg_ParseTuple(Args,"") == 0) + return 0; + + return Py_BuildValue("i",GetCpp<pkgTagSection>(Self).size()); +} + +static PyObject *TagSecStr(PyObject *Self) +{ + const char *Start; + const char *Stop; + GetCpp<pkgTagSection>(Self).GetSection(Start,Stop); + return PyString_FromStringAndSize(Start,Stop-Start); +} + /*}}}*/ +// TagFile Wrappers /*{{{*/ +static char *doc_Step = "Step() -> Integer\n0 means EOF."; +static PyObject *TagFileStep(PyObject *Self,PyObject *Args) +{ + if (PyArg_ParseTuple(Args,"") == 0) + return 0; + + TagFileData &Obj = *(TagFileData *)Self; + if (Obj.Object.Step(Obj.Section->Object) == false) + return HandleErrors(Py_BuildValue("i",0)); + + return HandleErrors(Py_BuildValue("i",1)); +} + +static char *doc_Offset = "Offset() -> Integer"; +static PyObject *TagFileOffset(PyObject *Self,PyObject *Args) +{ + if (PyArg_ParseTuple(Args,"") == 0) + return 0; + return Py_BuildValue("i",((TagFileData *)Self)->Object.Offset()); +} + +static char *doc_Jump = "Jump(Offset) -> Integer"; +static PyObject *TagFileJump(PyObject *Self,PyObject *Args) +{ + int Offset; + if (PyArg_ParseTuple(Args,"i",&Offset) == 0) + return 0; + + TagFileData &Obj = *(TagFileData *)Self; + if (Obj.Object.Jump(Obj.Section->Object,Offset) == false) + return HandleErrors(Py_BuildValue("i",0)); + + return HandleErrors(Py_BuildValue("i",1)); +} + /*}}}*/ +// ParseSection - Parse a single section from a tag file /*{{{*/ +// --------------------------------------------------------------------- +char *doc_ParseSection ="ParseSection(Text) -> SectionObject"; +PyObject *ParseSection(PyObject *self,PyObject *Args) +{ + char *Data; + if (PyArg_ParseTuple(Args,"s",&Data) == 0) + return 0; + + // Create the object.. + TagSecData *New = PyObject_NEW(TagSecData,&TagSecType); + new (&New->Object) pkgTagSection(); + New->Data = new char[strlen(Data)+2]; + snprintf(New->Data,strlen(Data)+2,"%s\n",Data); + + if (New->Object.Scan(New->Data,strlen(New->Data)) == false) + { + cerr << New->Data << endl; + Py_DECREF((PyObject *)New); + PyErr_SetString(PyExc_ValueError,"Unable to parse section data"); + return 0; + } + + New->Object.Trim(); + + return New; +} + /*}}}*/ +// ParseTagFile - Parse a tagd file /*{{{*/ +// --------------------------------------------------------------------- +/* This constructs the parser state. */ +char *doc_ParseTagFile = "ParseTagFile(File) -> TagFile"; +PyObject *ParseTagFile(PyObject *self,PyObject *Args) +{ + PyObject *File; + if (PyArg_ParseTuple(Args,"O!",&PyFile_Type,&File) == 0) + return 0; + + TagFileData *New = PyObject_NEW(TagFileData,&TagFileType); + new (&New->Fd) FileFd(fileno(PyFile_AsFile(File)),false); + New->File = File; + Py_INCREF(New->File); + new (&New->Object) pkgTagFile(&New->Fd); + + // Create the section + New->Section = PyObject_NEW(TagSecData,&TagSecType); + new (&New->Section->Object) pkgTagSection(); + New->Section->Data = 0; + + return HandleErrors(New); +} + /*}}}*/ +// RewriteSection - Rewrite a section.. /*{{{*/ +// --------------------------------------------------------------------- +/* An interesting future extension would be to add a user settable + order list */ +char *doc_RewriteSection = +"RewriteSection(Section,Order,RewriteList) -> String\n" +"\n" +"The section rewriter allows a section to be taken in, have fields added,\n" +"removed or changed and then put back out. During this process the fields\n" +"within the section are sorted to corrispond to a proper order. Order is a\n" +"list of field names with their proper capitialization.\n" +"apt_pkg.RewritePackageOrder and apt_pkg.RewriteSourceOrder are two predefined\n" +"orders.\n" +"RewriteList is a list of tuples. Each tuple is of the form:\n" +" (Tag,NewValue[,RenamedTo])\n" +"Tag specifies the tag in the source section. NewValue is the new value of\n" +"that tag and the optional RenamedTo field can cause the tag to be changed.\n" +"If NewValue is None then the tag is removed\n" +"Ex. ('Source','apt','Package') is used for .dsc files."; +PyObject *RewriteSection(PyObject *self,PyObject *Args) +{ + PyObject *Section; + PyObject *Order; + PyObject *Rewrite; + if (PyArg_ParseTuple(Args,"O!O!O!",&TagSecType,&Section, + &PyList_Type,&Order,&PyList_Type,&Rewrite) == 0) + return 0; + + // Convert the order list + const char **OrderList = ListToCharChar(Order,true); + + // Convert the Rewrite list. + TFRewriteData *List = new TFRewriteData[PySequence_Length(Rewrite)+1]; + memset(List,0,sizeof(*List)*(PySequence_Length(Rewrite)+1)); + for (int I = 0; I != PySequence_Length(Rewrite); I++) + { + List[I].NewTag = 0; + if (PyArg_ParseTuple(PySequence_GetItem(Rewrite,I),"sz|s", + &List[I].Tag,&List[I].Rewrite,&List[I].NewTag) == 0) + { + delete [] OrderList; + delete [] List; + return 0; + } + } + + /* This is a glibc extension.. If not running on glibc I'd just take + this whole function out, it is probably infrequently used */ + char *bp = 0; + size_t size; + FILE *F = open_memstream (&bp, &size); + + // Do the rewrite + bool Res = TFRewrite(F,GetCpp<pkgTagSection>(Section),OrderList,List); + delete [] OrderList; + delete [] List; + fclose(F); + + if (Res == false) + { + free(bp); + return HandleErrors(); + } + + // Return the string + PyObject *ResObj = PyString_FromStringAndSize(bp,size); + free(bp); + return HandleErrors(ResObj); +} + /*}}}*/ + +// Method table for the Tag Section object +static PyMethodDef TagSecMethods[] = +{ + // Query + {"Find",TagSecFind,METH_VARARGS,doc_Find}, + {"FindFlag",TagSecFindFlag,METH_VARARGS,doc_FindFlag}, + {"Bytes",TagSecBytes,METH_VARARGS,doc_Bytes}, + + // Python Special + {"keys",TagSecKeys,METH_VARARGS,doc_Keys}, + {"has_key",TagSecExists,METH_VARARGS,doc_Exists}, + {"get",TagSecFind,METH_VARARGS,doc_Find}, + {} +}; + +// Type for a Tag Section +PyMappingMethods TagSecMapMeth = {TagSecLength,TagSecMap,0}; +PyTypeObject TagSecType = +{ + PyObject_HEAD_INIT(&PyType_Type) + 0, // ob_size + "TagSection", // tp_name + sizeof(TagSecData), // tp_basicsize + 0, // tp_itemsize + // Methods + TagSecFree, // tp_dealloc + 0, // tp_print + TagSecGetAttr, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + &TagSecMapMeth, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + TagSecStr, // tp_str +}; + +// Method table for the Tag File object +static PyMethodDef TagFileMethods[] = +{ + // Query + {"Step",TagFileStep,METH_VARARGS,doc_Step}, + {"Offset",TagFileOffset,METH_VARARGS,doc_Offset}, + {"Jump",TagFileJump,METH_VARARGS,doc_Jump}, + + {} +}; + +// Type for a Tag File +PyTypeObject TagFileType = +{ + PyObject_HEAD_INIT(&PyType_Type) + 0, // ob_size + "TagFile", // tp_name + sizeof(TagFileData), // tp_basicsize + 0, // tp_itemsize + // Methods + TagFileFree, // tp_dealloc + 0, // tp_print + TagFileGetAttr, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash +}; |
