[HN Gopher] ZPL: (Almost) C99 Powerkit
___________________________________________________________________
ZPL: (Almost) C99 Powerkit
Author : up2isomorphism
Score : 60 points
Date : 2021-03-20 13:47 UTC (9 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| jart wrote:
| It looks like ZPL has its own memcpy() implementation which is a
| work in progress. Assuming the author posted this as a Show HN
| kind of thread, here's some feedback I could offer based on my
| experience implementing that function.
|
| It goes pretty quick on the machines I've used so far to have an
| indirect branch with overlapping moves. Here's what that looks
| like in "pure c" for gcc and clang.
| https://github.com/jart/cosmopolitan/blob/master/libc/str/me...
| memcpy is hard to implement in pure c99 because aliasing pointers
| to non-char types can trigger ubsan errors. With rep movsb it's a
| good idea to check cpuid for erms support. In that case it'll be
| fastest for bigger moves but is still slower for small moves. See
| the chart at https://justine.lol/cosmopolitan/index.html which
| compares various methods. Also take into consideration that if
| you call zpl_memcpy() the compiler doesn't know that's memcpy()
| so it can't perform some of its inlining magic at the call site.
| So if you want things like null propagation it might be better to
| do that as a macro.
|
| Regarding array.c I implemented a bunch of similar routines
| myself and eventually chose to not worry about capacity and just
| call realloc every time. I'm not sure if the standard specifies
| this, but I'm pretty sure every realloc implementation in
| practice, under the hood, should track the capacity and grow it
| at two power sizes. So even if you're just constantly appending
| by one char the cost short amortize itself out to be cheap in the
| long run.
| zX41ZdbW wrote:
| Testing performance of memcpy should be more exhaustive than
| just running on single CPU:
| https://github.com/ClickHouse/ClickHouse/issues/18583#issuec...
| JediPig wrote:
| is there any other similar libraries i should know about? frankly
| the developer is right, I hate re-implementation of lists and
| other crap in modern languages.
|
| I have a complete crap kernel include file i use when I write
| kernel modules. ( Though You will find me no longer publishing
| source code. Client is moving to freebsd, after a linux kernel
| bug that got labeled "WONT FIX" by linus & crew )
|
| So client goes "WONT SUPPORT" on 5.x linux. Linux userland is a
| damn mess.
| Deukhoofd wrote:
| So unrelated to the Zebra Programming Language?
| [deleted]
| [deleted]
| wg0 wrote:
| This is beautiful. I think I am going to toy around with it in a
| project I have been dreaming about.
| MaxBarraclough wrote:
| > Most parts of the library are written in pure C99. There are
| however, some additional components that require C11 to work
| (notably in the Threading module). As long as you are using
| minimal version (ZPL_NANO), and manually enable modules, the C99
| support should be just fine.
|
| I think it would be better to describe it as a C11 library. I
| didn't know what to make of 'almost C99', which might refer to
| limited use of compiler-specific features, for instance.
| mhd wrote:
| Is "Powerkit" some common term I'm missing here? At first I
| thought this was related to some kind of Apple "Kit", written in
| straight C instead of Objective-C/Swift.
| up2isomorphism wrote:
| I think that it is called "Powerkit" in a sense that it gives C
| programmers some tools that make daily programming task easier.
| [deleted]
| szanni wrote:
| This looks like a nice and concise library. Single header file,
| many useful functions, and a usable license. The only thing I
| really dislike are all of the typedefs. zpl_u64
| zpl_crc64(void const *data, zpl_isize len);
|
| Const correctness, good! But why is the size parameter signed?
| Why not use size_t and uint64_t like the C stdlib?
| messe wrote:
| The zpl_u64 seems to be because they're trying to support older
| versions of the MSVC compiler[1]. As for why they're using a
| signed size parameter, I'm not really sure. One idiom they
| appear to use often is[2]: for (...; x--;
| y++)
|
| where x is a size-type of some kind. They may be defaulting to
| signed size types to avoid errors in case somebody decides to
| change to above to: for (...; x-- >= 0; y++)
|
| There's even a macro zpl_size_of: #define
| zpl_size_of(x) (zpl_isize)(sizeof(x))
|
| But the real weirdness is in the other macros:
| #define cast(Type) (Type)
|
| ...just why? And #define ZPL_MULTILINE(...)
| #__VA_ARGS__
|
| is supposed to be a way of having multiline literals in C. But,
| everything inside the "..." has to be valid C tokens. It might
| work as a string literal in many cases, but it's misleading at
| best and broken at worst.
|
| I'm not sure what the advantage of the following is vs. just
| setting the bits using & and | which every C programmer should
| already be familiar with: #define
| ZPL_MASK_SET(var, set, mask) \ do {
| \ if (set) \
| (var) |= (mask); \ else
| \ (var) &= ~(mask); \ }
| while (0)
|
| There's surely no excuse for this: #define
| zpl_global static // Global variables
|
| While a lot of the library looks useful, stuff like the above
| makes it feel like it's written by somebody who knows C, but
| doesn't feel fully comfortable writing it.
|
| [1]:
| https://github.com/zpl-c/zpl/blob/master/code/header/essenti...
|
| [2]:
| https://github.com/zpl-c/zpl/blob/27c80bd5807da5238777bfcba8...
| up2isomorphism wrote:
| These extra wrappers are most likely when library writer
| trying to cover windows platform, which has almost never been
| a good place for ANSI C programming.
| keldaris wrote:
| > There's surely no excuse for this
|
| The "excuse" is greppability since static has three
| completely different meanings in C and the desire to clearly
| denote global variables is fairly common. The same reasoning
| goes for the cast define as well.
|
| Whether you find value in these small abuses of the
| preprocessor depends on your coding habits, but I don't
| really see much reason to criticize them. If the author finds
| them helpful, what's the harm? There isn't much room for
| confusion and they're not forced on the users of the library.
| badsectoracula wrote:
| From a quick look at the code it seems that zpl_isize is used
| to represent indices, counts, etc and in those cases -1 is
| often used as an "invalid" value with special meaning (e.g. in
| the hashtable -1 is used as a "not found" index).
| h_anna_h wrote:
| A bit sad that they did not go for uint64_t
| zpl_crc64(size_t len, const unsigned char data[len]);
| colejohnson66 wrote:
| Is that even portable?
| kiwidrew wrote:
| It's a C99 variable-length array declaration, so the syntax
| is valid; but unfortunately it doesn't actually do anything
| useful. The 'const unsigned char data[len]' declaration
| just decays to 'const unsigned char *data' -- the first
| level of array-ness is discarded.
|
| [ there was a bit of discussion about this earlier in the
| month: https://news.ycombinator.com/item?id=26349903 ]
| h_anna_h wrote:
| It is useful for static analysis, even the standard
| people say that they will move into this kind of
| declaration.
|
| > 15. Application Programming Interfaces (APIs) should be
| self-documenting when possible. In particular, the order
| of parameters in function declarations should be arranged
| such that the size of an array appears before the array.
| The purpose is to allow Variable-Length Array (VLA)
| notation to be used. This not only makes the code's
| purpose clearer to human readers, but also makes static
| analysis easier. Any new APIs added to the Standard
| should take this into consideration.
|
| from http://www.open-
| std.org/jtc1/sc22/wg14/www/docs/n2086.htm
___________________________________________________________________
(page generated 2021-03-20 23:01 UTC)