user503403
user503403

Reputation: 259

Unique file name using UUID

I need to create some binary data files from Object Identifiers, which is a variable-length binary void* buffer, upto 64 bytes and can contain any bytes corresponding to non-printable characters as well. I can't use Object Identifier as my file name as it contains non-printable letters. Any suggestions to create the unique filename. How can the UUID be derived or used in this case ?

Upvotes: 2

Views: 1709

Answers (1)

jxh
jxh

Reputation: 70392

You can convert the bytes into a hexadecimal string.

#define tohex(x) ("0123456789abcdef"[(x) & 0x0f])
char buf[129];
assert(objid_len <= 64);
for (int i = 0; i < objid_len; ++i) {
    buf[2*i] = tohex(objid[i] >> 4);
    buf[2*i+1] = tohex(objid[i]);
}
buf[2*objid_len] = '\0';

You can make the filenames have universal length by using a padding character that is outside the alphabet used to to represent the object id. If a shorter filename is desired, then a higher base could be used. For example, Base64.

const char * const base64str =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define tob64(x) base64str[(x) & 0x3f]

void objid_to_filename (const unsigned char *objid, int objid_len,
                        char *buf) {
    memset(buf, '-', 88);
    buf[88] = '\0';
    int i = 0, j = 0;
    int buflen = 4 * ((objid_len + 2)/3);
    while (i < objid_len) {
        unsigned x = 0;
        x |= (i < objid_len) ? objid[i++] << 16 : 0;
        x |= (i < objid_len) ? objid[i++] <<  8 : 0;
        x |= (i < objid_len) ? objid[i++] <<  0 : 0;
        buf[j++] = tob64(x >> 18);
        buf[j++] = tob64(x >> 12);
        buf[j++] = tob64(x >>  6);
        buf[j++] = tob64(x >>  0);
    }
    int pad = (3 - (objid_len % 3)) % 3;
    for (i = 0; i < pad; ++i) buf[buflen - 1 - i] = '=';
}

Upvotes: 4

Related Questions