xref: /petsc/src/binding/petsc4py/src/petsc4py/PETSc/petscopt.pxi (revision 6d8694c4fbab79f9439f1ad13c0386ba7ee1ca4b)
1cdef extern from * nogil:
2
3    ctypedef struct _n_PetscOptions
4    ctypedef _n_PetscOptions* PetscOptions
5
6    PetscErrorCode PetscOptionsCreate(PetscOptions*)
7    PetscErrorCode PetscOptionsDestroy(PetscOptions*)
8    PetscErrorCode PetscOptionsView(PetscOptions, PetscViewer)
9    PetscErrorCode PetscOptionsClear(PetscOptions)
10
11    PetscErrorCode PetscOptionsPrefixPush(PetscOptions, char[])
12    PetscErrorCode PetscOptionsPrefixPop(PetscOptions)
13
14    PetscErrorCode PetscOptionsHasName(PetscOptions, char[], char[], PetscBool*)
15    PetscErrorCode PetscOptionsUsed(PetscOptions, char[], PetscBool*)
16    PetscErrorCode PetscOptionsSetAlias(PetscOptions, char[], char[])
17    PetscErrorCode PetscOptionsSetValue(PetscOptions, char[], char[])
18    PetscErrorCode PetscOptionsClearValue(PetscOptions, char[])
19
20    PetscErrorCode PetscOptionsInsertString(PetscOptions, char[])
21    PetscErrorCode PetscOptionsInsertFile(PetscOptions, char[])
22    PetscErrorCode PetscOptionsGetAll(PetscOptions, char*[])
23
24    PetscErrorCode PetscOptionsGetBool(PetscOptions, char[], char[], PetscBool*, PetscBool*)
25    PetscErrorCode PetscOptionsGetBoolArray(PetscOptions, char[], char[], PetscBool[], PetscInt*, PetscBool*)
26    PetscErrorCode PetscOptionsGetInt(PetscOptions, char[], char[], PetscInt*, PetscBool*)
27    PetscErrorCode PetscOptionsGetIntArray(PetscOptions, char[], char[], PetscInt[], PetscInt*, PetscBool*)
28    PetscErrorCode PetscOptionsGetReal(PetscOptions, char[], char[], PetscReal*, PetscBool*)
29    PetscErrorCode PetscOptionsGetRealArray(PetscOptions, char[], char[], PetscReal[], PetscInt*, PetscBool*)
30    PetscErrorCode PetscOptionsGetScalar(PetscOptions, char[], char[], PetscScalar*, PetscBool*)
31    PetscErrorCode PetscOptionsGetScalarArray(PetscOptions, char[], char[], PetscScalar[], PetscInt*, PetscBool*)
32    PetscErrorCode PetscOptionsGetString(PetscOptions, char[], char[], char[], size_t, PetscBool*)
33
34    ctypedef struct _p_PetscToken
35    ctypedef _p_PetscToken* PetscToken
36    PetscErrorCode PetscTokenCreate(char[], char, PetscToken*)
37    PetscErrorCode PetscTokenDestroy(PetscToken*)
38    PetscErrorCode PetscTokenFind(PetscToken, const char*[])
39    PetscErrorCode PetscOptionsValidKey(char[], PetscBool*)
40
41#
42
43cdef getprefix(prefix, deft=None):
44    if prefix is None:
45        prefix = deft
46    elif isinstance(prefix, Options):
47        prefix = prefix.prefix
48    elif isinstance(prefix, Object):
49        prefix = prefix.getOptionsPrefix()
50    elif not isinstance(prefix, str):
51        raise TypeError('option prefix must be string')
52    if not prefix:
53        return None
54    if prefix.count(' '):
55        raise ValueError('option prefix should not have spaces')
56    if prefix.startswith('-'):
57        raise ValueError('option prefix should not start with a hyphen')
58    return prefix
59
60#
61
62cdef opt2str(const char *pre, const char *name):
63    p = bytes2str(pre)  if pre!=NULL else None
64    n = bytes2str(name) if name[0]!=c'-' else bytes2str(&name[1])
65    return '(prefix:%s, name:%s)' % (p, n)
66
67cdef getopt_Bool(PetscOptions opt, const char *pre, const char *name, object deft):
68    cdef PetscBool value = PETSC_FALSE
69    cdef PetscBool flag  = PETSC_FALSE
70    CHKERR(PetscOptionsGetBool(opt, pre, name, &value, &flag))
71    if flag==PETSC_TRUE: return toBool(value)
72    if deft is not None: return toBool(asBool(deft))
73    raise KeyError(opt2str(pre, name))
74
75cdef getopt_BoolArray(PetscOptions opt, const char *pre, const char *name, object deft):
76    cdef PetscBool value[1024], *ivalue = value, *ivaluedeft = NULL
77    cdef PetscInt nmax = 1024, ndeft = 0
78    cdef PetscBool flag = PETSC_FALSE
79    cdef object unused
80    if deft is not None:
81        deft = [toBool(asBool(d)) for d in deft]
82        deft = iarray_b(deft, &ndeft, &ivaluedeft)
83        if ndeft > nmax:
84            unused = oarray_b(empty_b(ndeft), &nmax, &ivalue)
85        memcpy(ivalue, ivaluedeft, <size_t>ndeft*sizeof(PetscBool))
86    CHKERR(PetscOptionsGetBoolArray(opt, pre, name, ivalue, &nmax, &flag))
87    if flag==PETSC_TRUE: return array_b(nmax, ivalue).astype('bool')
88    if deft is not None: return deft.astype('bool')
89    raise KeyError(opt2str(pre, name))
90
91cdef getopt_Int(PetscOptions opt, const char *pre, const char *name, object deft):
92    cdef PetscInt value = 0
93    cdef PetscBool flag = PETSC_FALSE
94    CHKERR(PetscOptionsGetInt(opt, pre, name, &value, &flag))
95    if flag==PETSC_TRUE: return toInt(value)
96    if deft is not None: return toInt(asInt(deft))
97    raise KeyError(opt2str(pre, name))
98
99cdef getopt_IntArray(PetscOptions opt, const char *pre, const char *name, object deft):
100    cdef PetscInt value[1024], *ivalue = value, *ivaluedeft = NULL
101    cdef PetscInt nmax = 1024, ndeft = 0
102    cdef PetscBool flag = PETSC_FALSE
103    cdef object unused
104    if deft is not None:
105        deft = iarray_i(deft, &ndeft, &ivaluedeft)
106        if ndeft > nmax:
107            unused = oarray_i(empty_i(ndeft), &nmax, &ivalue)
108        memcpy(ivalue, ivaluedeft, <size_t>ndeft*sizeof(PetscInt))
109    CHKERR(PetscOptionsGetIntArray(opt, pre, name, ivalue, &nmax, &flag))
110    if flag==PETSC_TRUE: return array_i(nmax, ivalue)
111    if deft is not None: return deft
112    raise KeyError(opt2str(pre, name))
113
114cdef getopt_Real(PetscOptions opt, const char *pre, const char *name, object deft):
115    cdef PetscReal value = 0
116    cdef PetscBool flag = PETSC_FALSE
117    CHKERR(PetscOptionsGetReal(opt, pre, name, &value, &flag))
118    if flag==PETSC_TRUE: return toReal(value)
119    if deft is not None: return toReal(asReal(deft))
120    raise KeyError(opt2str(pre, name))
121
122cdef getopt_RealArray(PetscOptions opt, const char *pre, const char *name, object deft):
123    cdef PetscReal value[1024], *ivalue = value, *ivaluedeft = NULL
124    cdef PetscInt nmax = 1024, ndeft = 0
125    cdef PetscBool flag = PETSC_FALSE
126    cdef object unused
127    if deft is not None:
128        deft = iarray_r(deft, &ndeft, &ivaluedeft)
129        if ndeft > nmax:
130            unused = oarray_r(empty_r(ndeft), &nmax, &ivalue)
131        memcpy(ivalue, ivaluedeft, <size_t>ndeft*sizeof(PetscReal))
132    CHKERR(PetscOptionsGetRealArray(opt, pre, name, ivalue, &nmax, &flag))
133    if flag==PETSC_TRUE: return array_r(nmax, ivalue)
134    if deft is not None: return deft
135    raise KeyError(opt2str(pre, name))
136
137cdef getopt_Scalar(PetscOptions opt, const char *pre, const char *name, object deft):
138    cdef PetscScalar value = 0
139    cdef PetscBool flag = PETSC_FALSE
140    CHKERR(PetscOptionsGetScalar(opt, pre, name, &value, &flag))
141    if flag==PETSC_TRUE: return toScalar(value)
142    if deft is not None: return toScalar(asScalar(deft))
143    raise KeyError(opt2str(pre, name))
144
145cdef getopt_ScalarArray(PetscOptions opt, const char *pre, const char *name, object deft):
146    cdef PetscScalar value[1024], *ivalue = value, *ivaluedeft = NULL
147    cdef PetscInt nmax = 1024, ndeft = 0
148    cdef PetscBool flag = PETSC_FALSE
149    cdef object unused
150    if deft is not None:
151        deft = iarray_s(deft, &ndeft, &ivaluedeft)
152        if ndeft > nmax:
153            unused = oarray_s(empty_s(ndeft), &nmax, &ivalue)
154        memcpy(ivalue, ivaluedeft, <size_t>ndeft*sizeof(PetscScalar))
155    CHKERR(PetscOptionsGetScalarArray(opt, pre, name, ivalue, &nmax, &flag))
156    if flag==PETSC_TRUE: return array_s(nmax, ivalue)
157    if deft is not None: return deft
158    raise KeyError(opt2str(pre, name))
159
160cdef getopt_String(PetscOptions opt, const char *pre, const char *name, object deft):
161    cdef char value[1024+1]
162    cdef PetscBool flag = PETSC_FALSE
163    CHKERR(PetscOptionsGetString(opt, pre, name, value, 1024, &flag))
164    if flag==PETSC_TRUE: return bytes2str(value)
165    if deft is not None: return str(deft)
166    raise KeyError(opt2str(pre, name))
167
168cdef enum PetscOptType:
169    OPT_BOOL
170    OPT_BOOLARRAY
171    OPT_INT
172    OPT_INTARRAY
173    OPT_REAL
174    OPT_REALARRAY
175    OPT_SCALAR
176    OPT_SCALARARRAY
177    OPT_STRING
178
179cdef getpair(prefix, name, const char **pr, const char **nm):
180    # --
181    cdef const char *p = NULL
182    prefix = str2bytes(prefix, &p)
183    if p != NULL and p[0] == c'-':
184        p = &p[1]
185    # --
186    cdef const char *n = NULL
187    name = str2bytes(name, &n)
188    if n != NULL and n[0] != c'-':
189        name = b'-' + name
190        name = str2bytes(name, &n)
191    # --
192    pr[0] = p
193    nm[0] = n
194    return (prefix, name)
195
196cdef getopt(PetscOptions opt, PetscOptType otype, prefix, name, deft):
197    cdef const char *pr = NULL
198    cdef const char *nm = NULL
199    cdef object unused = getpair(prefix, name, &pr, &nm)
200    if otype == OPT_BOOL        : return getopt_Bool        (opt, pr, nm, deft)
201    if otype == OPT_BOOLARRAY   : return getopt_BoolArray   (opt, pr, nm, deft)
202    if otype == OPT_INT         : return getopt_Int         (opt, pr, nm, deft)
203    if otype == OPT_INTARRAY    : return getopt_IntArray    (opt, pr, nm, deft)
204    if otype == OPT_REAL        : return getopt_Real        (opt, pr, nm, deft)
205    if otype == OPT_REALARRAY   : return getopt_RealArray   (opt, pr, nm, deft)
206    if otype == OPT_SCALAR      : return getopt_Scalar      (opt, pr, nm, deft)
207    if otype == OPT_SCALARARRAY : return getopt_ScalarArray (opt, pr, nm, deft)
208    if otype == OPT_STRING      : return getopt_String      (opt, pr, nm, deft)
209
210
211# simple minded options parser
212
213cdef tokenize(options):
214    cdef PetscToken t = NULL
215    cdef const char *s = NULL
216    cdef const char *p = NULL
217    options = str2bytes(options, &s)
218    cdef list tokens = []
219    CHKERR(PetscTokenCreate(s, c' ', &t))
220    try:
221        CHKERR(PetscTokenFind(t, <const char**>&p))
222        while p != NULL:
223            tokens.append(bytes2str(p))
224            CHKERR(PetscTokenFind(t, <const char**>&p))
225    finally:
226        CHKERR(PetscTokenDestroy(&t))
227    return tokens
228
229cdef bint iskey(key):
230    cdef const char *k = NULL
231    cdef PetscBool b = PETSC_FALSE
232    if key:
233        key = str2bytes(key, &k)
234        CHKERR(PetscOptionsValidKey(k, &b))
235        if b == PETSC_TRUE:
236            return True
237    return False
238
239cdef gettok(tokens):
240    if tokens:
241        return tokens.pop(0)
242    else:
243        return None
244
245cdef getkey(key, prefix):
246    if not iskey(key):
247        return None
248    key = key[1:]
249    if key[0] == '-':
250        key = key[1:]
251    if not key.startswith(prefix):
252        return None
253    return key.replace(prefix, '', 1)
254
255cdef parseopt(options, prefix):
256    if isinstance(options, str):
257        tokens = tokenize(options)
258    else:
259        tokens = list(options)
260    prefix = prefix or ''
261    # parser loop
262    opts = {}
263    first = gettok(tokens)
264    while first:
265        key = getkey(first, prefix)
266        if not key:
267            first = gettok(tokens)
268        else:
269            second = gettok(tokens)
270            if getkey(second, prefix):
271                value = None
272                first = second
273            else:
274                value = second
275                first = gettok(tokens)
276            opts[key] = value
277    # we are done
278    return opts
279