💾 Archived View for gemini.thededem.de › lc19 › src › src › util.c captured on 2021-12-03 at 14:04:38.
-=-=-=-=-=-=-
/* Copyright 2020, 2021 Lukas Wedeking * * This file is part of LC19. * * LC19 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LC19 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LC19. If not, see <https://www.gnu.org/licenses/>. */ #include "../include/util.h" #include<assert.h> #include<stdarg.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> size_t util_utf8_get_codepoint(const char *s, size_t max_length, unsigned char codepoint[3]) { assert(codepoint != NULL); size_t length = 0; codepoint[0] = 0x0; codepoint[1] = 0x0; codepoint[2] = 0x0; /* * Check for one, two, three and four byte UTF-8 character. The first * byte of a UTF-8 character signifies the length of the character: * 0b0xxxxxxx: 1 byte (ascii) * 0b110xxxxx: 2 bytes * 0b1110xxxx: 3 bytes * 0b11110xxx: 4 bytes * * The following bytes in a multi-byte UTF-8 character all have the * form: * 0b10xxxxxx * * To check, whether a byte is the start of a mutlti-byte UTF-8 * character, we use the bitwise & operator with the byte and the values * 0b10000000 * 0b11100000 * 0b11110000 * 0b11111000 * and check that the results are * 0b00000000 * 0b11000000 * 0b11100000 * 0b11110000 * respectively. */ if (max_length >= 1 && (s[0] & 0x80) == 0x0) { length = 1; codepoint[2] = s[0]; } else if (max_length >= 2 && (s[0] & 0xe0) == 0xc0 && (s[1] & 0xc0) == 0x80) { length = 2; codepoint[1] = (s[0] & 0x1f) >> 2; codepoint[2] = (s[0] & 0x1f) << 6; codepoint[2] |= s[1] & 0x3f; } else if (max_length >= 3 && (s[0] & 0xf0) == 0xe0 && (s[1] & 0xc0) == 0x80 && (s[1] & 0xc0) == 0x80) { length = 3; codepoint[1] = (s[0] & 0xf) << 4; codepoint[1] |= (s[1] & 0x3f) >> 2; codepoint[2] = (s[1] & 0x3f) << 6; codepoint[2] |= s[2] & 0x3f; } else if (max_length >= 4 && (s[0] & 0xf8) == 0xf0 && (s[1] & 0xc0) == 0x80 && (s[1] & 0xc0) == 0x80 && (s[1] & 0xc0) == 0x80) { length = 4; codepoint[0] = (s[0] & 0x7) << 2; codepoint[0] |= (s[1] & 0x3f) >> 4; codepoint[1] = (s[1] & 0x3f) << 4; codepoint[1] |= (s[2] & 0x3f) >> 2; codepoint[2] = (s[2] & 0x3f) << 6; codepoint[2] |= s[3] & 0x3f; } return length; } void log_msg(enum Loglevel level, const char *fmt, ...) { extern enum Loglevel loglevel; if (level > loglevel) { return; } time_t now_stamp = time(NULL); if (now_stamp >= 0) { struct tm *now_struct = localtime(&now_stamp); fprintf(stderr, "%d-%.2d-%.2dT%.2d:%.2d:%.2d ", now_struct->tm_year + 1900, now_struct->tm_mon + 1, now_struct->tm_mday, now_struct->tm_hour, now_struct->tm_min, now_struct->tm_sec); } switch (level) { case LOGLEVEL_ERROR: fprintf(stderr, "ERROR "); break; case LOGLEVEL_INFO: fprintf(stderr, "INFO "); break; case LOGLEVEL_DEBUG: fprintf(stderr, "DEBUG "); break; } /* * Add a newline at the end of fmt. */ size_t fmt_len = strlen(fmt); char *fmt_nl = calloc(fmt_len + 2, sizeof(char)); strcpy(fmt_nl, fmt); fmt_nl[fmt_len] = '\n'; va_list args; va_start(args, fmt); vfprintf(stderr, fmt_nl, args); va_end(args); free(fmt_nl); fflush(stderr); } size_t util_strcpy(char *dest, const char *src, size_t max) { size_t i = 0; while (i < max && src[i] != 0x0) { dest[i] = src[i]; i++; } if (i+1 < max) { dest[i+1] = 0x0; } else { dest[i] = 0x0; i--; } return i; } size_t util_mime_type(const char *mime_str, char *dest, size_t size) { size_t len = 0; while (len < size && mime_str[len] != 0x0 && mime_str[len] != ';' && mime_str[len] != ' ') { len++; } strncpy(dest, mime_str, len); return len; } size_t util_mime_next_param(const char *param_str, char *dest, size_t size) { size_t w = 0; for (size_t i = 0; param_str[i] != 0x0 && param_str[i] != ';' && param_str[i] != '=' && w < size - 1; i++) { if (param_str[i] == ' ') { continue; } else { dest[w] = param_str[i]; w++; } } dest[w] = 0x0; return w; }