Ejemplo n.º 1
0
static PyObject *
sv_LoadMap(svobject *self, PyObject *args)
{
	PyObject *rgb;
	PyObject *res = NULL;
	rgb_tuple *mapp = NULL;
	int maptype;
	int i, j;			     /* indices */

	if (!PyArg_Parse(args, "(iO)", &maptype, &rgb))
		return NULL;

	if (!PyList_Check(rgb) || PyList_Size(rgb) != 256) {
		PyErr_BadArgument();
		return NULL;
	}

	if (!(mapp = PyMem_NEW(rgb_tuple, 256)))
		return PyErr_NoMemory();

	for (i = 0; i < 256; i++) {
		PyObject* v = PyList_GetItem(rgb, i);
		if (!v)
			goto finally;

		if (!PyTuple_Check(v) || PyTuple_Size(v) != 3) {
			PyErr_BadArgument();
			goto finally;
		}
		for (j = 0; j < 3; j++) {
			PyObject* cell = PyTuple_GetItem(v, j);
			if (!cell)
				goto finally;

			if (!PyInt_Check(cell)) {
				PyErr_BadArgument();
				goto finally;
			}
			switch (j) {
			case 0: mapp[i].red = PyInt_AsLong(cell); break;
			case 1: mapp[i].blue = PyInt_AsLong(cell); break;
			case 2: mapp[i].green = PyInt_AsLong(cell); break;
			}
			if (PyErr_Occurred())
				goto finally;
		}
	}

	if (svLoadMap(self->ob_svideo, maptype, mapp)) {
		res = sv_error();
		goto finally;
	}

	Py_INCREF(Py_None);
	res = Py_None;

  finally:
	PyMem_DEL(mapp);
	return res;
}
Ejemplo n.º 2
0
// DEPRECATED
static PyObject* wpSocket_sendpacket( wpSocket* self, PyObject* args )
{
	if ( PyTuple_Size( args ) != 1 )
	{
		PyErr_BadArgument();
		return 0;
	}

	PyObject* list = PyTuple_GetItem( args, 0 );

	if ( !PyList_Check( list ) )
	{
		PyErr_BadArgument();
		return 0;
	}

	// Build a packet
	int packetLength = PyList_Size( list );

	QByteArray buffer( packetLength );

	for ( int i = 0; i < packetLength; ++i )
		buffer[i] = PyInt_AsLong( PyList_GetItem( list, i ) );

	cUOPacket packet( buffer );
	self->pSock->send( &packet );

	Py_RETURN_NONE;
}
Ejemplo n.º 3
0
// DEPRECATED
static PyObject* wpSocket_sendpacket( wpSocket* self, PyObject* args )
{
	if ( PyTuple_Size( args ) != 1 )
	{
		PyErr_BadArgument();
		return 0;
	}

	PyObject* list = PyTuple_GetItem( args, 0 );

	if ( !PyList_Check( list ) )
	{
		PyErr_BadArgument();
		return 0;
	}

	PyErr_Format( PyExc_DeprecationWarning, "socket.sendpacket is deprecated, please use something instead" );

	// Build a packet
	int packetLength = PyList_Size( list );

	QByteArray buffer( packetLength, 0 );

	for ( int i = 0; i < packetLength; ++i )
		buffer[i] = PyInt_AsLong( PyList_GetItem( list, i ) );

	cUOPacket packet( buffer );
	self->pSock->send( &packet );

	Py_RETURN_NONE;
}
Ejemplo n.º 4
0
static PyObject *
PyGreenlet_Switch(PyGreenlet *g, PyObject *args, PyObject *kwargs)
{
	PyGreenlet *self = (PyGreenlet *) g;

	if (!PyGreenlet_Check(self)) {
		PyErr_BadArgument();
		return NULL;
	}

	if (args == NULL) {
		args = Py_BuildValue("()");
	}
	else {
		Py_INCREF(args);
	}

	if (kwargs != NULL && PyDict_Check(kwargs)) {
		Py_INCREF(kwargs);
	}
	else {
		kwargs = NULL;
	}

	return single_result(g_switch(self, args, kwargs));
}
Ejemplo n.º 5
0
static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op)
{
	PyObject *res;
	int ok = -1; /* zero is true */

	if (QuaternionObject_Check(a) && QuaternionObject_Check(b)) {
		QuaternionObject *quatA = (QuaternionObject *)a;
		QuaternionObject *quatB = (QuaternionObject *)b;

		if (BaseMath_ReadCallback(quatA) == -1 || BaseMath_ReadCallback(quatB) == -1)
			return NULL;

		ok = (EXPP_VectorsAreEqual(quatA->quat, quatB->quat, QUAT_SIZE, 1)) ? 0 : -1;
	}

	switch (op) {
		case Py_NE:
			ok = !ok; /* pass through */
		case Py_EQ:
			res = ok ? Py_False : Py_True;
			break;

		case Py_LT:
		case Py_LE:
		case Py_GT:
		case Py_GE:
			res = Py_NotImplemented;
			break;
		default:
			PyErr_BadArgument();
			return NULL;
	}

	return Py_INCREF(res), res;
}
Ejemplo n.º 6
0
Archivo: pyext.c Proyecto: pzread/sdup
static PyObject* pyext_epoll_modify(PyObject *self,PyObject *args){
    int epfd;
    int fd;
    uint32_t events;

    struct pyep_data *pyep;
    struct ev_header *evhdr;

    if(!PyArg_ParseTuple(args,"iiI",&epfd,&fd,&events)){
        PyErr_BadArgument();
        return NULL;
    }
    if((pyep = pyep_getby_epfd(epfd)) == NULL){
        PyErr_SetString(PyExc_KeyError,"epoll file descriptor not found");
        return NULL;
    }
    if((evhdr = evhdr_getby_fd(pyep->evhdr_ht,fd)) == NULL){
        PyErr_SetString(PyExc_KeyError,"file descriptor not found");
        return NULL;
    }

    if(ev_mod(&pyep->evdata,evhdr,events)){
        PyErr_SetString(PyExc_SystemError,"modify event failed");
        return NULL;
    }

    Py_INCREF(Py_None);
    return Py_None;
}
Ejemplo n.º 7
0
Archivo: pyext.c Proyecto: pzread/sdup
static PyObject* pyext_epoll_unregister(PyObject *self,PyObject *args){
    khiter_t hit;

    int epfd;
    int fd;

    struct pyep_data *pyep;
    struct ev_header *evhdr;

    if(!PyArg_ParseTuple(args,"ii",&epfd,&fd)){
        PyErr_BadArgument();
        return NULL;
    }
    if((pyep = pyep_getby_epfd(epfd)) == NULL){
        PyErr_SetString(PyExc_KeyError,"epoll file descriptor not found");
        return NULL;
    }
    if((evhdr = evhdr_getby_fd(pyep->evhdr_ht,fd)) == NULL){
        PyErr_SetString(PyExc_KeyError,"file descriptor not found");
        return NULL;
    }

    if(ev_del(&pyep->evdata,evhdr)){
        PyErr_SetString(PyExc_SystemError,"unregister event failed");
        return NULL;
    }
    
    hit = kh_get(ptr,pyep->evhdr_ht,fd);
    kh_del(ptr,pyep->evhdr_ht,hit);

    free(evhdr);

    Py_INCREF(Py_None);
    return Py_None;
}
Ejemplo n.º 8
0
/*!
	Returns the custom tag passed
*/
static PyObject* wpMulti_gettag( wpMulti* self, PyObject* args )
{
	if( !self->pMulti || self->pMulti->free )
	{
		Py_INCREF( Py_None );
		return Py_None;
	}

	if( PyTuple_Size( args ) < 1 || !checkArgStr( 0 ) )
	{
		PyErr_BadArgument();
		return NULL;
	}

	QString key = PyString_AsString( PyTuple_GetItem( args, 0 ) );
	cVariant value = self->pMulti->getTag( key );

	if( value.type() == cVariant::String )
	{
		QString strValue = value.asString();

		if( !strValue.isNull() )
			return PyString_FromString( strValue.latin1() );
		else
			return PyString_FromString( "" );
	}
	else if( value.type() == cVariant::Int )
		return PyInt_FromLong( value.asInt() );

	Py_INCREF( Py_None );
	return Py_None;
}
Ejemplo n.º 9
0
/*!
	Sends custom house to client
*/
static PyObject* wpMulti_sendcustomhouse( wpMulti* self, PyObject* args )
{
	Q_UNUSED(args);	
	if( !self->pMulti || self->pMulti->free || !self->pMulti->ishouse() )
		return PyFalse;
	
	if( !checkArgChar( 0 ) )
	{
		PyErr_BadArgument();
		return NULL;
	}
	P_PLAYER player = dynamic_cast<P_PLAYER>( getArgChar( 0 ) );
	if ( !player )
		return PyFalse;

//	self->pMulti->sendCH( player->socket() );
	cUOTxAskCustomHouse askch;

	askch.setSerial( self->pMulti->serial() );
	askch.setId( self->pMulti->revision() );

	player->socket()->send( &askch );

	return PyTrue;
}
Ejemplo n.º 10
0
PyObject* Sbk_Double2DTupleFunc___getitem__(PyObject* self, Py_ssize_t _i)
{
    if (!Shiboken::Object::isValid(self))
        return 0;
    ::Double2DTuple* cppSelf = 0;
    SBK_UNUSED(cppSelf)
    if (!Shiboken::Object::isValid(self))
        return 0;
    cppSelf = ((::Double2DTuple*)Shiboken::Conversions::cppPointer(SbkNatronEngineTypes[SBK_DOUBLE2DTUPLE_IDX], (SbkObject*)self));
    // Begin code injection

    if (_i < 0 || _i >= 2) {
    PyErr_BadArgument();
    return 0;
    } else {
    double ret;
    switch (_i) {
    case 0:
    ret = cppSelf->x;
    break;
    case 1:
    ret = cppSelf->y;
    break;
    }
    return  Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter<double>(), &ret);
    }

    // End of code injection
}
Ejemplo n.º 11
0
PyObject *PyString_AsEncodedObject(PyObject *str,
                                   const char *encoding,
                                   const char *errors)
{
    PyObject *v;

    if (!PyString_Check(str)) {
        PyErr_BadArgument();
        goto onError;
    }

    if (encoding == NULL) {
#ifdef Py_USING_UNICODE
        encoding = PyUnicode_GetDefaultEncoding();
#else
        PyErr_SetString(PyExc_ValueError, "no encoding specified");
        goto onError;
#endif
    }

    /* Encode via the codec registry */
    v = PyCodec_Encode(str, encoding, errors);
    if (v == NULL)
        goto onError;

    return v;

 onError:
    return NULL;
}
Ejemplo n.º 12
0
static PyObject *KX_PythonSeq_richcmp(PyObject *a, PyObject *b, int op)
{
	PyObject *res;
	int ok= -1; /* zero is true */

	if(BPy_KX_PythonSeq_Check(a) && BPy_KX_PythonSeq_Check(b))
		ok= KX_PythonSeq_compare((KX_PythonSeq *)a, (KX_PythonSeq *)b);
	
	switch (op) {
	case Py_NE:
		ok = !ok; /* pass through */
	case Py_EQ:
		res = ok ? Py_False : Py_True;
		break;

	case Py_LT:
	case Py_LE:
	case Py_GT:
	case Py_GE:
		res = Py_NotImplemented;
		break;
	default:
		PyErr_BadArgument();
		return NULL;
	}
	
	Py_INCREF(res);
	return res;
}
Ejemplo n.º 13
0
static PyObject * mp_log_error(PyObject *self, PyObject *args)
{

    int level = 0;
    char *message = NULL;
    serverobject *server = NULL;
    server_rec *serv_rec;

    if (! PyArg_ParseTuple(args, "z|iO", &message, &level, &server))
        return NULL; /* error */

    if (message) {

        if (! level)
            level = APLOG_ERR;

        if (!server || (PyObject *)server == Py_None)
            serv_rec = NULL;
        else {
            if (! MpServer_Check(server)) {
                PyErr_BadArgument();
                return NULL;
            }
            serv_rec = server->server;
        }
        Py_BEGIN_ALLOW_THREADS
        ap_log_error(APLOG_MARK, level, 0, serv_rec, "%s", message);
        Py_END_ALLOW_THREADS
    }

    Py_INCREF(Py_None);
    return Py_None;
}
Ejemplo n.º 14
0
static PyObject *
range_richcompare(PyObject *self, PyObject *other, int op)
{
    int result;

    if (!PyRange_Check(other))
        Py_RETURN_NOTIMPLEMENTED;
    switch (op) {
    case Py_NE:
    case Py_EQ:
        result = range_equals((rangeobject*)self, (rangeobject*)other);
        if (result == -1)
            return NULL;
        if (op == Py_NE)
            result = !result;
        if (result)
            Py_RETURN_TRUE;
        else
            Py_RETURN_FALSE;
    case Py_LE:
    case Py_GE:
    case Py_LT:
    case Py_GT:
        Py_RETURN_NOTIMPLEMENTED;
    default:
        PyErr_BadArgument();
        return NULL;
    }
}
Ejemplo n.º 15
0
static PyObject* Euler_richcmpr(PyObject *a, PyObject *b, int op)
{
	PyObject *res;
	int ok= -1; /* zero is true */

	if (EulerObject_Check(a) && EulerObject_Check(b)) {
		EulerObject *eulA= (EulerObject*)a;
		EulerObject *eulB= (EulerObject*)b;

		if(!BaseMath_ReadCallback(eulA) || !BaseMath_ReadCallback(eulB))
			return NULL;

		ok= ((eulA->order == eulB->order) && EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1)) ? 0 : -1;
	}

	switch (op) {
	case Py_NE:
		ok = !ok; /* pass through */
	case Py_EQ:
		res = ok ? Py_False : Py_True;
		break;

	case Py_LT:
	case Py_LE:
	case Py_GT:
	case Py_GE:
		res = Py_NotImplemented;
		break;
	default:
		PyErr_BadArgument();
		return NULL;
	}

	return Py_INCREF(res), res;
}
Ejemplo n.º 16
0
//------------------------tp_richcmpr
//returns -1 execption, 0 false, 1 true
static PyObject* Color_richcmpr(PyObject *a, PyObject *b, int op)
{
	PyObject *res;
	int ok= -1; /* zero is true */

	if (ColorObject_Check(a) && ColorObject_Check(b)) {
		ColorObject *colA= (ColorObject*)a;
		ColorObject *colB= (ColorObject*)b;

		if (BaseMath_ReadCallback(colA) == -1 || BaseMath_ReadCallback(colB) == -1)
			return NULL;

		ok= EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1) ? 0 : -1;
	}

	switch (op) {
	case Py_NE:
		ok = !ok; /* pass through */
	case Py_EQ:
		res = ok ? Py_False : Py_True;
		break;

	case Py_LT:
	case Py_LE:
	case Py_GT:
	case Py_GE:
		res = Py_NotImplemented;
		break;
	default:
		PyErr_BadArgument();
		return NULL;
	}

	return Py_INCREF(res), res;
}
Ejemplo n.º 17
0
static int wpMulti_setAttr( wpMulti *self, char *name, PyObject *value )
{
	if( !strcmp( "events", name ) )
	{
		if( !PyList_Check( value ) )
		{
			PyErr_BadArgument();
			return -1;
		}

		self->pMulti->clearEvents();
		int i;
		for( i = 0; i < PyList_Size( value ); ++i )
		{
			if( !PyString_Check( PyList_GetItem( value, i ) ) )
				continue;

			cPythonScript *script = ScriptManager::instance()->find( PyString_AsString( PyList_GetItem( value, i ) ) );
			if( script )
				self->pMulti->addEvent( script );
		}
	}
	else
	{
		cVariant val;
		if( PyString_Check( value ) )
			val = cVariant( PyString_AsString( value ) );
		else if( PyInt_Check( value ) )
			val = cVariant( PyInt_AsLong( value ) );
		else if( checkWpItem( value ) )
			val = cVariant( getWpItem( value ) );
		else if( checkWpChar( value ) )
			val = cVariant( getWpChar( value ) );
		else if( checkWpCoord( value ) )
			val = cVariant( getWpCoord( value ) );
		else if( PyFloat_Check( value ) )
			val = cVariant( PyFloat_AsDouble( value ) );

		if( !val.isValid() )
		{
			if( value->ob_type )
				PyErr_Format( PyExc_TypeError, "Unsupported object type: %s", value->ob_type->tp_name );
			else
				PyErr_Format( PyExc_TypeError, "Unknown object type" );
			return 0;
		}

		stError *error = self->pMulti->setProperty( name, val );

		if( error )
		{
			PyErr_Format( PyExc_TypeError, "Error while setting attribute '%s': %s", name, error->text.latin1() );
			delete error;
			return 0;
		}
	}

	return 0;
}
Ejemplo n.º 18
0
static int
buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
{
    PyBufferProcs *pb;
    void *ptr1, *ptr2;
    Py_ssize_t size;
    Py_ssize_t slice_len;
    Py_ssize_t count;

    if ( self->b_readonly ) {
        PyErr_SetString(PyExc_TypeError,
                        "buffer is read-only");
        return -1;
    }

    pb = other ? other->ob_type->tp_as_buffer : NULL;
    if ( pb == NULL ||
         pb->bf_getreadbuffer == NULL ||
         pb->bf_getsegcount == NULL )
    {
        PyErr_BadArgument();
        return -1;
    }
    if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
    {
        /* ### use a different exception type/message? */
        PyErr_SetString(PyExc_TypeError,
                        "single-segment buffer object expected");
        return -1;
    }
    if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
        return -1;
    if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
        return -1;

    if ( left < 0 )
        left = 0;
    else if ( left > size )
        left = size;
    if ( right < left )
        right = left;
    else if ( right > size )
        right = size;
    slice_len = right - left;

    if ( count != slice_len ) {
        PyErr_SetString(
            PyExc_TypeError,
            "right operand length must match slice length");
        return -1;
    }

    if ( slice_len )
        memcpy((char *)ptr1 + left, ptr2, slice_len);

    return 0;
}
Ejemplo n.º 19
0
void*
PyModule_GetState(PyObject* m)
{
    if (!PyModule_Check(m)) {
        PyErr_BadArgument();
        return NULL;
    }
    return ((PyModuleObject *)m)->md_state;
}
Ejemplo n.º 20
0
PyModuleDef*
PyModule_GetDef(PyObject* m)
{
    if (!PyModule_Check(m)) {
        PyErr_BadArgument();
        return NULL;
    }
    return ((PyModuleObject *)m)->md_def;
}
Ejemplo n.º 21
0
SP_CLASS_ATTR_GET(Vector3,z)(PyObject *self, void*)
{
    Vector3* obj=dynamic_cast<Vector3*>(((PyPtr<Vector3>*)self)->object);
    if (!obj)
    {
        PyErr_BadArgument();
        return 0;
    }
    return PyFloat_FromDouble(obj->z());
}
Ejemplo n.º 22
0
XFontStruct *
PaxFont_AsFontStruct(PyObject *self)
{
    if (self->ob_type != &PaxFontType)
    {
	PyErr_BadArgument();
	return 0;
    }
    return ((PaxFontObject *) self)->font_struct;
}
Ejemplo n.º 23
0
int PyConvertSocket( PyObject* object, cUOSocket** sock )
{
	if ( object->ob_type != &wpSocketType )
	{
		PyErr_BadArgument();
		return 0;
	}

	*sock = ( ( wpSocket * ) object )->pSock;
	return 1;
}
Ejemplo n.º 24
0
int PyConvertCoord( PyObject* object, Coord_cl* pos )
{
	if ( object->ob_type != &wpCoordType )
	{
		PyErr_BadArgument();
		return 0;
	}

	*pos = ( ( wpCoord * ) object )->coord;
	return 1;
}
Ejemplo n.º 25
0
SP_CLASS_ATTR_SET(Vector3,z)(PyObject *self, PyObject * args, void*)
{
    Vector3* obj=dynamic_cast<Vector3*>(((PyPtr<Vector3>*)self)->object);
    if (!obj)
    {
        PyErr_BadArgument();
        return 0;
    }
    obj->z()=PyFloat_AsDouble(args);
    return 0;
}
Ejemplo n.º 26
0
static PyObject *
forms_get_rgbmode(PyObject *dummy, PyObject *args)
{
	extern int fl_rgbmode;

	if (args != NULL) {
		PyErr_BadArgument();
		return NULL;
	}
	return PyInt_FromLong((long)fl_rgbmode);
}
Ejemplo n.º 27
0
static PyObject *
PyGreenlet_Throw(PyGreenlet *self, PyObject *typ, PyObject *val, PyObject *tb)
{
	if (!PyGreenlet_Check(self)) {
		PyErr_BadArgument();
		return NULL;
	}
	Py_INCREF(typ);
	Py_XINCREF(val);
	Py_XINCREF(tb);
	return throw_greenlet(self, typ, val, tb);
}
Ejemplo n.º 28
0
static object *
amigalibs_fixstr(object *self, object *arg)
{
	if(arg && PyString_Check(arg))
	{
		char * str = PyString_AS_STRING((PyStringObject*)arg);
		int len = PyString_Size(arg);
		int len2 = strlen(str);
		return PyString_FromStringAndSize(str,min(len,len2));
	}
	return (object*)PyErr_BadArgument();
}
Ejemplo n.º 29
0
PyObject *wrap_setEntry(PyObject *o, PyObject * args, PyObject * kwargs)
{
	const char *module_id;
	ppk_entry entry;
	ppk_data data;
	unsigned int type, data_type;
	const char *host = 0, *login = 0, *app_name = 0, *username = 0, *item = 0, *string = 0, *blob = 0;
	int size = 0;
	unsigned int port = 0;
	unsigned int flags = 0;
	static char *kwlist[] = { "module_id", "type", "data_type", "host", "login", "port", "app_name", "username", "item", "string", "blob", "flags", NULL };
	int ok = PyArg_ParseTupleAndKeywords(args, kwargs, "sII|ssHsssst#I", kwlist, &module_id,
			&type, &data_type, &host, &login, &port, &app_name, &username, &item, &string, &blob, &size, &flags);

	switch (type)
	{
	case ppk_network:
		ok = ok && host && login && port && ! app_name && ! username && ! item;
		break;
	case ppk_application:
		ok = ok && ! host && ! login && ! port && app_name && username && ! item;
		break;
	case ppk_item:
		ok = ok && ! host && ! login && ! port && ! app_name && ! username && item;
		break;
	default:
		ok = 0;
	};

	switch (data_type)
	{
	case ppk_string:
		ok = ok && string && ! blob;
		break;
	case ppk_blob:
		ok = ok && blob && size && ! string;
		break;
	default:
		ok = 0;
	}

	if (! ok)
	{
	    PyErr_BadArgument();
	    return 0;
	}

	buildEntry(&entry, type, host, login, port, app_name, username, item);
	buildData(&data, data_type, string, blob, size);

	return (ppk_setEntry(module_id, entry, data, flags)) ? Py_True : Py_False;
}
Ejemplo n.º 30
0
static PyObject *
buffer_concat(PyBufferObject *self, PyObject *other)
{
    PyBufferProcs *pb = other->ob_type->tp_as_buffer;
    void *ptr1, *ptr2;
    char *p;
    PyObject *ob;
    Py_ssize_t size, count;

    if ( pb == NULL ||
         pb->bf_getreadbuffer == NULL ||
         pb->bf_getsegcount == NULL )
    {
        PyErr_BadArgument();
        return NULL;
    }
    if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
    {
        /* ### use a different exception type/message? */
        PyErr_SetString(PyExc_TypeError,
                        "single-segment buffer object expected");
        return NULL;
    }

    if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
        return NULL;

    /* optimize special case */
    if ( size == 0 )
    {
        Py_INCREF(other);
        return other;
    }

    if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
        return NULL;

    // Pyston change: no PY_SIZE_MAX
    // assert(count <= PY_SIZE_MAX - size);

    ob = PyString_FromStringAndSize(NULL, size + count);
    if ( ob == NULL )
        return NULL;
    p = PyString_AS_STRING(ob);
    memcpy(p, ptr1, size);
    memcpy(p + size, ptr2, count);

    /* there is an extra byte in the string object, so this is safe */
    p[size + count] = '\0';

    return ob;
}