TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Binary to hex faster than xxd, part 1 of 2

3 pointsby textmodeabout 4 years ago
<p><pre><code> #include &lt;unistd.h&gt; #include &lt;poll.h&gt; #include &lt;errno.h&gt; #include &lt;sys&#x2F;types.h&gt; #include &lt;sys&#x2F;stat.h&gt; #ifndef EINTR #define EINTR (-5004) #endif #ifndef EAGAIN #define EAGAIN (-5011) #endif #ifndef EWOULDBLOCK #define EWOULDBLOCK (-7011) #endif int writeall(int fd,const void *xv,long long xlen) { const unsigned char *x = xv; long long w; while (xlen &gt; 0) { w = xlen; if (w &gt; 1048576) w = 1048576; w = write(fd,x,w); if (w &lt; 0) { if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { struct pollfd p; p.fd = fd; p.events = POLLOUT | POLLERR; poll(&amp;p,1,-1); continue; } return -1; } x += w; xlen -= w; } return 0; } long long readblock(int fd, void *x, long long xlen) { long long r; char *buf = x; while (xlen &gt; 0) { r = xlen; if (r &gt; 1048576) r = 1048576; r = read(fd, buf, r); if (r == 0) break; if (r == -1) { if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { struct pollfd p; p.fd = fd; p.events = POLLIN; poll(&amp;p, 1, -1); continue; } return -1; } buf += r; xlen -= r; } return (buf - (char *)x); } int fsyncfd(int fd) { struct stat st; if (fstat(fd, &amp;st) == 0 &amp;&amp; S_ISREG(st.st_mode)) { if (fsync(fd) == -1) return -1; } return 0; }</code></pre>

2 comments

kazinatorabout 4 years ago
There is no reason to ever integrate any of these functions into a xxd-like program. Or almost any program.<p>Non-blocking I&#x2F;O would ever only be used on pipe-like objects (sockets, serial ports, IPC pipes). There is no reason to use it if you are not multiplexing multiple I&#x2F;O descriptors onto one thread. There is no point in making a single thread sit in a loop that calls read and write on a single non-blocking descriptor, and uses poll to block. You&#x27;ve just implemented a bunch of complexity in order to do blocking I&#x2F;O, which you could get by not turning that descriptor non-blocking in the first place.<p>If you want to bring in POSIX-isms into an xxd-like program, consider mmaping the input (if it is a file) and then treating it as a big binary buffer to hexdump.<p>I see in your part 2&#x2F;2 that you&#x27;re not even calling readblock! The function is unused.<p>You are using writeall --- for flushing a &quot;char buf [256]&quot; static object when it fills up.<p>The fsync stuff is pointless; if someone cares, they can call the sync utility in a script after calling your program. Utilities like this should not be second-guessing the I&#x2F;O subsystem. fsync is for database engines and whatnot. Actually it&#x27;s pretty useless because it doesn&#x27;t give hard guarantees. Just because something is flushed out of the operating system&#x27;s buffers down to the hardware doesn&#x27;t mean it&#x27;s actually written into the storage device (disk surface or flash chips or whatever).<p>Calling fsync can only add a delay before your program terminates, making it look slower, so if you&#x27;re after writing a fast xxd, why would you be calling it?
评论 #27219672 未加载
textmodeabout 4 years ago
<p><pre><code> #include &lt;unistd.h&gt; #include &lt;errno.h&gt; #include &lt;sys&#x2F;types.h&gt; int writeall(int fd,const void *xv,long long xlen) { const unsigned char *x = xv; long long w; while (xlen &gt; 0) { w = xlen; if (w &gt; 1048576) w = 1048576; w = write(fd,x,w); x += w; xlen -= w; } return 0; } static int hexdigit(char x) { if (x &gt;= &#x27;0&#x27; &amp;&amp; x &lt;= &#x27;9&#x27;) return x - &#x27;0&#x27;; if (x &gt;= &#x27;a&#x27; &amp;&amp; x &lt;= &#x27;f&#x27;) return 10 + (x - &#x27;a&#x27;); if (x &gt;= &#x27;A&#x27; &amp;&amp; x &lt;= &#x27;F&#x27;) return 10 + (x - &#x27;A&#x27;); return -1; } int hexparse(unsigned char *y,long long len,const char *x) { if (!x) return 0; while (len &gt; 0) { int digit0; int digit1; digit0 = hexdigit(x[0]); if (digit0 == -1) return 0; digit1 = hexdigit(x[1]); if (digit1 == -1) return 0; *y++ = digit1 + 16 * digit0; --len; x += 2; } if (x[0]) return 0; return 1; }</code></pre>