1 /******************************************************************************
2  * $Id: python_strings.i d735c61288062ffcfdcc10d5b37e27443ffaaed7 2021-08-24 11:32:17 +0200 Even Rouault $
3  *
4  * Name:     python_strings.i
5  * Project:  GDAL Python Interface
6  * Author:   Even Rouault, <even dot rouault at spatialys.com>
7  *
8  ******************************************************************************
9  * Copyright (c) 2009, Even Rouault
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  *****************************************************************************/
29 
30 %{
31 
32 /* Return a PyObject* from a NULL terminated C String */
33 static PyObject* GDALPythonObjectFromCStr(const char *pszStr) CPL_UNUSED;
GDALPythonObjectFromCStr(const char * pszStr)34 static PyObject* GDALPythonObjectFromCStr(const char *pszStr)
35 {
36   const unsigned char* pszIter = (const unsigned char*) pszStr;
37   while(*pszIter != 0)
38   {
39     if (*pszIter > 127)
40     {
41         PyObject* pyObj = PyUnicode_DecodeUTF8(pszStr, strlen(pszStr), "strict");
42         if (pyObj != NULL && !PyErr_Occurred())
43             return pyObj;
44         PyErr_Clear();
45         return PyBytes_FromString(pszStr);
46     }
47     pszIter ++;
48   }
49   return PyUnicode_FromString(pszStr);
50 }
51 
52 /* Return a NULL terminated c String from a PyObject */
53 /* Result must be freed with GDALPythonFreeCStr */
54 static char* GDALPythonObjectToCStr(PyObject* pyObject, int* pbToFree) CPL_UNUSED;
GDALPythonObjectToCStr(PyObject * pyObject,int * pbToFree)55 static char* GDALPythonObjectToCStr(PyObject* pyObject, int* pbToFree)
56 {
57   *pbToFree = 0;
58   if (PyUnicode_Check(pyObject))
59   {
60       char *pszStr;
61       char *pszNewStr;
62       Py_ssize_t nLen;
63       PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObject);
64       if( pyUTF8Str == NULL )
65         return NULL;
66       PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
67       pszNewStr = (char *) malloc(nLen+1);
68       if( pszNewStr == NULL )
69       {
70           CPLError(CE_Failure, CPLE_OutOfMemory, "Failed to allocate %llu bytes",
71                    (unsigned long long)(nLen + 1));
72           Py_XDECREF(pyUTF8Str);
73           return NULL;
74       }
75       memcpy(pszNewStr, pszStr, nLen+1);
76       Py_XDECREF(pyUTF8Str);
77       *pbToFree = 1;
78       return pszNewStr;
79   }
80   else if( PyBytes_Check(pyObject) )
81   {
82       char* ret = PyBytes_AsString(pyObject);
83 
84       // Check if there are \0 bytes inside the string
85       const Py_ssize_t size = PyBytes_Size(pyObject);
86       for( Py_ssize_t i = 0; i < size; i++ )
87       {
88           if( ret[i] == 0 )
89           {
90               CPLError(CE_Failure, CPLE_AppDefined,
91                        "bytes object cast as string contains a zero-byte.");
92               return NULL;
93           }
94       }
95 
96       return ret;
97   }
98   else
99   {
100       CPLError(CE_Failure, CPLE_AppDefined,
101                "Passed object is neither of type string nor bytes");
102       return NULL;
103   }
104 }
105 
106 static void GDALPythonFreeCStr(void* ptr, int bToFree) CPL_UNUSED;
GDALPythonFreeCStr(void * ptr,int bToFree)107 static void GDALPythonFreeCStr(void* ptr, int bToFree)
108 {
109    if (bToFree)
110        free(ptr);
111 }
112 
113 %}
114