ucx/utils.c

Thu, 21 Dec 2017 19:48:27 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 21 Dec 2017 19:48:27 +0100
changeset 359
bacb54502b24
parent 335
c1bc13faadaa
child 505
481802342fdf
permissions
-rw-r--r--

davql: allow ANYWHERE keyword in SELECT statements

This may seem pointless, but users might want to be explicit about this and the grammar is more consistent.

This commit also adds some no-ops to the functions body of the SET parser, because some day the grammar might allow more clauses after the WHERE clause.

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "ucx/utils.h"

#include <math.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>

/* COPY FUCNTIONS */
void* ucx_strcpy(const void* s, void* data) {
    const char *str = (const char*) s;
    size_t n = 1+strlen(str);
    char *cpy = (char*) malloc(n);
    memcpy(cpy, str, n);
    return cpy;
}

void* ucx_memcpy(const void* m, void* n) {
    size_t k = *((size_t*)n);
    void *cpy = malloc(k);
    memcpy(cpy, m, k);
    return cpy;
}

size_t ucx_stream_bncopy(void *src, void *dest, read_func readfnc,
        write_func writefnc, char* buf, size_t bufsize, size_t n) {
    if(n == 0 || bufsize == 0) {
        return 0;
    }
    
    char *lbuf;    
    size_t ncp = 0;
    
    if(buf) {
        lbuf = buf;
    } else {
        lbuf = (char*)malloc(bufsize);
        if(lbuf == NULL) {
            return 0;
        }
    }
    
    size_t r;
    size_t rn = bufsize > n ? n : bufsize;
    while((r = readfnc(lbuf, 1, rn, src)) != 0) {
        r = writefnc(lbuf, 1, r, dest);
        ncp += r;
        n -= r;
        rn = bufsize > n ? n : bufsize;
        if(r == 0 || n == 0) {
            break;
        }
    }
    
    if (lbuf != buf) {
        free(lbuf);
    }
    
    return ncp;
}

/* COMPARE FUNCTIONS */

int ucx_strcmp(const void *s1, const void *s2, void *data) {
    return strcmp((const char*)s1, (const char*)s2);
}

int ucx_strncmp(const void *s1, const void *s2, void *n) {
    return strncmp((const char*)s1, (const char*)s2, *((size_t*) n));
}

int ucx_intcmp(const void *i1, const void *i2, void *data) {
   int a = *((const int*) i1);
   int b = *((const int*) i2);
   if (a == b) {
       return 0;
   } else {
       return a < b ? -1 : 1;
   }
}

int ucx_floatcmp(const void *f1, const void *f2, void *epsilon) {
   float a = *((const float*) f1);
   float b = *((const float*) f2);
   float e = !epsilon ? 1e-6f : *((float*)epsilon);
   if (fabsf(a - b) < e) {
       return 0;
   } else {
       return a < b ? -1 : 1;
   }
}

int ucx_doublecmp(const void *d1, const void *d2, void *epsilon) {
   double a = *((const double*) d1);
   double b = *((const double*) d2);
   double e = !epsilon ? 1e-14 : *((double*)epsilon);
   if (fabs(a - b) < e) {
       return 0;
   } else {
       return a < b ? -1 : 1;
   }
}

int ucx_ptrcmp(const void *ptr1, const void *ptr2, void *data) {
    const intptr_t p1 = (const intptr_t) ptr1;
    const intptr_t p2 = (const intptr_t) ptr2;
    if (p1 == p2) {
        return 0;
    } else {
        return p1  < p2 ? -1 : 1;
    }
}

int ucx_memcmp(const void *ptr1, const void *ptr2, void *n) {
    return memcmp(ptr1, ptr2, *((size_t*)n));
}

/* PRINTF FUNCTIONS */

#ifdef va_copy
#define UCX_PRINTF_BUFSIZE 256
#else
#pragma message("WARNING: C99 va_copy macro not supported by this platform" \
                " - limiting ucx_*printf to 2 KiB")
#define UCX_PRINTF_BUFSIZE 0x800
#endif

int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...) {
    int ret;
    va_list ap;
    va_start(ap, fmt);
    ret = ucx_vfprintf(stream, wfc, fmt, ap);
    va_end(ap);
    return ret;
}

int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap) {
    char buf[UCX_PRINTF_BUFSIZE];
#ifdef va_copy
    va_list ap2;
    va_copy(ap2, ap);
    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
    if (ret < 0) {
        return ret;
    } else if (ret < UCX_PRINTF_BUFSIZE) {
        return (int)wfc(buf, 1, ret, stream);
    } else {
        if (ret == INT_MAX) {
            errno = ENOMEM;
            return -1;
        }
        
        int len = ret + 1;
        char *newbuf = (char*)malloc(len);
        if (!newbuf) {
            return -1;
        }
        
        ret = vsnprintf(newbuf, len, fmt, ap2);
        if (ret > 0) {
            ret = (int)wfc(newbuf, 1, ret, stream);
        }
        free(newbuf);
    }
    return ret;
#else
    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
    if (ret < 0) {
        return ret;
    } else if (ret < UCX_PRINTF_BUFSIZE) {
        return (int)wfc(buf, 1, ret, stream);
    } else {
        errno = ENOMEM;
        return -1;
    }
#endif
}

sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...) {
    va_list ap;
    sstr_t ret;
    va_start(ap, fmt);
    ret = ucx_vasprintf(allocator, fmt, ap);
    va_end(ap);
    return ret;
}

sstr_t ucx_vasprintf(UcxAllocator *a, const char *fmt, va_list ap) {
    sstr_t s;
    s.ptr = NULL;
    s.length = 0;
    char buf[UCX_PRINTF_BUFSIZE];
#ifdef va_copy
    va_list ap2;
    va_copy(ap2, ap);
    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
    if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) {
        s.ptr = (char*)almalloc(a, ret + 1);
        if (s.ptr) {
            s.length = (size_t)ret;
            memcpy(s.ptr, buf, ret);
            s.ptr[s.length] = '\0';
        }
    } else if (ret == INT_MAX) {
        errno = ENOMEM;
    } else  {
        int len = ret + 1;
        s.ptr = (char*)almalloc(a, len);
        if (s.ptr) {
            ret = vsnprintf(s.ptr, len, fmt, ap2);
            if (ret < 0) {
                free(s.ptr);
                s.ptr = NULL;
            } else {
                s.length = (size_t)ret;
            }
        }
    }
#else
    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
    if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) {
        s.ptr = (char*)almalloc(a, ret + 1);
        if (s.ptr) {
            s.length = (size_t)ret;
            memcpy(s.ptr, buf, ret);
            s.ptr[s.length] = '\0';
        }
    } else {
        errno = ENOMEM;
    }
#endif
    return s;
}

mercurial