OILS / pyext / fastfunc.c View on Github | oilshell.org

133 lines, 88 significant
1// Python wrapper for FANOS library in cpp/fanos_shared.h
2
3#include <assert.h>
4#include <stdarg.h> // va_list, etc.
5#include <stdio.h> // vfprintf
6#include <stdlib.h>
7
8#include "data_lang/j8.h" // CanOmitQuotes
9#include "data_lang/j8_libc.h"
10#include "data_lang/utf8.h"
11
12#include <Python.h>
13
14#if 0
15// Log messages to stderr.
16static void debug(const char* fmt, ...) {
17 va_list args;
18 va_start(args, fmt);
19 vfprintf(stderr, fmt, args);
20 va_end(args);
21 fprintf(stderr, "\n");
22}
23#endif
24
25static PyObject *
26func_J8EncodeString(PyObject *self, PyObject *args) {
27 j8_buf_t in;
28 int j8_fallback;
29
30 if (!PyArg_ParseTuple(args, "s#i", &(in.data), &(in.len), &j8_fallback)) {
31 return NULL;
32 }
33
34 j8_buf_t out;
35 J8EncodeString(in, &out, j8_fallback);
36
37 PyObject *ret = PyString_FromStringAndSize(out.data, out.len);
38 return ret;
39}
40
41static PyObject *
42func_ShellEncodeString(PyObject *self, PyObject *args) {
43 j8_buf_t in;
44 int ysh_fallback;
45
46 if (!PyArg_ParseTuple(args, "s#i", &(in.data), &(in.len), &ysh_fallback)) {
47 return NULL;
48 }
49
50 j8_buf_t out;
51 ShellEncodeString(in, &out, ysh_fallback);
52
53 PyObject *ret = PyString_FromStringAndSize(out.data, out.len);
54 return ret;
55}
56
57static PyObject *
58func_PartIsUtf8(PyObject *self, PyObject *args) {
59 j8_buf_t in;
60 int start;
61 int end;
62
63 if (!PyArg_ParseTuple(args, "s#ii", &(in.data), &(in.len), &start, &end)) {
64 return NULL;
65 }
66 // Bounds check for safety
67 assert(0 <= start);
68 assert(end <= in.len);
69
70 Utf8Result_t result;
71 for (int i = start; i < end;) {
72 utf8_decode(in.data + i, &result);
73 if (result.error) {
74 return PyBool_FromLong(0);
75 }
76
77 i += result.bytes_read;
78 }
79
80 return PyBool_FromLong(1);
81}
82
83static PyObject *
84func_Utf8DecodeOne(PyObject *self, PyObject *args) {
85 char *string;
86 size_t length;
87 int start;
88
89 if (!PyArg_ParseTuple(args, "s#i", &string, &length, &start)) {
90 return NULL;
91 }
92
93 // Bounds check for safety
94 assert(0 <= start && start < length);
95
96 Utf8Result_t decode_result;
97 utf8_decode(string + start, &decode_result);
98 int32_t codepoint_or_error;
99 if (decode_result.error) {
100 codepoint_or_error = -decode_result.error;
101 } else {
102 codepoint_or_error = decode_result.codepoint;
103 }
104
105 PyObject *ret_val = PyTuple_New(2);
106 PyTuple_SET_ITEM(ret_val, 0, PyInt_FromLong(codepoint_or_error));
107 PyTuple_SET_ITEM(ret_val, 1, PyInt_FromLong(decode_result.bytes_read));
108 return ret_val;
109}
110
111static PyObject *
112func_CanOmitQuotes(PyObject *self, PyObject *args) {
113 j8_buf_t in;
114 if (!PyArg_ParseTuple(args, "s#", &(in.data), &(in.len))) {
115 return NULL;
116 }
117 int result = CanOmitQuotes(in.data, in.len);
118 return PyBool_FromLong(result);
119}
120
121static PyMethodDef methods[] = {
122 {"J8EncodeString", func_J8EncodeString, METH_VARARGS, ""},
123 {"ShellEncodeString", func_ShellEncodeString, METH_VARARGS, ""},
124 {"PartIsUtf8", func_PartIsUtf8, METH_VARARGS, ""},
125 {"Utf8DecodeOne", func_Utf8DecodeOne, METH_VARARGS, ""},
126 {"CanOmitQuotes", func_CanOmitQuotes, METH_VARARGS, ""},
127
128 {NULL, NULL},
129};
130
131void initfastfunc(void) {
132 Py_InitModule("fastfunc", methods);
133}