#include "test.h" /* all optional */ #define SP_MALLOC mallocc #define SP_REALLOC reallocc #define SP_FREE free #include /* including default name is fine */ #include /* separate string type, can be defined in addition to the default type. The * default type can be included multiple times, but specially-named types * cannot. */ #define SP_NAME second #define SP_MALLOC mallocc #define SP_REALLOC reallocc #define SP_FREE free #include int main() { #if defined(COVERAGE) assert(!covsrv_init()); atexit(covsrv_destroy); #endif struct sp sp = sp_create(); /* should be in static buffer, cannot fail * (though the user should probably assume that appending can always * fail) */ assert(!sp_append_str(&sp, "123")); /* don't use sp.b directly, prefer sp_str, but this is fine for testing */ assert(strcmp(sp.b, "123") == 0); /* test static iteration */ foreach(sp, c, &sp) { switch (c.i) { case 0: assert(*c.p == '1'); break; case 1: assert(*c.p == '2'); break; case 2: assert(*c.p == '3'); break; default: assert(0 && "weird iteration"); } } /* now we should switch over to the dynamic buffer, as we have more * characters than can fit in any regular pointer type (3 for 32bit, 7 * for 64 bit, 15 for stuff like Cheri), might fail */ if (sp_append_str(&sp, "4567890ABCDEFGH")) { fprintf(stderr, "failed appending to string buffer"); sp_destroy(&sp); return -1; } /* same deal, check that we're using the dynamic buffer */ assert(strcmp(sp.p, "1234567890ABCDEFGH") == 0); /* test dynamic iteration */ foreach(sp, c, &sp) { switch (c.i) { case 0: assert(*c.p == '1'); break; case 1: assert(*c.p == '2'); break; case 2: assert(*c.p == '3'); break; case 3: assert(*c.p == '4'); break; case 4: assert(*c.p == '5'); break; case 5: assert(*c.p == '6'); break; case 6: assert(*c.p == '7'); break; case 7: assert(*c.p == '8'); break; case 8: assert(*c.p == '9'); break; case 9: assert(*c.p == '0'); break; case 10: assert(*c.p == 'A'); break; case 11: assert(*c.p == 'B'); break; case 12: assert(*c.p == 'C'); break; case 13: assert(*c.p == 'D'); break; case 14: assert(*c.p == 'E'); break; case 15: assert(*c.p == 'F'); break; case 16: assert(*c.p == 'G'); break; case 17: assert(*c.p == 'H'); break; default: assert(0 && "weird iteration"); } } /* 'reset' string */ sp_destroy(&sp); /* test formatting functions */ sp = sp_create(); /* static formatting */ for (int i = 1; i < 4; ++i) assert(!sp_append_fmt(&sp, "%d", i)); assert(strcmp(sp.b, "123") == 0); /* dynamic formatting */ for (int i = 4; i < 15; ++i) if (sp_append_fmt(&sp, "%d", i)) { fprintf(stderr, "failed formatting input\n"); sp_destroy(&sp); return -1; } assert(strcmp(sp.p, "1234567891011121314") == 0); sp_destroy(&sp); /* do some benchmarking, oh yeah! */ struct second sec = second_create(); for (int i = 0; i < ITER; ++i) if (second_append_str(&sec, "BENCHMARK, FUCK YEAH\n")) { fprintf(stderr, "failed when stressing append\n"); second_destroy(&sec); return -1; } /* hmm, come to think of it, foreach_line or something along those lines * might be pretty neat? */ second_destroy(&sec); sec = second_create(); for (int i = 0; i < ITER; ++i) if (second_append_fmt(&sec, "I'm in iteration %d!\n", i)) { fprintf(stderr, "failed when stressing fmt\n"); second_destroy(&sec); return -1; } second_destroy(&sec); /* all done! */ return 0; }