1/*
2 * A custom wrapper for the (opaque) FSSpec structure.
3 */
4#include "pyobjc.h"
5#import <CoreServices/CoreServices.h>
6
7
8#if USE_TOOLBOX_OBJECT_GLUE
9#include "pymactoolbox.h"
10#endif
11
12/*
13 * Interface of the FSSpec type:
14 *
15 * FSSpec.from_pathname(value)
16 *   # -> returns new FSSpec instance for posix path 'value'
17 *
18 * aspec.as_pathname()
19 *  # -> returns a Unicode string with the posix path
20 *
21 * aspec.as_carbon()
22 *  # -> return a Carbon.File.FSSpec instance (only
23 *  #    available when Carbon support is enabled in Python)
24 *
25 * aspec.data
26 *  # -> read-only property with the bytes in the FSSpec
27 *
28 * This is more or less the same interface as Carbon.File.FSSpec, but
29 * excluding API wrappers.
30 */
31
32typedef struct {
33	PyObject_HEAD
34
35	FSSpec	ref;
36} PyObjC_FSSpecObject;
37
38static PyObject* fsspec_as_bytes(PyObject* ref, void* closure __attribute__((__unused__)))
39{
40	if (!PyObjC_FSSpecCheck(ref)) {
41		PyErr_SetString(PyExc_TypeError, "self is not a FSSpec");
42	}
43
44	return PyBytes_FromStringAndSize(
45			(char*)&((PyObjC_FSSpecObject*)ref)->ref,
46			sizeof(FSSpec));
47}
48
49#if defined(USE_TOOLBOX_OBJECT_GLUE) && !defined(__LP64__)
50static PyObject* fsspec_as_carbon(PyObject* ref)
51{
52	if (!PyObjC_FSSpecCheck(ref)) {
53		PyErr_SetString(PyExc_TypeError, "self is not a FSSpec");
54	}
55
56	return PyMac_BuildFSSpec((&((PyObjC_FSSpecObject*)ref)->ref));
57}
58#endif
59
60static PyGetSetDef fsspec_getset[] = {
61	{
62		"data",
63		fsspec_as_bytes,
64		0,
65		"bytes in the FSSpec",
66		0
67	},
68	{ 0, 0, 0, 0, 0}
69};
70
71
72static PyMethodDef fsspec_methods[] = {
73#if defined(USE_TOOLBOX_OBJECT_GLUE) && !defined(__LP64__)
74	{
75		"as_carbon",
76		(PyCFunction)fsspec_as_carbon,
77		METH_NOARGS,
78		"return Carbon.File.FSSpec instance for this object"
79	},
80#endif
81
82	{ 0, 0, 0, 0 }
83};
84
85
86PyTypeObject PyObjC_FSSpecType = {
87	PyVarObject_HEAD_INIT(&PyType_Type, 0)
88	"objc.FSSpec",				/* tp_name */
89	sizeof(PyObjC_FSSpecObject),		/* tp_basicsize */
90	0,					/* tp_itemsize */
91	/* methods */
92	0,					/* tp_dealloc */
93	0,					/* tp_print */
94	0,					/* tp_getattr */
95	0,					/* tp_setattr */
96	0,					/* tp_compare */
97	0,					/* tp_repr */
98	0,					/* tp_as_number */
99	0,					/* tp_as_sequence */
100	0,		       			/* tp_as_mapping */
101	0,					/* tp_hash */
102	0,					/* tp_call */
103	0,					/* tp_str */
104	PyObject_GenericGetAttr,		/* tp_getattro */
105	PyObject_GenericSetAttr,		/* tp_setattro */
106	0,					/* tp_as_buffer */
107	Py_TPFLAGS_DEFAULT,			/* tp_flags */
108 	0,					/* tp_doc */
109 	0,					/* tp_traverse */
110 	0,					/* tp_clear */
111	0,					/* tp_richcompare */
112	0,					/* tp_weaklistoffset */
113	0,					/* tp_iter */
114	0,					/* tp_iternext */
115	fsspec_methods,				/* tp_methods */
116	0,					/* tp_members */
117	fsspec_getset,				/* tp_getset */
118	0,					/* tp_base */
119	0,					/* tp_dict */
120	0,					/* tp_descr_get */
121	0,					/* tp_descr_set */
122	0,					/* tp_dictoffset */
123	0,					/* tp_init */
124	0,					/* tp_alloc */
125	0,					/* tp_new */
126	0,		        		/* tp_free */
127	0,					/* tp_is_gc */
128	0,                                      /* tp_bases */
129	0,                                      /* tp_mro */
130	0,                                      /* tp_cache */
131	0,                                      /* tp_subclasses */
132	0,                                      /* tp_weaklist */
133	0                                       /* tp_del */
134#if PY_VERSION_HEX >= 0x02060000
135	, 0                                     /* tp_version_tag */
136#endif
137
138};
139
140
141int PyObjC_encode_fsspec(PyObject* value, void* buffer)
142{
143#if defined(USE_TOOLBOX_OBJECT_GLUE) && !defined(__LP64__)
144	/* We cannot test if 'arg' is an instance of Carbon.File.FSSpec... */
145	if (PyMac_GetFSSpec(value, (FSSpec*)buffer) == 1) {
146		return 0;
147	}
148	PyErr_Clear();
149#endif
150
151	if (PyObjC_FSSpecCheck(value)) {
152		*(FSSpec*)buffer = ((PyObjC_FSSpecObject*)value)->ref;
153		return 0;
154	}
155
156	PyErr_SetString(PyExc_ValueError, "Cannot convert value to FSSpec");
157	return -1;
158}
159
160
161PyObject* PyObjC_decode_fsspec(void* buffer)
162{
163	PyObjC_FSSpecObject* result = PyObject_New(
164			PyObjC_FSSpecObject, &PyObjC_FSSpecType);
165	if (result == NULL) {
166		return NULL;
167	}
168	result->ref = *(FSSpec*)buffer;
169	return (PyObject*)result;
170}
171