Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
main
pyicu
Commits
2de02374
Commit
2de02374
authored
May 01, 2021
by
Andi Vajda
Browse files
added wrapper for LocaleMatcher.acceptLanguage()
parent
f7c51083
Changes
3
Hide whitespace changes
Inline
Side-by-side
common.cpp
View file @
2de02374
...
...
@@ -786,6 +786,46 @@ static UnicodeString *toUnicodeStringArray(PyObject *arg, int *len)
return
NULL
;
}
static
charsArg
*
toCharsArgArray
(
PyObject
*
arg
,
int
*
len
)
{
if
(
PySequence_Check
(
arg
))
{
*
len
=
(
int
)
PySequence_Size
(
arg
);
charsArg
*
array
=
new
charsArg
[
*
len
+
1
];
if
(
!
array
)
return
(
charsArg
*
)
PyErr_NoMemory
();
for
(
int
i
=
0
;
i
<
*
len
;
i
++
)
{
PyObject
*
obj
=
PySequence_GetItem
(
arg
,
i
);
if
(
PyUnicode_Check
(
obj
))
{
PyObject
*
bytes
=
PyUnicode_AsUTF8String
(
obj
);
if
(
bytes
==
NULL
)
{
Py_DECREF
(
obj
);
delete
[]
array
;
return
NULL
;
}
array
[
i
].
own
(
bytes
);
}
else
{
array
[
i
].
borrow
(
obj
);
}
Py_DECREF
(
obj
);
}
return
array
;
}
return
NULL
;
}
static
int
*
toIntArray
(
PyObject
*
arg
,
int
*
len
)
{
if
(
PySequence_Check
(
arg
))
...
...
@@ -1001,6 +1041,22 @@ int _parseArgs(PyObject **args, int count, const char *types, ...)
break
;
return
-
1
;
case
'm'
:
/* array of string or unicode, to utf8 charsArg */
if
(
PySequence_Check
(
arg
))
{
if
(
PySequence_Length
(
arg
)
>
0
)
{
PyObject
*
obj
=
PySequence_GetItem
(
arg
,
0
);
int
ok
=
PyBytes_Check
(
obj
)
||
PyUnicode_Check
(
obj
);
Py_DECREF
(
obj
);
if
(
ok
)
break
;
}
else
break
;
}
return
-
1
;
case
'T'
:
/* array of string, unicode or UnicodeString */
if
(
PySequence_Check
(
arg
))
{
...
...
@@ -1318,6 +1374,16 @@ int _parseArgs(PyObject **args, int count, const char *types, ...)
break
;
}
case
'm'
:
/* array of string or unicode, to utf8 charsArg */
{
charsArg
**
array
=
va_arg
(
list
,
charsArg
**
);
int
*
len
=
va_arg
(
list
,
int
*
);
*
array
=
toCharsArgArray
(
arg
,
len
);
if
(
!*
array
)
return
-
1
;
break
;
}
case
'T'
:
/* array of string, unicode or UnicodeString */
{
UnicodeString
**
array
=
va_arg
(
list
,
UnicodeString
**
);
...
...
locale.cpp
View file @
2de02374
...
...
@@ -514,6 +514,7 @@ static PyObject *t_localematcher_getBestMatchResult(t_localematcher *self, PyObj
static
PyObject
*
t_localematcher_isMatch
(
t_localematcher
*
self
,
PyObject
*
args
);
#endif
static
PyObject
*
t_localematcher_acceptLanguage
(
PyTypeObject
*
type
,
PyObject
*
args
);
static
PyObject
*
t_localematcher_acceptLanguageFromHTTP
(
PyTypeObject
*
type
,
PyObject
*
args
);
static
PyMethodDef
t_localematcher_methods
[]
=
{
...
...
@@ -523,6 +524,7 @@ static PyMethodDef t_localematcher_methods[] = {
#if U_ICU_VERSION_HEX >= VERSION_HEX(68, 0, 0)
DECLARE_METHOD
(
t_localematcher
,
isMatch
,
METH_VARARGS
),
#endif
DECLARE_METHOD
(
t_localematcher
,
acceptLanguage
,
METH_CLASS
|
METH_VARARGS
),
DECLARE_METHOD
(
t_localematcher
,
acceptLanguageFromHTTP
,
METH_CLASS
|
METH_VARARGS
),
{
NULL
,
NULL
,
0
,
NULL
}
};
...
...
@@ -2485,38 +2487,113 @@ static PyObject *t_localematcher_isMatch(t_localematcher *self, PyObject *args)
#endif // ICU >= 65
static
PyObject
*
t_localematcher_acceptLanguageFromHTTP
(
PyTypeObject
*
type
,
PyObject
*
args
)
static
PyObject
*
t_localematcher_acceptLanguage
(
PyTypeObject
*
type
,
PyObject
*
args
)
{
charsArg
*
accepts
=
NULL
,
*
locales
=
NULL
;
int
num_locales
=
0
,
num_accepts
=
0
;
switch
(
PyTuple_Size
(
args
))
{
case
2
:
if
(
!
parseArgs
(
args
,
"mm"
,
&
accepts
,
&
num_accepts
,
&
locales
,
&
num_locales
))
{
const
char
**
accept_buffers
=
(
const
char
**
)
calloc
(
num_accepts
,
sizeof
(
char
*
));
const
char
**
locale_buffers
=
(
const
char
**
)
calloc
(
num_locales
,
sizeof
(
char
*
));
if
(
!
accept_buffers
||
!
locale_buffers
)
{
free
(
locale_buffers
);
free
(
accept_buffers
);
delete
[]
locales
;
delete
[]
accepts
;
return
PyErr_NoMemory
();
}
for
(
int
i
=
0
;
i
<
num_accepts
;
++
i
)
accept_buffers
[
i
]
=
accepts
[
i
].
c_str
();
for
(
int
i
=
0
;
i
<
num_locales
;
++
i
)
locale_buffers
[
i
]
=
locales
[
i
].
c_str
();
UErrorCode
status
=
U_ZERO_ERROR
;
UEnumeration
*
uenum
=
uenum_openCharStringsEnumeration
(
locale_buffers
,
num_locales
,
&
status
);
if
(
U_FAILURE
(
status
))
{
free
(
locale_buffers
);
free
(
accept_buffers
);
delete
[]
locales
;
delete
[]
accepts
;
return
ICUException
(
status
).
reportError
();
}
else
status
=
U_ZERO_ERROR
;
UAcceptResult
result
;
char
buffer
[
128
];
size_t
size
=
uloc_acceptLanguage
(
buffer
,
sizeof
(
buffer
),
&
result
,
accept_buffers
,
num_accepts
,
uenum
,
&
status
);
uenum_close
(
uenum
);
free
(
locale_buffers
);
free
(
accept_buffers
);
delete
[]
locales
;
delete
[]
accepts
;
if
(
U_FAILURE
(
status
))
return
ICUException
(
status
).
reportError
();
if
(
size
>=
sizeof
(
buffer
))
{
PyErr_SetString
(
PyExc_ValueError
,
"resulting locale id length > 128"
);
return
NULL
;
}
return
Py_BuildValue
(
"(s#i)"
,
buffer
,
(
int
)
size
,
(
int
)
result
);
}
break
;
}
return
PyErr_SetArgsError
(
type
,
"acceptLanguageFromHTTP"
,
args
);
}
static
PyObject
*
t_localematcher_acceptLanguageFromHTTP
(
PyTypeObject
*
type
,
PyObject
*
args
)
{
charsArg
header_value
;
UnicodeStrin
g
*
locales
=
NULL
;
charsAr
g
*
locales
=
NULL
;
int
num_locales
=
0
;
switch
(
PyTuple_Size
(
args
))
{
case
2
:
if
(
!
parseArgs
(
args
,
"n
T
"
,
&
header_value
,
&
locales
,
&
num_locales
))
if
(
!
parseArgs
(
args
,
"n
m
"
,
&
header_value
,
&
locales
,
&
num_locales
))
{
const
UC
har
**
buffers
=
(
const
UC
har
**
)
calloc
(
num_locales
,
sizeof
(
UC
har
*
));
const
c
har
**
locale_
buffers
=
(
const
c
har
**
)
calloc
(
num_locales
,
sizeof
(
c
har
*
));
if
(
!
buffers
)
if
(
!
locale_
buffers
)
{
delete
[]
locales
;
return
PyErr_NoMemory
();
}
for
(
int
i
=
0
;
i
<
num_locales
;
++
i
)
buffers
[
i
]
=
locales
[
i
].
getTerminatedBuffe
r
();
locale_
buffers
[
i
]
=
locales
[
i
].
c_st
r
();
UErrorCode
status
=
U_ZERO_ERROR
;
UEnumeration
*
uenum
=
uenum_open
U
CharStringsEnumeration
(
buffers
,
num_locales
,
&
status
);
UEnumeration
*
uenum
=
uenum_openCharStringsEnumeration
(
locale_
buffers
,
num_locales
,
&
status
);
if
(
U_FAILURE
(
status
))
{
free
(
buffers
);
free
(
locale_
buffers
);
delete
[]
locales
;
return
ICUException
(
status
).
reportError
();
}
else
...
...
@@ -2529,16 +2606,16 @@ static PyObject *t_localematcher_acceptLanguageFromHTTP(
&
status
);
uenum_close
(
uenum
);
free
(
buffers
);
free
(
locale_
buffers
);
delete
[]
locales
;
if
(
size
>=
sizeof
(
buffer
)
||
U_FAILURE
(
status
))
{
if
(
U_FAILURE
(
status
))
return
ICUException
(
status
).
reportError
();
if
(
U_FAILURE
(
status
))
return
ICUException
(
status
).
reportError
();
PyErr_SetString
(
PyExc_ValueError
,
"resulting locale id length > 128"
);
if
(
size
>=
sizeof
(
buffer
))
{
PyErr_SetString
(
PyExc_ValueError
,
"resulting locale id length > 128"
);
return
NULL
;
}
...
...
test/test_LocaleMatcher.py
View file @
2de02374
...
...
@@ -59,20 +59,36 @@ class TestLocaleMatcher(TestCase):
self
.
assertEqual
(
Locale
(
'de-AT'
),
result
.
getDesiredLocale
())
self
.
assertEqual
(
Locale
.
getGermany
(),
result
.
getSupportedLocale
())
def
testAcceptLanguage
(
self
):
locale
,
status
=
LocaleMatcher
.
acceptLanguage
(
(
'fr-CH'
,
'fr'
,
'en'
,
'de'
,
'*'
),
(
'de-AT'
,
'fr-CA'
))
self
.
assertEqual
(
'fr_CA'
,
locale
)
self
.
assertEqual
(
UAcceptResult
.
FALLBACK
,
status
)
locale
,
status
=
LocaleMatcher
.
acceptLanguage
(
(
'fr-CH'
,
'fr'
,
'en'
,
'de'
,
'*'
),
list
(
Locale
.
getAvailableLocales
().
keys
()))
self
.
assertEqual
(
'fr_CH'
,
locale
)
self
.
assertEqual
(
UAcceptResult
.
VALID
,
status
)
def
testAcceptLanguageFromHTTP
(
self
):
locale
,
status
=
LocaleMatcher
.
acceptLanguageFromHTTP
(
"
fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5
"
,
(
"
de-AT
"
,
"
fr-CA
"
))
'
fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5
'
,
(
'
de-AT
'
,
'
fr-CA
'
))
self
.
assertEqual
(
"
fr_CA
"
,
locale
)
self
.
assertEqual
(
'
fr_CA
'
,
locale
)
self
.
assertEqual
(
UAcceptResult
.
FALLBACK
,
status
)
locale
,
status
=
LocaleMatcher
.
acceptLanguageFromHTTP
(
"
fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5
"
,
'
fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5
'
,
list
(
Locale
.
getAvailableLocales
().
keys
()))
self
.
assertEqual
(
"
fr_CH
"
,
locale
)
self
.
assertEqual
(
'
fr_CH
'
,
locale
)
self
.
assertEqual
(
UAcceptResult
.
VALID
,
status
)
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment