/* * This function assists in building textual lists of the form "Tom, Dick and Harry". Call it three * times with the arguments "Tom", "Dick" and "Harry". Set sep1 to ", " and sep2 to " and ". Set * is_first to TRUE when passing in "Tom", set is_last to TRUE when passing in "Harry", set them * both to FALSE for "Dick". Returns the same pointer to <buf> that was passed in. */ Buffer *bufList(Buffer *buf, const char *sep1, const char *sep2, int is_first, int is_last, const char *fmt, ...) { va_list ap; if (!is_first) { if (is_last) bufAddF(buf, "%s", sep2); else bufAddF(buf, "%s", sep1); } va_start(ap, fmt); bufAddV(buf, fmt, ap); va_end(ap); return buf; }
/* * Write the requested prefixes into the log message. */ static void log_write_prefixes(Logger *logger, const char *file, int line, const char *func) { struct tm tm = { 0 }; struct timeval tv = { 0 }; LOG_Prefix *pfx; tv.tv_sec = -1; for (pfx = listHead(&logger->prefixes); pfx; pfx = listNext(pfx)) { switch(pfx->type) { case LOG_PT_DATE: if (tv.tv_sec == -1) log_get_time(&tm, &tv); bufAddF(&logger->scratch, "%04d-%02d-%02d ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); break; case LOG_PT_TIME: if (tv.tv_sec == -1) log_get_time(&tm, &tv); bufAddF(&logger->scratch, "%02d:%02d:", tm.tm_hour, tm.tm_min); if (pfx->u.precision == 0) { bufAddF(&logger->scratch, "%02d ", tm.tm_sec); } else { double seconds = (double) tm.tm_sec + (double) tv.tv_usec / 1000000.0; bufAddF(&logger->scratch, "%0*.*f ", 3 + pfx->u.precision, pfx->u.precision, seconds); } break; case LOG_PT_FILE: bufAddF(&logger->scratch, "%s ", file); break; case LOG_PT_LINE: bufAddF(&logger->scratch, "%d ", line); break; case LOG_PT_FUNC: bufAddF(&logger->scratch, "%s ", func); break; case LOG_PT_STR: bufAddF(&logger->scratch, "%s ", pfx->u.string); break; } } }
int main(int argc, char *argv[]) { Buffer buf1 = { 0 }; Buffer buf2 = { 0 }; Buffer *buf3; bufClear(&buf1); make_sure_that(bufLen(&buf1) == 0); make_sure_that(bufIsEmpty(&buf1)); bufAdd(&buf1, "ABCDEF", 3); make_sure_that(bufLen(&buf1) == 3); make_sure_that(!bufIsEmpty(&buf1)); make_sure_that(strcmp(bufGet(&buf1), "ABC") == 0); bufAddC(&buf1, 'D'); make_sure_that(bufLen(&buf1) == 4); make_sure_that(strcmp(bufGet(&buf1), "ABCD") == 0); bufAddF(&buf1, "%d", 1234); make_sure_that(bufLen(&buf1) == 8); make_sure_that(strcmp(bufGet(&buf1), "ABCD1234") == 0); bufAddS(&buf1, "XYZ"); make_sure_that(bufLen(&buf1) == 11); make_sure_that(strcmp(bufGet(&buf1), "ABCD1234XYZ") == 0); bufSet(&buf1, "ABCDEF", 3); make_sure_that(bufLen(&buf1) == 3); make_sure_that(strcmp(bufGet(&buf1), "ABC") == 0); bufSetC(&buf1, 'D'); make_sure_that(bufLen(&buf1) == 1); make_sure_that(strcmp(bufGet(&buf1), "D") == 0); bufSetF(&buf1, "%d", 1234); make_sure_that(bufLen(&buf1) == 4); make_sure_that(strcmp(bufGet(&buf1), "1234") == 0); bufSetS(&buf1, "ABCDEF"); make_sure_that(bufLen(&buf1) == 6); make_sure_that(strcmp(bufGet(&buf1), "ABCDEF") == 0); bufClear(&buf1); make_sure_that(bufLen(&buf1) == 0); make_sure_that(strcmp(bufGet(&buf1), "") == 0); bufSet(&buf1, "ABC", 3); bufSet(&buf2, "DEF", 3); buf3 = bufCat(&buf1, &buf2); make_sure_that(&buf1 == buf3); make_sure_that(bufLen(&buf1) == 6); make_sure_that(strcmp(bufGet(&buf1), "ABCDEF") == 0); make_sure_that(bufLen(&buf2) == 3); make_sure_that(strcmp(bufGet(&buf2), "DEF") == 0); bufSetF(&buf1, "ABCDEF"); make_sure_that(strcmp(bufGet(bufTrim(&buf1, 0, 0)), "ABCDEF") == 0); make_sure_that(strcmp(bufGet(bufTrim(&buf1, 1, 0)), "BCDEF") == 0); make_sure_that(strcmp(bufGet(bufTrim(&buf1, 0, 1)), "BCDE") == 0); make_sure_that(strcmp(bufGet(bufTrim(&buf1, 1, 1)), "CD") == 0); make_sure_that(strcmp(bufGet(bufTrim(&buf1, 3, 3)), "") == 0); bufPack(&buf1, PACK_INT8, 0x01, PACK_INT16, 0x0123, PACK_INT32, 0x01234567, PACK_INT64, 0x0123456789ABCDEF, PACK_FLOAT, 0.0, PACK_DOUBLE, 0.0, PACK_STRING, "Hoi1", PACK_DATA, "Hoi2", 4, PACK_RAW, "Hoi3", 4, END); make_sure_that(bufLen(&buf1) == 47); make_sure_that(memcmp(bufGet(&buf1), "\x01" "\x01\x23" "\x01\x23\x45\x67" "\x01\x23\x45\x67\x89\xAB\xCD\xEF" "\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x04Hoi1" "\x00\x00\x00\x04Hoi2" "Hoi3", 47) == 0); { uint8_t u8; uint16_t u16; uint32_t u32; uint64_t u64; float f32; double f64; char *string, *data, raw[4]; int data_size; bufUnpack(&buf1, PACK_INT8, &u8, PACK_INT16, &u16, PACK_INT32, &u32, PACK_INT64, &u64, PACK_FLOAT, &f32, PACK_DOUBLE, &f64, PACK_STRING, &string, PACK_DATA, &data, &data_size, PACK_RAW, &raw, sizeof(raw), END); make_sure_that(u8 == 0x01); make_sure_that(u16 == 0x0123); make_sure_that(u32 == 0x01234567); make_sure_that(u64 == 0x0123456789ABCDEF); make_sure_that(f32 == 0.0); make_sure_that(f64 == 0.0); make_sure_that(memcmp(string, "Hoi1", 5) == 0); make_sure_that(memcmp(data, "Hoi2", 4) == 0); make_sure_that(data_size == 4); make_sure_that(memcmp(raw, "Hoi3", 4) == 0); } { bufUnpack(&buf1, PACK_INT8, NULL, PACK_INT16, NULL, PACK_INT32, NULL, PACK_INT64, NULL, PACK_FLOAT, NULL, PACK_DOUBLE, NULL, PACK_STRING, NULL, PACK_DATA, NULL, NULL, PACK_RAW, NULL, 4, END); } { const char *name[] = { "Mills", "Berry", "Buck", "Stipe" }; bufClear(&buf1); bufList(&buf1, ", ", " and ", TRUE, TRUE, "%s", name[0]); make_sure_that(strcmp(bufGet(&buf1), "Mills") == 0); bufClear(&buf1); bufList(&buf1, ", ", " and ", TRUE, FALSE, "%s", name[0]); bufList(&buf1, ", ", " and ", FALSE, TRUE, "%s", name[1]); make_sure_that(strcmp(bufGet(&buf1), "Mills and Berry") == 0); bufClear(&buf1); bufList(&buf1, ", ", " and ", TRUE, FALSE, "%s", name[0]); bufList(&buf1, ", ", " and ", FALSE, FALSE, "%s", name[1]); bufList(&buf1, ", ", " and ", FALSE, TRUE, "%s", name[2]); make_sure_that(strcmp(bufGet(&buf1), "Mills, Berry and Buck") == 0); bufClear(&buf1); bufList(&buf1, ", ", " and ", TRUE, FALSE, "%s", name[0]); bufList(&buf1, ", ", " and ", FALSE, FALSE, "%s", name[1]); bufList(&buf1, ", ", " and ", FALSE, FALSE, "%s", name[2]); bufList(&buf1, ", ", " and ", FALSE, TRUE, "%s", name[3]); make_sure_that(strcmp(bufGet(&buf1), "Mills, Berry, Buck and Stipe") == 0); } bufReset(&buf1); bufReset(&buf2); return errors; }