Skip to content

Commit 48dd8d5

Browse files
committed
Initial Public Release.
0 parents  commit 48dd8d5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+8895
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
*.o
2+
*.os
3+
*.so
4+
.sconsign.dblite
5+
test/rng_mt_test
6+
test/runif_geti_test
7+
test/runif_getf_test

CMakeLists.txt

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
3+
project(csnip
4+
VERSION 0.1
5+
LANGUAGES C
6+
)
7+
8+
### Check for C++
9+
include(CheckLanguage)
10+
check_language(CXX)
11+
if (CMAKE_CXX_COMPILER)
12+
set(has_cxx ON)
13+
else()
14+
set(has_cxx OFF)
15+
endif()
16+
option(BUILD_CXX_PIECES "Build C++ parts" ${has_cxx})
17+
if (BUILD_CXX_PIECES)
18+
enable_language(CXX)
19+
endif()
20+
21+
### Project-wide settings and compiler flags
22+
23+
#set(CMAKE_C_VISIBILITY_PRESET hidden)
24+
25+
if (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES CLANG)
26+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
27+
endif ()
28+
if (CMAKE_CXX_COMPILER_ID MATCHES GNU OR
29+
CMAKE_CXX_COMPILER_ID MATCHES CLANG)
30+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
31+
endif ()
32+
33+
### Dependencies
34+
option(BUILD_DOCS "Build documentation" ON)
35+
if (BUILD_DOCS)
36+
find_package(Doxygen REQUIRED)
37+
endif ()
38+
39+
### Testing
40+
41+
enable_testing()
42+
43+
#### Installation
44+
45+
include(GNUInstallDirs)
46+
set(INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}
47+
CACHE STRING "Relative installation directory for libraries")
48+
set(INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR}
49+
CACHE STRING "Relative installation directory for binaries")
50+
set(INSTALL_INCLUDEDIR
51+
${CMAKE_INSTALL_INCLUDEDIR}/csnip-${PROJECT_VERSION}
52+
CACHE STRING "Relative installation directory for headers")
53+
set(INSTALL_DOCDIR
54+
${CMAKE_INSTALL_DOCDIR}
55+
CACHE STRING "Relative installation directory for documentation")
56+
57+
#### Subdirectories
58+
59+
add_subdirectory(examples)
60+
add_subdirectory(in)
61+
add_subdirectory(src)
62+
add_subdirectory(test)
63+
64+
# doc/ comes last as Doxygen will need to know the complete other
65+
# targets.
66+
add_subdirectory(doc)
67+
68+
69+
### Packaging
70+
71+
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
72+
set(CPACK_PACKAGE_VENDOR "[email protected]")
73+
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "C snippet library")
74+
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
75+
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
76+
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
77+
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
78+
if(NOT DEFINED CPACK_SYSTEM_NAME)
79+
set(CPACK_SYSTEM_NAME ${CMAKE_SYSTEM_NAME})
80+
endif()
81+
set(CPACK_SOURCE_IGNORE_FILES ${PROJECT_BINARY_DIR} .git .gitignore)
82+
set(CPACK_SOURCE_GENERATOR "TGZ")
83+
set(CPACK_GENERATOR "TGZ")
84+
85+
include(CPack)

LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright 2018-2020 Lorenz Minder
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a
4+
copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included
12+
in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

doc/CMakeLists.txt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
function(get_target_sources retvar target_name)
2+
get_target_property(src_files ${target_name} SOURCES)
3+
get_target_property(src_dir ${target_name} SOURCE_DIR)
4+
set(ret "")
5+
foreach(src ${src_files})
6+
list(APPEND ret ${src_dir}/${src})
7+
endforeach()
8+
set(${retvar} ${ret} PARENT_SCOPE)
9+
endfunction()
10+
11+
function(add_docs_target)
12+
if(NOT BUILD_DOCS)
13+
return()
14+
endif()
15+
set(DOXYGEN_JAVADOC_AUTOBRIEF YES)
16+
set(DOXYGEN_MAX_INITIALIZER_LINES 3)
17+
set(DOXYGEN_REPEAT_BRIEF NO)
18+
set(DOXYGEN_EXAMPLE_PATH examples/)
19+
set(DOXYGEN_QUIET YES)
20+
21+
# Get the sources from the csnip library
22+
get_target_sources(src_csnip csnip)
23+
24+
# Figure out whether we can use a stamp file
25+
set(use_stamp "")
26+
if(CMAKE_MAJOR_VERSION GREATER 3 OR (CMAKE_MAJOR_VERSION GREATER_EQUAL 3
27+
AND CMAKE_MINOR_VERSION GREATER_EQUAL 16))
28+
set(use_stamp "USE_STAMP_FILE")
29+
endif()
30+
31+
doxygen_add_docs(docs
32+
${src_csnip}
33+
${CMAKE_CURRENT_SOURCE_DIR}/mainpage.md
34+
ALL
35+
${use_stamp}
36+
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
37+
)
38+
endfunction()
39+
40+
option(BUILD_DOCS "Build documentation" ON)
41+
add_docs_target()
42+
43+
# Installation
44+
if (BUILD_DOCS)
45+
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
46+
DESTINATION ${INSTALL_DOCDIR})
47+
endif ()

doc/mainpage.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Introduction {#mainpage}
2+
3+
## What is Csnip?
4+
5+
Csnip is a library of C code macros and functions (snippets, hence the
6+
name), that are frequently useful for general purpose C programming.
7+
It augments the standard C library with generic container data
8+
structures, such as dynamic arrays, lists, hash tables, and so on. It
9+
also provides high quality implementations of frequently used
10+
functionality such as for example random number generation.
11+
12+
In short, it provides functionality similar to C++'s standard template
13+
library for C programs.
14+
15+
## Csnip design goals
16+
17+
We strive to provide components that are:
18+
19+
- **Quality**. Csnip aims to provide higher quality algorithms and
20+
datastructures than what you would typically get if you implemented
21+
the same in an ad hoc fashion.
22+
23+
- **Transparency**. The implementation of csnip's datastructures is
24+
documented in addition to the interfaces. You may opt to modify them
25+
directly; and in some cases this can come in handy, say, if you want
26+
to do something that's not possible or easy with the official
27+
interfaces. For example, you can use direct access to sample a random
28+
entry from a hash set, or can read data from a file into a dynamic
29+
array that way.
30+
31+
In contrast, most other libraries are designed to be opaque, providing
32+
_data abstraction_ as a means to compartmentalize funcionality. In
33+
csnip, the same can be achieved with CSNIP\_\*\_{DECL,DEF}\_FUNCS()
34+
(see XXX), but it is entirely optional. It can be used when it makes
35+
sense, but avoided when it gets into the way.
36+
37+
- **General**. Csnip wants to be useful for as wide a class of users
38+
and environments as possible. A liberal license is used so it can be
39+
used in as many contexts as possible. We try to stay portable where
40+
this is possible, but to provide the extras for environments that have
41+
them. Thus, e.g., type generic macros via \_Generic are used for C11
42+
users along with non-generic versions for those which don't have that
43+
functionality available.
44+
45+
Csnip is generic, thus e.g. the sorting functions do not depend on the
46+
data type being sorted, or what type of random access container is
47+
used to store the elements.
48+
49+
We aim to design the library in a way that they can also be useful in
50+
uncommon use cases, provided that doesn't result in unduly burdening
51+
typical use cases.
52+
53+
- **Pragmatic**. Csnip strives to be pragmatic. For example, we like
54+
consistent interfaces, but if they get in the way of e.g. usability,
55+
we'll do something else. Csnip tries to be general in the definition
56+
of its datastructures and function, but not to the point of making
57+
them unnecessarily painful.
58+
59+
## Library conventions
60+
61+
### Notation
62+
63+
Csnip uses the prefixes csnip\_ or CSNIP\_ for its symbols and macros.
64+
Users should not define their own symbols or macros with such names.
65+
66+
Many functions or macros are grouped by functionality, e.g. things
67+
related to memory management are called csnip\_mem\_\*. Though some very
68+
frequently used functionality that does not nicely fit into a group is
69+
directly under csnip\_\*, without further grouping.
70+
71+
Macros that expand to statements or expression (_statement macros_ or
72+
_expression macros_) have upper CamelCase names; thus for example
73+
csnip\_arr\_Init() is a macro. Unless the behavior of the macro is
74+
documented for the case when the argument has side effects, the user is
75+
expected to use arguments without side effects, since the arguments may
76+
be evaluated more than once.
77+
78+
Macros and enumeration values that expand to constants are all-caps
79+
after the prefix, e.g. csnip\_err\_SUCCESS is such a constant.
80+
81+
Macros that evaluate to more than an expression or a statement are
82+
written in all-caps. Examples include macros that generate functions for
83+
container manipulation, such as CSNIP\_LPHASH\_TABLE\_DEF\_FUNCS().
84+
85+
Normal C functions and variables are written in snake case, for example
86+
csnip\_time\_timespec\_as\_float() is a function.
87+

examples/CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
set(samples_c
2+
clopts.c
3+
dlist.c
4+
getopt.c
5+
sort_cmdline.c
6+
)
7+
if (BUILD_CXX_PIECES)
8+
set(samples_cxx
9+
find.cc
10+
sort_perf.cc
11+
)
12+
else()
13+
set(samples_cxx)
14+
endif()
15+
16+
foreach(fn
17+
${samples_c}
18+
${samples_cxx}
19+
)
20+
get_filename_component(tgt "${fn}" NAME_WE)
21+
add_executable(${tgt} ${fn})
22+
target_link_libraries(${tgt} csnip)
23+
endforeach()

examples/clopts.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <stdio.h>
2+
3+
#define CSNIP_SHORT_NAMES
4+
#include <csnip/err.h>
5+
#include <csnip/clopts.h>
6+
7+
int main(int argc, char** argv)
8+
{
9+
clopts opts = {
10+
.description = "Testing tool for clopts library."
11+
};
12+
clopts_add_defaults(&opts);
13+
14+
/* Do the command line parsing */
15+
int i = 0;
16+
long l = 1;
17+
unsigned long ul = 2;
18+
const char* str = "unset";
19+
_Bool flag = 0;
20+
clopts_Addvar(&opts, 'i', "int", "int argument", &i, _);
21+
clopts_Addvar(&opts, 'l', "long", "long int argument", &l, _);
22+
clopts_Addvar(&opts, 'u', "ulong", "unsigned long argument", &ul, _);
23+
clopts_Addvar(&opts, 's', "string", "string argument", &str, _);
24+
clopts_Addflag(&opts, 'f', "flag", "flag", &flag, _);
25+
int err = clopts_process(&opts, argc - 1, argv + 1, NULL);
26+
if (err != 0) {
27+
printf("Error from clopts_process: %s\n", err_str(err));
28+
return 1;
29+
}
30+
31+
/* Display result */
32+
printf("Done with argument processing.\n");
33+
printf("Got i = %d, l = %ld, ul = %lu, str = \"%s\", flag = %s\n",
34+
i, l, ul, str, (flag ? "true" : "false"));
35+
36+
return 0;
37+
}

examples/dlist.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include <stdio.h>
2+
3+
#define CSNIP_SHORT_NAMES
4+
#include <csnip/mem.h>
5+
#include <csnip/list.h>
6+
#include <csnip/util.h>
7+
8+
struct Entry {
9+
const char* name;
10+
struct Entry *prev, *next;
11+
};
12+
13+
int main(void)
14+
{
15+
// Create an empty list:
16+
struct Entry *head, *tail;
17+
dlist_Init(head, tail, prev, next);
18+
19+
// Add some stuff to it
20+
const char* names_to_add[] = {
21+
"John", "David", "Michael", "Scott"
22+
};
23+
for (int i = 0; i < Static_len(names_to_add); ++i) {
24+
struct Entry* enew;
25+
mem_Alloc(1, enew, _);
26+
enew->name = names_to_add[i];
27+
28+
// Add the entry
29+
dlist_PushTail(head, tail, prev, next, enew);
30+
}
31+
32+
// Now read out backwards
33+
struct Entry* p = tail;
34+
while (p) {
35+
printf("%s\n", p->name);
36+
p = p->prev;
37+
}
38+
39+
return 0;
40+
}

examples/find.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <stdio.h>
2+
3+
#define CSNIP_SHORT_NAMES
4+
#include <csnip/find.h>
5+
#include <csnip/util.h>
6+
7+
int main()
8+
{
9+
int a[] = {0, 1, 2, 3, 4};
10+
const int N = Static_len(a);
11+
12+
/* Search with indices */
13+
for (int i = -1; i < N + 2; ++i) {
14+
int ret;
15+
Bsearch(int, u, a[u] < i, N, ret);
16+
printf("search for %d: index %d\n", i, (int)ret);
17+
}
18+
19+
/* Search for intermediate values */
20+
for (int i = -1; i < N + 1; ++i) {
21+
const float target = i + 0.5;
22+
int ret;
23+
Bsearch(int, u, a[u] < target, N, ret);
24+
printf("search for %g: index %d with value %d\n", target, ret,
25+
ret < N ? a[ret] : -999);
26+
}
27+
return 0;
28+
}

0 commit comments

Comments
 (0)