generated from par-tec/python-cookiecutter
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f4f1aab
commit 86dee1b
Showing
8 changed files
with
161 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -130,3 +130,7 @@ dmypy.json | |
|
||
# IDE | ||
.vscode/ | ||
|
||
# C | ||
*.o | ||
*.so |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
example |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,17 @@ | ||
CC=gcc | ||
CFLAGS=-fPIC -g | ||
CFLAGS=-fPIC -g -lc -lm -Wall | ||
|
||
all: example example.so | ||
all: example libexample.so | ||
|
||
example: example.o | ||
$(CC) -o example example.o $(CFLAGS) | ||
|
||
example.o: example.c | ||
$(CC) -c example.c $(CFLAGS) | ||
|
||
example.so: example.o | ||
$(CC) -shared -o example.so example.o | ||
libexample.so: example.o | ||
$(CC) -shared -o libexample.so example.o | ||
|
||
clean: | ||
rm -f example example.o example.so | ||
rm -f example example.o | ||
rm -f example example.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,46 @@ | ||
/** | ||
* A C file with a library function that appends a buffer to a linked list. | ||
* A C file with a library function with a simple parsing funciton | ||
* based on sscanf | ||
*/ | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#include <search.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
|
||
#include "example.h" | ||
|
||
struct person | ||
{ | ||
int id; | ||
char name[20]; | ||
} person; | ||
|
||
static element * | ||
new_element(void) | ||
int parse_person(char *line, struct person *p) | ||
{ | ||
element *e; | ||
int n; | ||
|
||
e = malloc(sizeof(*e)); | ||
if (e == NULL) | ||
// Beware! There is an error in the format string. | ||
// %s reads until the first whitespace character, so it won't work. | ||
n = sscanf(line, "%d;%19s", &p->id, p->name); | ||
if (n != 2) | ||
{ | ||
fprintf(stderr, "malloc() failed\n"); | ||
exit(EXIT_FAILURE); | ||
return -1; | ||
} | ||
|
||
return e; | ||
return 0; | ||
} | ||
|
||
|
||
|
||
element* append(queue *q, char *name) { | ||
element *elem, *prev; | ||
|
||
if (!q) return NULL; // Check if the queue pointer itself is NULL | ||
|
||
elem = new_element(); | ||
if (!elem) return NULL; // Check if memory allocation failed | ||
|
||
elem->name = name; // Assuming name is properly allocated and managed outside this function | ||
|
||
if (!*q) { | ||
// If the queue is empty, insert the new element at the beginning | ||
*q = elem; | ||
} else { | ||
// Find the last element in the queue | ||
for (prev = *q; prev->forward != NULL; prev = prev->forward) | ||
; | ||
// Insert the new element at the end of the queue | ||
} | ||
insque(elem, prev); | ||
|
||
return elem; | ||
} | ||
|
||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
element *first, *elem, *prev; | ||
queue *q = malloc(sizeof(queue)); | ||
|
||
elem = append(q, "1"); | ||
char line[] = "42;John Doe"; | ||
struct person p; | ||
|
||
|
||
printf("Traversing completed list:\n"); | ||
elem = first; | ||
do | ||
if (parse_person(line, &p) == 0) | ||
{ | ||
printf(" %s\n", elem->name); | ||
elem = elem->forward; | ||
} while (elem != NULL && elem != first); | ||
|
||
if (elem == first) | ||
printf("That was a circular list\n"); | ||
printf("ID: %d\n", p.id); | ||
printf("Name: %s\n", p.name); | ||
} | ||
else | ||
{ | ||
fprintf(stderr, "Parsing failed\n"); | ||
} | ||
|
||
exit(EXIT_SUCCESS); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1 @@ | ||
typedef struct element | ||
{ | ||
struct element *forward; | ||
struct element *backward; | ||
char *name; | ||
} element; | ||
|
||
typedef element* queue; | ||
int parse_person(char *line, struct person *p); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import ctypes | ||
from ctypes import Structure, byref, c_char, c_int, create_string_buffer | ||
from pathlib import Path | ||
|
||
# Load libraries. | ||
l_so = Path(__file__).parent.parent / "c-project" / "libexample.so" | ||
libc = ctypes.CDLL("libc.so.6") | ||
libexample = ctypes.CDLL(l_so) | ||
|
||
|
||
class Person(Structure): | ||
_fields_ = [("id", c_int), ("name", c_char * 20)] | ||
|
||
|
||
def test_parse_person(): | ||
p = Person() | ||
row = "1;John Dow" | ||
row_p = create_string_buffer(row.encode()) | ||
libexample.parse_person(row_p, byref(p)) | ||
assert p.id == 1 | ||
assert p.name == b"John Dow" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import ctypes | ||
import json | ||
from ctypes import * | ||
from ctypes import POINTER, Structure, c_int | ||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
# Load libraries. | ||
cJSON_so = Path(__file__).parent / "libcjson.so" | ||
libc = ctypes.CDLL("libc.so.6") | ||
libcjson = ctypes.CDLL(cJSON_so) | ||
|
||
|
||
# | ||
# Define cJSON struct in two steps to avoid circular references. | ||
# | ||
class cJSON(Structure): | ||
pass | ||
|
||
|
||
cJSON._fields_ = [ | ||
("next", POINTER(cJSON)), | ||
("prev", POINTER(cJSON)), | ||
("child", POINTER(cJSON)), | ||
("type", c_int), | ||
("valuestring", c_char_p), | ||
("valueint", c_int), | ||
("valuedouble", c_double), | ||
("string", c_char_p), | ||
] | ||
|
||
# | ||
# Associate a return type with cJSON_Parse. | ||
# | ||
cJSON_Parse = libcjson.cJSON_Parse | ||
cJSON_Parse.restype = ctypes.POINTER(cJSON) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"json_document, json_type, expected_values", | ||
[ | ||
(b"1", 1 << 3, 1), | ||
(b"1.1", 1 << 3, 1.1), | ||
(b"1e+2", 1 << 3, 100), | ||
(b"1_000", 1 << 3, 1.0), | ||
], | ||
) | ||
def test_cJSON_Parse_can_parse_numbers(json_document, json_type, expected_values): | ||
msg = ctypes.create_string_buffer(json_document) | ||
c_json = cJSON_Parse(msg) | ||
assert c_json.contents.type == json_type | ||
assert c_json.contents.valuedouble == expected_values | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"json_document, json_type, expected_values", | ||
[ | ||
(b'"ciao"', 1 << 4, b"ciao"), | ||
(json.dumps("però").encode(), 1 << 4, "però".encode()), | ||
], | ||
) | ||
def test_cJSON_Parse_can_parse_strings(json_document, json_type, expected_values): | ||
msg = ctypes.create_string_buffer(json_document) | ||
c_json = cJSON_Parse(msg) | ||
assert c_json.contents.type == json_type | ||
assert c_json.contents.valuestring == expected_values | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"json_document, json_type, expected_values", | ||
[ | ||
(b"[1,2,3]", 1 << 5, [1, 2, 3]), | ||
], | ||
) | ||
def test_cJSON_Parse_can_parse_arrays(json_document, json_type, expected_values): | ||
msg = ctypes.create_string_buffer(json_document) | ||
c_json = cJSON_Parse(msg) | ||
assert c_json.contents.type == json_type | ||
|
||
e = c_json.contents.child.contents | ||
for expected_value in expected_values: | ||
assert e.valueint == expected_value | ||
try: | ||
e = e.next.contents | ||
except ValueError: | ||
assert expected_value == expected_values[-1] | ||
break | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"json_document, json_type, expected_values", | ||
[ | ||
(b'{"a": 1', None, None), | ||
], | ||
) | ||
def test_cJSON_Parse_raises_when_invalid_json( | ||
json_document, json_type, expected_values | ||
): | ||
msg = ctypes.create_string_buffer(json_document) | ||
c_json = cJSON_Parse(msg) | ||
with pytest.raises(ValueError): | ||
assert c_json.contents |