1/*
2 * Special wrappers for NSString methods with 'difficult' arguments.
3 *
4 * -getCString:maxLength:range:remainingRange:	[call]
5 * -getCString:maxLength:			[call]
6 *
7 */
8
9static PyObject*
10call_NSString_getCString_maxLength_range_remainingRange_(
11	PyObject* method, PyObject* self, PyObject* arguments)
12{
13	PyObject* rangeObj;
14	NSRange aRange;
15	NSRange leftoverRange;
16	NSRange* leftoverPtr;
17	char* buf;
18	NSUInteger maxLength;
19	struct objc_super super;
20	PyObject* res;
21	PyObject* buf1, *buf2;
22
23	if  (!PyArg_ParseTuple(arguments, "O" Py_ARG_NSUInteger "OO", &buf1, &maxLength, &rangeObj, &buf2)) {
24		return NULL;
25	}
26
27	if (PyObjC_PythonToObjC(@encode(NSRange), rangeObj, &aRange) < 0) {
28		return NULL;
29	}
30
31	if (buf1 != Py_None) {
32		PyErr_SetString(PyExc_ValueError, "output buffer must be None");
33		return NULL;
34	}
35	if (buf2 != Py_None && buf2 != PyObjC_NULL) {
36		PyErr_SetString(PyExc_ValueError, "range buffer must be None or NULL");
37		return NULL;
38	}
39	if (buf2 == PyObjC_NULL) {
40		leftoverPtr = NULL;
41	} else {
42		leftoverPtr = &leftoverRange;
43	}
44
45
46	buf = malloc(maxLength+1);
47	if (buf == NULL) {
48		PyErr_NoMemory();
49		return NULL;
50	}
51
52	PyObjC_DURING
53		PyObjC_InitSuper(&super,
54			PyObjCSelector_GetClass(method),
55			PyObjCObject_GetObject(self));
56
57		((void(*)(struct objc_super*, SEL, void*, NSInteger, NSRange, NSRange*))objc_msgSendSuper)(&super,
58			@selector(getCString:maxLength:range:remainingRange:),
59			buf, maxLength, aRange, leftoverPtr);
60	PyObjC_HANDLER
61		PyObjCErr_FromObjC(localException);
62	PyObjC_ENDHANDLER
63
64	if (PyErr_Occurred()) {
65		free(buf);
66		return NULL;
67	}
68
69	res = PyTuple_New(2);
70	if (res == NULL) {
71		free(buf);
72		return NULL;
73	}
74
75	PyTuple_SetItem(res, 0, PyBytes_FromString(buf));
76	free(buf);
77	if (PyErr_Occurred()) {
78		Py_DECREF(res);
79		free(buf);
80		return NULL;
81	}
82
83	if (leftoverPtr != NULL) {
84		rangeObj = PyObjC_ObjCToPython(@encode(NSRange), &leftoverRange);
85		if (rangeObj == NULL) {
86			Py_DECREF(res);
87			return NULL;
88		}
89
90		PyTuple_SetItem(res, 1, rangeObj);
91	} else {
92		PyTuple_SetItem(res, 1, PyObjC_NULL);
93	}
94	return res;
95}
96
97static PyObject*
98call_NSString_getCString_maxLength_(
99	PyObject* method, PyObject* self, PyObject* arguments)
100{
101	char* buf;
102	NSUInteger maxLength;
103	struct objc_super super;
104	PyObject* res;
105	PyObject* py_buf;
106
107	if  (!PyArg_ParseTuple(arguments, "O" Py_ARG_NSUInteger, &py_buf, &maxLength)) {
108		return NULL;
109	}
110	if (py_buf != Py_None) {
111		PyErr_SetString(PyExc_ValueError, "buffer must be None");
112		return NULL;
113	}
114
115	buf = malloc(maxLength+1);
116	if (buf == NULL) {
117		PyErr_NoMemory();
118		return NULL;
119	}
120
121	PyObjC_DURING
122		PyObjC_InitSuper(&super,
123			PyObjCSelector_GetClass(method),
124			PyObjCObject_GetObject(self));
125
126		((void(*)(struct objc_super*, SEL, void*, NSUInteger))objc_msgSendSuper)(&super,
127			@selector(getCString:maxLength:),
128			buf, maxLength);
129	PyObjC_HANDLER
130		PyObjCErr_FromObjC(localException);
131	PyObjC_ENDHANDLER
132
133	if (PyErr_Occurred()) {
134		free(buf);
135		return NULL;
136	}
137
138	res = PyBytes_FromString(buf);
139	free(buf);
140	if (res == NULL) {
141		return NULL;
142	}
143
144	return res;
145}
146
147static int setup_nssstring(PyObject* m __attribute__((__unused__)))
148{
149	Class classNSString = objc_lookUpClass("NSString");
150	if (classNSString == NULL) {
151		return 0;
152	}
153
154	if (PyObjC_RegisterMethodMapping(
155		classNSString,
156		@selector(getCString:maxLength:range:remainingRange:),
157		call_NSString_getCString_maxLength_range_remainingRange_,
158		PyObjCUnsupportedMethod_IMP) < 0) {
159
160		return -1;
161	}
162
163	if (PyObjC_RegisterMethodMapping(
164		classNSString,
165		@selector(getCString:maxLength:),
166		call_NSString_getCString_maxLength_,
167		PyObjCUnsupportedMethod_IMP) < 0) {
168
169		return -1;
170	}
171
172	return 0;
173}
174