wolkykim / qlibc Goto Github PK
View Code? Open in Web Editor NEWqLibc is a simple and yet powerful C library providing generic data structures and algorithms.
Home Page: http://wolkykim.github.io/qlibc
License: Other
qLibc is a simple and yet powerful C library providing generic data structures and algorithms.
Home Page: http://wolkykim.github.io/qlibc
License: Other
I'm getting some errors regarding the types ssize_t
and off_t
when including utilities/qhash.h
in Ubuntu + gcc. Shouldn't the #include <sys/types.h>
present in src/utilities/qhash.c
be in the corresponding .h? It fixes the problem...
It also occurs in other files. Following is the output of running grep "sys/types.h" -R include/ src/
:
src/extensions/qhttpclient.c:#include <sys/types.h>
src/utilities/qfile.c:#include <sys/types.h>
src/utilities/qcount.c:#include <sys/types.h>
src/utilities/qhash.c:#include <sys/types.h>
src/internal/md5/md5c.c:#include <sys/types.h>
Hi
How would I go about using this library in my c99 code?
I didn't see any section in then docs on installing it, so could use the help.
I tried make
, but make didn't have any target.
So then I created a build dir in the project root and the did cd build
and cmake ..
This errored out however, as I apparantly do not have pthreads.
It will be good to have a section on installing qlibc and its dependencies on each platform.
Please join us, we need your help on writing unit tests.
If this is something that interests you, please refer /tests/README.md file for more details.
Thank you.
Hello, there. qlibc
is awesome. I am sadly, currently in a pickle: I can't execute the object file created upon successful compilation of a C file containing qhttpclient
code. The linker flags -lqlibc -lqlibcext -lssl -lcrypto -pthread
work only during compilation, but attempting to run the object file created from the linkage produces the message:
./[file]: error while loading shared libraries: ../lib/libqlibc.so.2: cannot open shared object file: No such file or directory
Any help would be appreciated.
line81-86 can be modified to:
* obj = queue->pop(queue, NULL);
* printf("pop(): %s\n", (char*)obj);
* free(obj);
* obj = queue->pop(queue, NULL);
* printf("pop(): %s\n", (char*)obj);
* free(obj);
In my opinion, I think qvector needs to be implemented based on array, and provide get methods to access element by index.
Hello
A few months ago I developed a wrapper for some of qlibc containers to be called from Fortran language (here). Thanks to the developers of qlibc!
Recently one of the user, frazar, performed tests with qtreetbl container. He found, that an invariant 4 "If a node is red, then both its children are black." (Wikipedia) is broken in his test case. Original message of frazar can be found here. I repeated the same test with qlibc in my fork.
Does the rule "If a node is red, then both its children are black" should be always enforced in the realized algorithm?
After running configure, some files appear in the repo to be modified but without any actual difference in a git diff. It is strange because these files appear as "Untracked", but they existed in the repo right after pulling - for example, Makefile. Additionally, even after running make clean
these files are still modified.
What is the suggested method of keeping the repo clean for committing changes upstream for a pull request?
➜ qlibc git:(master) ✗ git st
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
Makefile
config.h
config.log
config.status
examples/Makefile
src/Makefile
tests/Makefile
I'm so excited to tell everyone that we're going to add a new container in tree data structure.
That has been wanted for long time. This implementation takes left-leaning red-black BST algorithm and fully written from ground up.
The implementation adds some useful addition algorithm tune ups such as iteration over LLRB tree and find_nearest_key.
The code might be little rough but I'd like ask your review and feedback and I'll keep working on code polishing.
Thank you all.
I've been trying to use your excellent library for repeated HTTPS requests, and have found that if I free and reallocate a client object, then subsequent operations quietly fail.
Having dug through the code I think the issue is to do with the setssl method, where the second time round, the initialized flag stops a ssl object being allocated on the client object.
I've fixed as below in my code and it seems to work fine.
Given that to date I believe you're the only person that has touched the code I thought I'd raise this issue rather than fixing directly, but feel free to let me know otherwise.
Once again, thanks for the excellent library.
Cheers,
Colin.
static bool setssl(qhttpclient_t *client) {
static bool initialized = false;
if (client->socket >= 0) {
// must be set before making a connection.
return false;
}
if (client->ssl != NULL) {
// already initialized.
return true;
}
// init openssl
if (initialized == false)
{
initialized = true;
SSL_load_error_strings();
SSL_library_init();
}
// allocate ssl structure
client->ssl = malloc(sizeof(struct SslConn));
if (client->ssl == NULL) return false;
memset(client->ssl, 0, sizeof(struct SslConn));
return true;
return false;
}
#include "qlibc.h"
int main(int argc, char *argv[]) {
char* str = "JW";
qurl_decode(str);
return(0);
}
This produces a segfault when run. The function definition says it will return NULL if there is any problem but only a check for str == NULL is being performed. I have not taken the time to fully understand the problem happening here, in the hopes someone more familiar with this could take a look and do a proper fix.
Valgrind shows this:
==6515== Memcheck, a memory error detector
==6515== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6515== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==6515== Command: ./ex
==6515==
==6515==
==6515== Process terminating with default action of signal 11 (SIGSEGV)
==6515== Bad permissions for mapped region at address 0x111004
==6515== at 0x10A7EF: qurl_decode (qencode.c:210)
==6515== by 0x10A7EF: qurl_decode (qencode.c:192)
==6515== by 0x10A43F: main (ex.c:7)
==6515==
==6515== HEAP SUMMARY:
==6515== in use at exit: 0 bytes in 0 blocks
==6515== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==6515==
==6515== All heap blocks were freed -- no leaks are possible
==6515==
==6515== For counts of detected and suppressed errors, rerun with: -v
==6515== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
The file extensions/qtokenbucket.h is missing from the install instructions in src/Makefile.in
From qhashtbl.c:
qhashtbl implements a hash table, which maps keys to values. Key is a unique string and ...
Does it mean for instance, that a hash table with int keys is not supported?
Hi there! I've been contributing to the project. Seeing that this project is using CMake.
I think this could be better if qlibc implements Meson and Ninja for better project configuration and build.
The expected behaviour of a vector is:
a) O(1) random element access and append.
b) O(n) iteration, element removal, and element insertion
c) Specify capacity
b) sequential layout in memory.
If qlibc is targeting C99, then it could use a flexible array member to keep the vector size info together with
the array.
I would like to point out that identifiers like "_QLIBC_H
" and "_QLIST_H
" do eventually not fit to the expected naming convention of the C language standard.
Would you like to adjust your selection for unique names?
I modified examples/hashtbl.c as follows:
qhashtbl_t *tbl = qhashtbl(0, 0);
which then crashes with:
allan@vent:~/src/qlibc/examples$ ./hashtbl
*** Error in `./hashtbl': double free or corruption (top): 0x00000000015010b0 ***
Aborted
What am I missing?
qlibc is a great job, and I'm writing a library https://github.com/gozfree/gear-lib similar with qlibc
#include "qlibc.h"
int main(int argc, char *argv[]) {
char* str = "JW";
qhex_decode(str);
return(0);
}
This program segfaults when run. The function definition says it will return NULL if there is any problem but I do not see any checks being done. Would it be enough to check if the characters are in the valid set of characters for this function? [0-9][a-f][A-F] or something similar.
Valgrind shows this:
==6475== Memcheck, a memory error detector
==6475== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6475== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==6475== Command: ./ex
==6475==
==6475==
==6475== Process terminating with default action of signal 11 (SIGSEGV)
==6475== Bad permissions for mapped region at address 0x111004
==6475== at 0x10AE58: qhex_decode (qencode.c:448)
==6475== by 0x10A43F: main (ex.c:6)
==6475==
==6475== HEAP SUMMARY:
==6475== in use at exit: 0 bytes in 0 blocks
==6475== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==6475==
==6475== All heap blocks were freed -- no leaks are possible
==6475==
==6475== For counts of detected and suppressed errors, rerun with: -v
==6475== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
make test will fail when qlibc is compiled with gcc >= 10.
Under this case, test_qtreetbl.c will compile but will segfault during execution.
I believe that it is caused by the unused return true;
of drawtree().
test_qtreetbl_gcc10.txt
test_qtreetbl_gcc11.txt
test_qtreetbl_gcc12.txt
hostname or destname?????
qhttpclient_t *qhttpclient(const char *destname, int port) {
bool ishttps = false;
char hostname[256];
if (port == 0 || strstr(hostname, "://") != NULL) { // hostname or destname?????
if (_parse_uri(destname, &ishttps, hostname, sizeof(hostname), &port)
== false) {
DEBUG("Can't parse URI %s", destname);
return NULL;
}
DEBUG("https: %d, hostname: %s, port:%d\n", ishttps, hostname, port);
} else {
qstrcpy(hostname, sizeof(hostname), destname);
}
ut_qrbtree(134)-> "put: 40\n"
(BLK:40)
| |---L(BLK, null)
| |---R(BLK, null)
ut_qrbtree(134)-> "put: 30\n"
(BLK:40)
| |---L(RED:30)
| | |---L(BLK, null)
| | |---R(BLK, null)
| |---R(BLK, null)
ut_qrbtree(134)-> "put: 20\n"
(BLK:30)
| |---L(RED:20)
| | |---L(BLK, null)
| | |---R(BLK, null)
| |---R(RED:40) -- right lean red node.
| | |---L(BLK, null)
| | |---R(BLK, null)
test code:
`TESTCASE(rbtree, ut_qrbtree)
{
int i;
int data[] = {
40, 30, 20, 50, 60, 55, 4, 24, 80, 33, 44, 11
};
int size = ARRAY_CNT(data);
qtreetbl_t *qtree = qtreetbl(0);
qtree->set_compare(qtree, qtree_cmp);
for (i = 0; i < ARRAY_CNT(data); i++) {
LOG_DEBUG("put: %d\n", data[i]);
qtree->put_by_obj(qtree, &data[i], sizeof(int), &data[i], sizeof(int));
print_qrbtree(qtree->root, 0, 0);
}
{
for (i = 0; i < size; i++) {
LOG_DEBUG("delete-inorder:%d", data[i]);
qtree->remove_by_obj(qtree, &data[i], sizeof(int));
print_qrbtree(qtree->root, 0, 0);
}
}
qtree->free(qtree);
return 0;
}
`
Firstly, I apologize if this is something on my own side (it probably is) - I am not super familiar with CMake, as I normally utilize plain old make.
When attempting to run make
on Mac OSX/Darwin, I receive an error about -soname flag. I do have gcc installed, and it appears that the generated Makefiles are properly instructed to use gcc (not clang) - however, this error does appear to be clang related (see below). My system info:
➜ qlibc git:(master) ✗ uname -a
Darwin MacBook-Air.local 12.5.0 Darwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64 x86_64
➜ qlibc git:(master) ✗ cmake --version
cmake version 3.1.1
➜ qlibc git:(master) ✗ gcc -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix
./configure
was run succesfully, but here is the config.log if it's any help.
The specific output of make
is below, with the error at the very bottom:
➜ qlibc git:(master) ✗ make
===> src
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o containers/qlist.o containers/qlist.c
containers/qlist.c:873:5: warning: if statement has empty body [-Wempty-body]
Q_MUTEX_DESTROY(list->qmutex);
^
./internal/qinternal.h:121:68: note: expanded from macro 'Q_MUTEX_DESTROY'
if(x->count != 0) DEBUG("Q_MUTEX: mutex counter is not 0."); \
^
containers/qlist.c:873:5: note: put the semicolon on a separate line to silence this warning
./internal/qinternal.h:121:68: note: expanded from macro 'Q_MUTEX_DESTROY'
if(x->count != 0) DEBUG("Q_MUTEX: mutex counter is not 0."); \
^
1 warning generated.
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o containers/qlisttbl.o containers/qlisttbl.c
containers/qlisttbl.c:1072:5: warning: if statement has empty body [-Wempty-body]
Q_MUTEX_DESTROY(tbl->qmutex);
^
./internal/qinternal.h:121:68: note: expanded from macro 'Q_MUTEX_DESTROY'
if(x->count != 0) DEBUG("Q_MUTEX: mutex counter is not 0."); \
^
containers/qlisttbl.c:1072:5: note: put the semicolon on a separate line to silence this warning
./internal/qinternal.h:121:68: note: expanded from macro 'Q_MUTEX_DESTROY'
if(x->count != 0) DEBUG("Q_MUTEX: mutex counter is not 0."); \
^
1 warning generated.
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o containers/qhashtbl.o containers/qhashtbl.c
containers/qhashtbl.c:757:5: warning: if statement has empty body [-Wempty-body]
Q_MUTEX_DESTROY(tbl->qmutex);
^
./internal/qinternal.h:121:68: note: expanded from macro 'Q_MUTEX_DESTROY'
if(x->count != 0) DEBUG("Q_MUTEX: mutex counter is not 0."); \
^
containers/qhashtbl.c:757:5: note: put the semicolon on a separate line to silence this warning
./internal/qinternal.h:121:68: note: expanded from macro 'Q_MUTEX_DESTROY'
if(x->count != 0) DEBUG("Q_MUTEX: mutex counter is not 0."); \
^
1 warning generated.
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o containers/qhasharr.o containers/qhasharr.c
containers/qhasharr.c:758:22: warning: unused variable 'data' [-Wunused-variable]
qhasharr_data_t *data = tbl->data;
^
containers/qhasharr.c:911:22: warning: unused variable 'data' [-Wunused-variable]
qhasharr_data_t *data = tbl->data;
^
2 warnings generated.
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o containers/qvector.o containers/qvector.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o containers/qqueue.o containers/qqueue.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o containers/qstack.o containers/qstack.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o utilities/qcount.o utilities/qcount.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o utilities/qencode.o utilities/qencode.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o utilities/qfile.o utilities/qfile.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o utilities/qhash.o utilities/qhash.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o utilities/qio.o utilities/qio.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o utilities/qsocket.o utilities/qsocket.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o utilities/qstring.o utilities/qstring.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o utilities/qsystem.o utilities/qsystem.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o utilities/qtime.o utilities/qtime.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o ipc/qsem.o ipc/qsem.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o ipc/qshm.o ipc/qshm.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o internal/qinternal.o internal/qinternal.c
gcc -Wall -Wstrict-prototypes -fPIC -g -O2 -I/usr/include -I/usr/local/include -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I../include/qlibc -I./internal -c -o internal/md5/md5c.o internal/md5/md5c.c
/usr/bin/ar -rc ../lib/libqlibc.a containers/qlist.o containers/qlisttbl.o containers/qhashtbl.o containers/qhasharr.o containers/qvector.o containers/qqueue.o containers/qstack.o utilities/qcount.o utilities/qencode.o utilities/qfile.o utilities/qhash.o utilities/qio.o utilities/qsocket.o utilities/qstring.o utilities/qsystem.o utilities/qtime.o ipc/qsem.o ipc/qshm.o internal/qinternal.o internal/md5/md5c.o
ranlib ../lib/libqlibc.a
gcc -shared -Wl,-soname,libqlibc.so.2 -o ../lib/libqlibc.so.2 containers/qlist.o containers/qlisttbl.o containers/qhashtbl.o containers/qhasharr.o containers/qvector.o containers/qqueue.o containers/qstack.o utilities/qcount.o utilities/qencode.o utilities/qfile.o utilities/qhash.o utilities/qio.o utilities/qsocket.o utilities/qstring.o utilities/qsystem.o utilities/qtime.o ipc/qsem.o ipc/qshm.o internal/qinternal.o internal/md5/md5c.o
ld: unknown option: -soname
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [qlibc] Error 1
<=== src
An issue reported on StackOverflow suggests that Mac OSX should use -install_name instead of -soname, but I am not sure how to instruct CMake of this.
Any ideas about this one? Thanks!
Calling qhashmd5_file(myfile, 0, 0, buf) will result in an initialized MD5 context and an incorrect hash returned to the caller.
When nbytes is set to zero, the for loop never executes skipping all read() and MD5Update() calls.
Qlibc is a fantastic C library, thanks for creating this project!
It's always my great pleasure to know how it gets used.
Please leave your comment if you're using qlibc.
And any change, giving a Star to the project helps!
Many thanks.
It doesn't use standard C headers but relying on platform specific headers too much. This would work on posix systems but on Windows it's problematic. For example, on mingw64 there is no such header as <sys/sem.h>. It also uses <sys/types.h> that causes problem on mingw64 because on mingw64 there is no such thing as u_int32_t defined. There are ifdefs on source code to check for _WIN32 but I don't think it could build out of the box with MSVC either. This library shouldn't be used if you want something truly portable. There are much better solutions: https://github.com/oz123/awesome-c#frameworks
Um, I've just cloned and built this library and I can see there is a doc
directory and that it contains html
pages but that these are not installed outside of the source tree. I am intending to use this for a INI config file reader/writer provided by the Extension API on a Raspberry Pi (for a Home Automation Project) that I am SSH
ing into and I'm not using a GUI so I'd be looking to use man
(or the GNU preferred documentation info
system) to browse the reference documentation.
Is it intended to expand the documentation into other formats or to install the information into a known location? 😀
pthreads
is required, so I use pthreads for Windows instead. It seems CMakeLists.txt does not work well with find.MESSAGE(FATAL_ERROR "Couldn't find pthreads.")
, then build process will be fail. One of the error messages come withE:\DemoProjects\qlibc\src\internal\qinternal.h(64): fatal error C1083: Cannot open include file: 'unist d.h': No such file or directory [E:\DemoProjects\qlibc\build\qlibcext-static.vcxproj]
It seems some POSIX interfaces are required. Does it mean Windows not supported? Thansk!
[XXX@vagrant-centos64 qlibc]# git branch unit_test
[XXX@vagrant-centos64 qlibc]# git checkout unit_test
M src/qlibc_eclipse_formatter.xml
Switched to branch 'unit_test'
As shown above, when I created a new branch unit_test
and checkout it, the file src/qlibc_eclipse_formatter.xml
will be automatically modified. How can I resolve this problem?
Is there anyone interested in updating INSTALL.md with information about using CMake on Windows/Mac/Linux for those who are not familiar with it?
The .io site says:
All of the deliverable code in qLibc has been dedicated to the public domain by the authors
However, the readme lists a more restrictive two-clause licence, and refers to the LICENCE file which is a traditional BSD-style licence.
Since the source files themselves also contain the same copyright notice and BSD-style licence, I guess that's the one that was intended to apply. That would mean that the project is not in the public domain, and the .io description is inaccurate.
I think it's all of our contributors pleasure seeing the number of star increases~ That pays off the efforts we're putting into this project. It's a great day~
When can we publish next release? I want to integrate the official release to my project.
Because I need the remove_by_idx() API of the changes since 2.2.0.
In function qlist_getnext
, the following lines:
if (obj == NULL)
return NULL;
The return type of qlist_getnext
is bool
, so the return line needs to be changed to:
if (obj == NULL)
return false;
like B+Tree bloomfilter and so on
I'm thinking about using qunit.h for floating-point calculations.
What do you think about assertion like this
#define ASSERT_EQUAL_FLOAT_TOL(p1, p2, tol) ASSERT( (p1<p2 ? p2-p1 : p1-p2) < tol )
that can be used in tests:
TEST("Compare floats") {
float f1 = 1.000000;
float f2 = 1.000001;
ASSERT_EQUAL_FLOAT_TOL(f1, f2, 1.0e-7); // should fail
ASSERT_EQUAL_FLOAT_TOL(f1, f2, 1.0e-6); // who knows???
ASSERT_EQUAL_FLOAT_TOL(f1, f2, 1.0e-5); // should pass
}
I use it to replace space in a exec string and it fails. The string was something like "/home/user/test/project/progs/cprogs/this is.sh" and the function destroys the string. If I use the function for "this is.sh" everything is right. I try to replace the " " with "\ " to escape the space for exec.
When I compile and install qlibc, the following files are not ignored to be tracked.
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# ../lib/libqlibc.so
# ../lib/libqlibc.so.2
# ../lib/libqlibcext.so
# ../lib/libqlibcext.so.2
# test_qhasharr
# test_qhasharr_darkdh
# test_qhashtbl
# test_qstring
# test_qtreetbl
nothing added to commit but untracked files present (use "git add" to track)
Hi,
I think I found a small bug in qvector container in function qvector_resize().
If the argument 'newmax' is smaller than the current size of container 'num', then the 'num' should be changed to 'newmax' too. I think the code should be added after 768 line:
if (vector->num > newmax) {
vector->num = newmax;
}
It's in qfile.c and I'm on MSYS2 with cmake and ninja. Compiler is mingw-w64-x86_64-gcc. POSIX mkdir takes two arguments but Windows' mkdir only take just one. It seems your library doesn't support Windows, isn't it?
There's an interesting conversation going on about qLibc. I left below comments at the forum. I'm copying it here for those who might have similar questions.
The full conversation can be seen at here
Hi,
I'm the author of qLibc. One of our contributors let me know this interesting conversation is going on here. I've read all thoroughly and I consider all the comments here are so helpful and valuable. Thank you for all the inputs. I will use your input for the future improvements. Just wanted to leave my takeouts and current plan on your suggestions and comments.
In the history, the many parts of qLibc code has delivered from the successor project of qDecoder. qDecoder is a C library for Common Gateway Interface(CGI). Around 2010, one of qDecoder fan suggested to break the project into 2 parts and maintain the general codes in a separate project. I took the advice then qLibc was born like that. There's qHttpd project which was also departed from qDecoder project. So I gave qLibc a sibling mark of alphabet Q :) I was little concerning about the look similarity between qlibc and glibc in lower case writings. But it just went like that and I like the name. So alphabet Q happened to get a meaning to me. I guess now you all like the name like I do ? Still no? Oh man! I'm sad then...
I think the principals are different. To me glib is like Home Depot. qLibc is like Ace Hardware Store or Radio Shark. qLibc takes practical needs. For an example,
Personally, I say personally, sticking on traditional C coding standard gives pros and cons. With traditional style, your code can be more widely ported with minimum efforts. If I were working on glib, I'd stick to it. For qLibc? I've choose to take the advantages. Using pointer member concept is one of them. Integer type could replace boolean type, or char type could be used for it, but to me it is not obvious not to use boolean type since most of recent dev environments can handle them. C99 makes code more readable, less buggy and I think it helps making the code easier to maintain.
The project is open to suggestions and looking for better ways all the times. Your interests feeds the project and drives the projects. So drop it a line at the project home if you have any ideas or suggestions. The spirit of open source.
Thank you again for all your interests and valuable comments/suggestions.
Seungyoung “Steve” Kim
For those, who's interested in to see the performance diff between encapsulation call VS direct call.
Test qtreetbl.c
======================================================================
* TEST : Test growth of tree
E
C `````````````````````````````````` R
B ```````````````` D N ```````````````` X
[A]```````` ```````` [I]```````` [S]````````
```` ```` ````
Tree Info : #nodes=10, #red=3, #black=-7, root=E
.................... OK (20 assertions, 80us)
* TEST : Test basic but complete .............................. OK (33 assertions, 9us)
* TEST : Test encapsulated call perf - 1,000,000,000 times OK (0 assertions, 1592006us)
* TEST : Test direct call perf - 1,000,000,000 times OK (0 assertions, 1557411us)
Here the test code:
TEST("Test encapsulated call perf - 1,000,000,000 times") {
qtreetbl_t *tbl = qtreetbl(0);
long i;
for (i = 0; i < 1000000000; i++) {
tbl->size(tbl);
}
tbl->free(tbl);
}
TEST("Test direct call perf - 1,000,000,000 times") {
qtreetbl_t *tbl = qtreetbl(0);
long i;
for (i = 0; i < 1000000000; i++) {
qtreetbl_size(tbl);
}
tbl->free(tbl);
}
My dev box has Intel(R) Core(TM) i5-4430 CPU @ 3.00GHz
Hello, I encounter a segmentation fault in qhashtbl_lock (which is called by qhashtbl_getnext) where I have multiple threads call this function.
I suspect the problem is due to the following code in qinternal.h:
#define Q_MUTEX_ENTER(m) do { \
if(m == NULL) break; \
while(true) { \
int _ret, i; \
for(i = 0; (_ret = pthread_mutex_trylock(&(((qmutex_t *)m)->mutex))) != 0 \
&& i < MAX_MUTEX_LOCK_WAIT; i++) { \
if(i == 0) { \
DEBUG("Q_MUTEX: mutex is already locked - retrying"); \
} \
usleep(1); \
} \
if(_ret == 0) break; \
DEBUG("Q_MUTEX: can't get lock - force to unlock. [%d]", \
_ret); \
Q_MUTEX_LEAVE(m); \
} \
((qmutex_t *)m)->count++; \
((qmutex_t *)m)->owner = pthread_self(); \
} while(0)
In this code, the mutex that is locked by another thread is unlocked after trying MAX_MUTEX_LOCK_WAIT times.
However, is it safe to unlock a mutex lock that is locked by another thread ?
Someone pointed it out in the Reddit thread; see here for more info. Basically, it's very bad.
It really sucks. I've been doing this for a while and had no idea...
An extra null pointer check is not needed in functions like the following.
Would you like to apply the following semantic patch to find more update candidates?
@Remove_unnecessary_pointer_checks@
expression x;
@@
-if (x)
free(x);
I think there may be an issue in the clear
function in qvector_t
(using C11) starting with the line:
free(vector->data);
I ran into this when using the library (which has been super valuable and useful, thank you!) and I tested it in isolation with this program (lines packed for brevity):
#include <stdio.h>
#include <qlibc/qlibc.h>
void succeeds() {
printf("\nsucceeds:\n");
qvector_t *vec = qvector(10, sizeof(uint64_t), QVECTOR_RESIZE_DOUBLE);
uint64_t a = 1, b = 2, c = 3, d = 4, e = 5;
printf("addlast: &a"); vec->addlast(vec, &a);
printf(", &b"); vec->addlast(vec, &b);
printf(", &c"); vec->addlast(vec, &c);
printf(", &d"); vec->addlast(vec, &d);
printf(", &e"); vec->addlast(vec, &e);
printf(", size=%zu\n", vec->size(vec));
printf("remove all"); while (vec->size(vec) != 0) { vec->removelast(vec); }
printf(", size=%zu\n", vec->size(vec));
printf("addlast: &a"); vec->addlast(vec, &a);
printf(", &b"); vec->addlast(vec, &b);
printf(", &c"); vec->addlast(vec, &c);
printf(", &d"); vec->addlast(vec, &d);
printf(", &e"); vec->addlast(vec, &e);
printf(", size=%zu\n", vec->size(vec));
vec->free(vec);
}
void fails_with_double_free() {
printf("\nfails_with_double_free:\n");
qvector_t *vec = qvector(10, sizeof(uint64_t), QVECTOR_RESIZE_DOUBLE);
uint64_t a = 1, b = 2, c = 3, d = 4, e = 5;
printf("addlast: &a"); vec->addlast(vec, &a);
printf(", &b"); vec->addlast(vec, &b);
printf(", &c"); vec->addlast(vec, &c);
printf(", &d"); vec->addlast(vec, &d);
printf(", &e"); vec->addlast(vec, &e);
printf(", size=%zu\n", vec->size(vec));
printf("clear"); vec->clear(vec);
printf(", size=%zu\n", vec->size(vec));
printf("addlast: &a"); vec->addlast(vec, &a);
printf(", &b"); vec->addlast(vec, &b);
printf(", &c"); vec->addlast(vec, &c);
printf(", &d"); vec->addlast(vec, &d);
printf(", &e"); vec->addlast(vec, &e);
printf(", size=%zu\n", vec->size(vec));
vec->free(vec);
}
void also_fails_with_double_free() {
printf("\nalso_fails_with_double_free:\n");
qvector_t *vec = qvector(10, sizeof(uint64_t), QVECTOR_RESIZE_DOUBLE);
uint64_t a = 1, b = 2, c = 3, d = 4, e = 5;
printf("clear"); vec->clear(vec);
printf(", size=%zu\n", vec->size(vec));
printf("addlast: &a"); vec->addlast(vec, &a);
printf(", &b"); vec->addlast(vec, &b);
printf(", &c"); vec->addlast(vec, &c);
printf(", &d"); vec->addlast(vec, &d);
printf(", &e"); vec->addlast(vec, &e);
printf(", size=%zu\n", vec->size(vec));
vec->free(vec);
}
int main(int argc, char *argv[]) {
setbuf(stdout, NULL);
succeeds();
fails_with_double_free();
//also_fails_with_double_free();
return 0;
}
Output:
succeeds:
addlast: &a, &b, &c, &d, &e, size=5
remove all, size=0
addlast: &a, &b, &c, &d, &e, size=5
fails_with_double_free:
addlast: &a, &b, &c, &d, &e, size=5
clear, size=0
addlast: &a, &b, &c, &dfree(): double free detected in tcache 2
Process finished with exit code 134
Other output:
also_fails_with_double_free:
clear, size=0
addlast: &a, &b, &c, &dfree(): double free detected in tcache 2
I'm statically linking to qlibc and using gcc version:
gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)
Does this look like an issue or am I doing something wrong? My workaround for now is to wrap "remove all" into a function; this will work fine for me since my use case isn't speed-critical.
Hello,
I was using American Fuzzy Lop (afl-fuzz) to fuzz the input to the examples/config
program. It uses the qconfig_parse_file() function that crashes the program if provided certain input. Is fixing these crashes something you're interested in? The input files can be found here: https://github.com/rwhitworth/qlibc-fuzz/
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.