#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
char *speak ( char *bs, unsigned int counter ) {
char *str = "Hello %d: %s";
size_t bs_l = strlen( bs );
size_t str_l = strlen( str ) - 2;
size_t c_l = counter == 0? 1 : log(counter) / log(10) + 1;
size_t alloc = str_l + c_l + bs_l;
char *ptr = malloc( alloc );
int written = snprintf( ptr, alloc, str, counter, bs );
printf( "(%zd + %zd + %zd) = %zd <> %i: ", str_l, c_l, bs_l, alloc, written );
return ptr;
}
int main ( void ) {
unsigned int c;
for( c = 0; c == c; c = c + 5 ) {
char *foo = speak("Have a nice day!", c);
printf("%s\r", foo);
free( foo );
}
exit(0);
}
Wednesday, August 31, 2011
Some more C musings
Still working on getting my C mojo back both for school and for a application project. Here is an example of some (attempting to be overrun safe) dynamic memory alocation:
Wednesday, August 24, 2011
Example of libxslt transform from a libcurl fetch
I've written various programs/network services that perform this function for one purpose or another. In light of some performance needs of one of these services I've been considering porting it from Perl to C in order to get the most performance possible. Being as I haven't written anything in C in a very long time I thought I would implement one aspect of the service as a simple command line tool.
This is the result:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <curl/curl.h> #include <libxml/xmlmemory.h> #include <libxslt/xslt.h> #include <libxslt/xsltInternals.h> #include <libxslt/transform.h> #include <libxslt/xsltutils.h> struct fetch { char *buffer; size_t size; }; static size_t write_fetch ( void *chunk, size_t size, size_t nmemb, void *data ) { size_t realsize = size * nmemb; struct fetch *f = (struct fetch *)data; f->buffer = realloc( f->buffer, f->size + realsize + 1 ); if ( f->buffer == NULL ) { fprintf( stderr, "Out of memory (realloc returned NULL)\n" ); exit( EXIT_FAILURE ); } memcpy( &( f->buffer[ f->size ] ), chunk, realsize ); f->size += realsize; f->buffer[ f->size ] = 0; return realsize; } CURLcode get_curl_xml ( char *url, void *chunk ) { CURL *curl; CURLcode result; if ( curl = curl_easy_init() ) { curl_easy_setopt( curl, CURLOPT_URL, url ); curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, write_fetch ); curl_easy_setopt( curl, CURLOPT_WRITEDATA, chunk ); if ( ( result = curl_easy_perform( curl ) ) != 0 ) { fprintf( stderr, "Error %i: %s\n", result, curl_easy_strerror( result ) ); return result; } curl_easy_cleanup( curl ); } else { return -1; } } int main (int argc, char *argv[]) { struct fetch data; xsltStylesheetPtr xslt = NULL; xmlDocPtr source, normalized; data.buffer = malloc( 1 ); data.size = 0; if ( argc < 2 ) { fprintf( stderr, "Usage: %s <stylesheet> <url>\n", argv[0] ); return 0; } get_curl_xml( argv[2], (void *)&data ); fprintf( stderr, "Fetched %lu bytes\n", (long)data.size); fprintf( stderr, "Buffer size %lu\n", sizeof( data.buffer ) ); if ( source = xmlReadMemory( data.buffer, data.size, "memory.xml", NULL, 0 ) ) { xslt = xsltParseStylesheetFile( (const xmlChar *)argv[1] ); normalized = xsltApplyStylesheet( xslt, source, NULL ); fprintf( stderr, "Normlized XML data\n" ); xmlSaveFile( "-", normalized ); } else { fprintf( stderr, "Failed to parse XML document\n" ); } xmlFreeDoc( source ); xmlFreeDoc( normalized ); xmlCleanupParser(); free( data.buffer ); return 0; }
Subscribe to:
Posts (Atom)