diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2023-04-10 00:31:37 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-10 00:31:37 +0100 |
| commit | f3ba877fc52ff902b211e58d3c0e6e005bf3ab84 (patch) | |
| tree | db37c7caaf1c40ebf8b2b3527a7598b6d1fe39b5 | |
| parent | 2699911c7bf1f409e74fd45888441d990e5f81da (diff) | |
| parent | c5c9938bcabccd143a967d74a9fc135beeee8002 (diff) | |
| download | perlweeklychallenge-club-f3ba877fc52ff902b211e58d3c0e6e005bf3ab84.tar.gz perlweeklychallenge-club-f3ba877fc52ff902b211e58d3c0e6e005bf3ab84.tar.bz2 perlweeklychallenge-club-f3ba877fc52ff902b211e58d3c0e6e005bf3ab84.zip | |
Merge pull request #7873 from pauloscustodio/master
Add solution
| -rw-r--r-- | challenge-001/paulo-custodio/brainfuck.py | 2 | ||||
| -rw-r--r-- | challenge-001/paulo-custodio/c/ch-1.c | 28 | ||||
| -rw-r--r-- | challenge-001/paulo-custodio/c/utstring.h | 407 | ||||
| -rw-r--r-- | challenge-001/paulo-custodio/test.pl | 2 | ||||
| -rw-r--r-- | challenge-022/paulo-custodio/c/ch-1.c | 54 | ||||
| -rw-r--r-- | challenge-022/paulo-custodio/c/ch-2.c | 233 | ||||
| -rw-r--r-- | challenge-022/paulo-custodio/c/utarray.h | 252 | ||||
| -rw-r--r-- | challenge-022/paulo-custodio/c/uthash.h | 1140 | ||||
| -rw-r--r-- | challenge-022/paulo-custodio/c/utstring.h | 407 |
9 files changed, 2505 insertions, 20 deletions
diff --git a/challenge-001/paulo-custodio/brainfuck.py b/challenge-001/paulo-custodio/brainfuck.py index 9d68e92acc..7316bd6456 100644 --- a/challenge-001/paulo-custodio/brainfuck.py +++ b/challenge-001/paulo-custodio/brainfuck.py @@ -131,6 +131,6 @@ if len(args)!=1: with open(args[0]) as f: prog = "".join(f.readlines()) -# initialize and run Tuting Machine +# initialize and run Turing Machine tm = TuringMachine(prog) tm.run() diff --git a/challenge-001/paulo-custodio/c/ch-1.c b/challenge-001/paulo-custodio/c/ch-1.c index 54c2e8e58e..ea730a938b 100644 --- a/challenge-001/paulo-custodio/c/ch-1.c +++ b/challenge-001/paulo-custodio/c/ch-1.c @@ -11,13 +11,7 @@ is found in the string. #include <string.h> #include <stdlib.h> #include <memory.h> - -void* check_mem(void* p) { - if (!p) { - fputs("out of memory", stderr); - exit(EXIT_FAILURE); - } -} +#include "utstring.h" int replace_e(char* text) { int count = 0; @@ -31,16 +25,14 @@ int replace_e(char* text) { } int main(int argc, char* argv[]) { - char* text = check_mem(strdup("")); - for (int i = 1; i < argc; i++) { - text = check_mem(realloc(text, strlen(text)+strlen(argv[i])+2)); - strcat(text, argv[i]); - strcat(text, " "); - } - if (*text) - text[strlen(text)-1] = '\0'; // remove last space + UT_string* text; + utstring_new(text); + + for (int i = 1; i < argc; i++) + utstring_printf(text, "%s%s", i==1 ? "" : " ", argv[i]); + + int count = replace_e(utstring_body(text)); + printf("%d %s\n", count, utstring_body(text)); - int count = replace_e(text); - printf("%d %s\n", count, text); - free(text); + utstring_free(text); } diff --git a/challenge-001/paulo-custodio/c/utstring.h b/challenge-001/paulo-custodio/c/utstring.h new file mode 100644 index 0000000000..f0270fb632 --- /dev/null +++ b/challenge-001/paulo-custodio/c/utstring.h @@ -0,0 +1,407 @@ +/* +Copyright (c) 2008-2022, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +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 OWNER +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. +*/ + +/* a dynamic string implementation using macros + */ +#ifndef UTSTRING_H +#define UTSTRING_H + +#define UTSTRING_VERSION 2.3.0 + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> + +#ifdef __GNUC__ +#define UTSTRING_UNUSED __attribute__((__unused__)) +#else +#define UTSTRING_UNUSED +#endif + +#ifdef oom +#error "The name of macro 'oom' has been changed to 'utstring_oom'. Please update your code." +#define utstring_oom() oom() +#endif + +#ifndef utstring_oom +#define utstring_oom() exit(-1) +#endif + +typedef struct { + char *d; /* pointer to allocated buffer */ + size_t n; /* allocated capacity */ + size_t i; /* index of first unused byte */ +} UT_string; + +#define utstring_reserve(s,amt) \ +do { \ + if (((s)->n - (s)->i) < (size_t)(amt)) { \ + char *utstring_tmp = (char*)realloc( \ + (s)->d, (s)->n + (amt)); \ + if (!utstring_tmp) { \ + utstring_oom(); \ + } \ + (s)->d = utstring_tmp; \ + (s)->n += (amt); \ + } \ +} while(0) + +#define utstring_init(s) \ +do { \ + (s)->n = 0; (s)->i = 0; (s)->d = NULL; \ + utstring_reserve(s,100); \ + (s)->d[0] = '\0'; \ +} while(0) + +#define utstring_done(s) \ +do { \ + if ((s)->d != NULL) free((s)->d); \ + (s)->n = 0; \ +} while(0) + +#define utstring_free(s) \ +do { \ + utstring_done(s); \ + free(s); \ +} while(0) + +#define utstring_new(s) \ +do { \ + (s) = (UT_string*)malloc(sizeof(UT_string)); \ + if (!(s)) { \ + utstring_oom(); \ + } \ + utstring_init(s); \ +} while(0) + +#define utstring_renew(s) \ +do { \ + if (s) { \ + utstring_clear(s); \ + } else { \ + utstring_new(s); \ + } \ +} while(0) + +#define utstring_clear(s) \ +do { \ + (s)->i = 0; \ + (s)->d[0] = '\0'; \ +} while(0) + +#define utstring_bincpy(s,b,l) \ +do { \ + utstring_reserve((s),(l)+1); \ + if (l) memcpy(&(s)->d[(s)->i], b, l); \ + (s)->i += (l); \ + (s)->d[(s)->i]='\0'; \ +} while(0) + +#define utstring_concat(dst,src) \ +do { \ + utstring_reserve((dst),((src)->i)+1); \ + if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \ + (dst)->i += (src)->i; \ + (dst)->d[(dst)->i]='\0'; \ +} while(0) + +#define utstring_len(s) ((s)->i) + +#define utstring_body(s) ((s)->d) + +UTSTRING_UNUSED static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) { + int n; + va_list cp; + for (;;) { +#ifdef _WIN32 + cp = ap; +#else + va_copy(cp, ap); +#endif + n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp); + va_end(cp); + + if ((n > -1) && ((size_t) n < (s->n-s->i))) { + s->i += n; + return; + } + + /* Else try again with more space. */ + if (n > -1) utstring_reserve(s,n+1); /* exact */ + else utstring_reserve(s,(s->n)*2); /* 2x */ + } +} +#ifdef __GNUC__ +/* support printf format checking (2=the format string, 3=start of varargs) */ +static void utstring_printf(UT_string *s, const char *fmt, ...) + __attribute__ (( format( printf, 2, 3) )); +#endif +UTSTRING_UNUSED static void utstring_printf(UT_string *s, const char *fmt, ...) { + va_list ap; + va_start(ap,fmt); + utstring_printf_va(s,fmt,ap); + va_end(ap); +} + +/******************************************************************************* + * begin substring search functions * + ******************************************************************************/ +/* Build KMP table from left to right. */ +UTSTRING_UNUSED static void _utstring_BuildTable( + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + + i = 0; + j = i - 1; + P_KMP_Table[i] = j; + while (i < (long) P_NeedleLen) + { + while ( (j > -1) && (P_Needle[i] != P_Needle[j]) ) + { + j = P_KMP_Table[j]; + } + i++; + j++; + if (i < (long) P_NeedleLen) + { + if (P_Needle[i] == P_Needle[j]) + { + P_KMP_Table[i] = P_KMP_Table[j]; + } + else + { + P_KMP_Table[i] = j; + } + } + else + { + P_KMP_Table[i] = j; + } + } + + return; +} + + +/* Build KMP table from right to left. */ +UTSTRING_UNUSED static void _utstring_BuildTableR( + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + + i = P_NeedleLen - 1; + j = i + 1; + P_KMP_Table[i + 1] = j; + while (i >= 0) + { + while ( (j < (long) P_NeedleLen) && (P_Needle[i] != P_Needle[j]) ) + { + j = P_KMP_Table[j + 1]; + } + i--; + j--; + if (i >= 0) + { + if (P_Needle[i] == P_Needle[j]) + { + P_KMP_Table[i + 1] = P_KMP_Table[j + 1]; + } + else + { + P_KMP_Table[i + 1] = j; + } + } + else + { + P_KMP_Table[i + 1] = j; + } + } + + return; +} + + +/* Search data from left to right. ( Multiple search mode. ) */ +UTSTRING_UNUSED static long _utstring_find( + const char *P_Haystack, + size_t P_HaystackLen, + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + long V_FindPosition = -1; + + /* Search from left to right. */ + i = j = 0; + while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) ) + { + while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) ) + { + i = P_KMP_Table[i]; + } + i++; + j++; + if (i >= (int)P_NeedleLen) + { + /* Found. */ + V_FindPosition = j - i; + break; + } + } + + return V_FindPosition; +} + + +/* Search data from right to left. ( Multiple search mode. ) */ +UTSTRING_UNUSED static long _utstring_findR( + const char *P_Haystack, + size_t P_HaystackLen, + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + long V_FindPosition = -1; + + /* Search from right to left. */ + j = (P_HaystackLen - 1); + i = (P_NeedleLen - 1); + while ( (j >= 0) && (j >= i) ) + { + while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) ) + { + i = P_KMP_Table[i + 1]; + } + i--; + j--; + if (i < 0) + { + /* Found. */ + V_FindPosition = j + 1; + break; + } + } + + return V_FindPosition; +} + + +/* Search data from left to right. ( One time search mode. ) */ +UTSTRING_UNUSED static long utstring_find( + UT_string *s, + long P_StartPosition, /* Start from 0. -1 means last position. */ + const char *P_Needle, + size_t P_NeedleLen) +{ + long V_StartPosition; + long V_HaystackLen; + long *V_KMP_Table; + long V_FindPosition = -1; + + if (P_StartPosition < 0) + { + V_StartPosition = s->i + P_StartPosition; + } + else + { + V_StartPosition = P_StartPosition; + } + V_HaystackLen = s->i - V_StartPosition; + if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) + { + V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); + if (V_KMP_Table != NULL) + { + _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table); + + V_FindPosition = _utstring_find(s->d + V_StartPosition, + V_HaystackLen, + P_Needle, + P_NeedleLen, + V_KMP_Table); + if (V_FindPosition >= 0) + { + V_FindPosition += V_StartPosition; + } + + free(V_KMP_Table); + } + } + + return V_FindPosition; +} + + +/* Search data from right to left. ( One time search mode. ) */ +UTSTRING_UNUSED static long utstring_findR( + UT_string *s, + long P_StartPosition, /* Start from 0. -1 means last position. */ + const char *P_Needle, + size_t P_NeedleLen) +{ + long V_StartPosition; + long V_HaystackLen; + long *V_KMP_Table; + long V_FindPosition = -1; + + if (P_StartPosition < 0) + { + V_StartPosition = s->i + P_StartPosition; + } + else + { + V_StartPosition = P_StartPosition; + } + V_HaystackLen = V_StartPosition + 1; + if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) + { + V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); + if (V_KMP_Table != NULL) + { + _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table); + + V_FindPosition = _utstring_findR(s->d, + V_HaystackLen, + P_Needle, + P_NeedleLen, + V_KMP_Table); + + free(V_KMP_Table); + } + } + + return V_FindPosition; +} +/******************************************************************************* + * end substring search functions * + ******************************************************************************/ + +#endif /* UTSTRING_H */ diff --git a/challenge-001/paulo-custodio/test.pl b/challenge-001/paulo-custodio/test.pl index 118c4fee8b..e05049e9fd 100644 --- a/challenge-001/paulo-custodio/test.pl +++ b/challenge-001/paulo-custodio/test.pl @@ -145,7 +145,7 @@ sub build { } if (/^brainfuck$/) { #run("perl bfpp.pl <$prog_wo_ext.bfpp >$prog_wo_ext.bf"); - return "bf $prog_wo_ext.bf"; + return "python3 ../../challenge-001/paulo-custodio/brainfuck.py $prog_wo_ext.bf"; } if (/^c$/) { run("gcc $prog -o $prog_wo_ext -lm -lmpfr -lgmp") if (!-f $exe || -M $exe > -M $prog); diff --git a/challenge-022/paulo-custodio/c/ch-1.c b/challenge-022/paulo-custodio/c/ch-1.c new file mode 100644 index 0000000000..52c30201ba --- /dev/null +++ b/challenge-022/paulo-custodio/c/ch-1.c @@ -0,0 +1,54 @@ +/* +Challenge 022 + +Task #1 +Write a script to print first 10 Sexy Prime Pairs. Sexy primes are prime +numbers that differ from each other by 6. For example, the numbers 5 and 11 +are both sexy primes, because 11 - 5 = 6. The term "sexy prime" is a pun +stemming from the Latin word for six: sex. For more information, please +checkout wiki page. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> + +bool is_prime(int n) { + if (n <= 1) + return false; + if (n <= 3) + return true; + if ((n % 2) == 0 || (n % 3) == 0) + return false; + for (int i = 5; i * i <= n; i += 6) + if ((n % i) == 0 || (n % (i + 2)) == 0) + return false; + return true; +} + +int next_prime(int n) { + if (n <= 1) + return 2; + do { + n++; + } while (!is_prime(n)); + return n; +} + +void print_sexy_primes(int count) { + int a = 1; + while (count > 0) { + a = next_prime(a); + int b = a; + while (b < a+6) + b = next_prime(b); + if (b == a+6) { + printf("(%d, %d)\n", a, b); + count--; + } + } +} + +int main() { + print_sexy_primes(10); +} diff --git a/challenge-022/paulo-custodio/c/ch-2.c b/challenge-022/paulo-custodio/c/ch-2.c new file mode 100644 index 0000000000..05a0f0c9ef --- /dev/null +++ b/challenge-022/paulo-custodio/c/ch-2.c @@ -0,0 +1,233 @@ +/* +Challenge 022 + +Task #2 +Write a script to implement Lempel-Ziv-Welch (LZW) compression algorithm. +The script should have method to encode/decode algorithm. The wiki page +explains the compression algorithm very nicely. +*/ + +#include <assert.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "uthash.h" +#include "utstring.h" +#include "utarray.h" + +#define EOM '#' +#define SYMBOLS "#ABCDEFGHIJKLMNOPQRSTUVWXYZ" + +typedef struct dict { + char* key; + int id; + UT_hash_handle hh; +} Dict; + +typedef struct lzw { + Dict* dict; + UT_array* symbols; +} LZW; + +int bits_width(int n) { + int width = 0; + while (n > 0) { + n /= 2; + width++; + } + return width; +} + +void output_bits(UT_string* result, int n, int width) { + UT_string* reverse_bits; + utstring_new(reverse_bits); + + while (width > 0 || n > 0) { + utstring_printf(reverse_bits, "%c", '0' + (n & 1)); + n /= 2; + width--; + } + + for (const char* p = utstring_body(reverse_bits) + utstring_len(reverse_bits) - 1; + p >= utstring_body(reverse_bits); p--) + utstring_printf(result, "%c", *p); + + utstring_free(reverse_bits); +} + +int input_bits(const char** p, int width) { + int result = 0; + while (**p != '\0' && width-- > 0) { + result *= 2; + result += **p == '1' ? 1 : 0; + (*p)++; + } + return result; +} + +void* check_mem(void* p) { + if (!p) { + fputs("out of memory", stderr); + exit(EXIT_FAILURE); + } + return p; +} + +int lzw_last(LZW* lzw) { + return utarray_len(lzw->symbols) - 1; +} + +int lzw_width(LZW* lzw) { + return bits_width(lzw_last(lzw)); +} + +int lzw_next_width(LZW* lzw) { + return bits_width(lzw_last(lzw) + 1); +} + +void lzw_add(LZW* lzw, const char* seq) { + int id = lzw_last(lzw) + 1; + + Dict* elt = check_mem(calloc(1, sizeof(Dict))); + elt->key = check_mem(strdup(seq)); + elt->id = id; + HASH_ADD_KEYPTR(hh, lzw->dict, elt->key, strlen(elt->key), elt); + + utarray_push_back(lzw->symbols, &seq); +} + +LZW* lzw_new() { + LZW* lzw = check_mem(calloc(1, sizeof(LZW))); + utarray_new(lzw->symbols, &ut_str_icd); + + for (const char* p = SYMBOLS; *p; p++) { + char seq[2]; + seq[0] = *p; + seq[1] = '\0'; + lzw_add(lzw, seq); + } + + return lzw; +} + +void lzw_free(LZW* lzw) { + Dict* elt, * tmp; + + HASH_ITER(hh, lzw->dict, elt , tmp) { + HASH_DEL(lzw->dict, elt); + free(elt->key); + free(elt); + } + + utarray_free(lzw->symbols); +} + +void lzw_longest_match(LZW* lzw, UT_string* encoded, const char** p) { + UT_string* prefix; + utstring_new(prefix); + + // find longest match + int len = 0; + while (len < strlen(*p)) { + utstring_clear(prefix); + utstring_printf(prefix, "%-.*s", len + 1, *p); + Dict* elt; + HASH_FIND_STR(lzw->dict, utstring_body(prefix), elt); + if (elt == NULL) + break; + len++; + } + + utstring_clear(prefix); + utstring_printf(prefix, "%-.*s", len, *p); + (*p) += len; + + Dict* elt; + HASH_FIND_STR(lzw->dict, utstring_body(prefix), elt); + assert(elt != NULL); + int code = elt->id; + int code_width = lzw_width(lzw); + + // store new prefix in dictionary + if (**p != '\0') { + utstring_printf(prefix, "%c", **p); + lzw_add(lzw, utstring_body(prefix)); + } + + output_bits(encoded, code, code_width); + utstring_free(prefix); +} + +void lzw_encode(LZW* lzw, UT_string* encoded, const char* text_) { + UT_string* text; + utstring_new(text); + for (const char* p = text_; *p; p++) + if (isalpha(*p)) + utstring_printf(text, "%c", toupper(*p)); + utstring_printf(text, "%c", EOM); + + utstring_clear(encoded); + const char* p = utstring_body(text); + while (*p) { + lzw_longest_match(lzw, encoded, &p); + } + + utstring_free(text); +} + +void lzw_decode(LZW* lzw, UT_string* decoded, const char* text) { + const char* p = text; + utstring_clear(decoded); + while (*p) { + int code = input_bits(&p, lzw_width(lzw)); + const char* seq = *(const char**)utarray_eltptr(lzw->symbols, code); + utstring_printf(decoded, "%s", seq); + if (*p) { + int next_width = lzw_next_width(lzw); + const char* p1 = p; + int next_code = input_bits(&p1, next_width); + const char* next_seq= *(const char**)utarray_eltptr(lzw->symbols, next_code); + UT_string* next_prefix; + utstring_new(next_prefix); + utstring_printf(next_prefix, "%s%c", seq, *next_seq); + lzw_add(lzw, utstring_body(next_prefix)); + utstring_free(next_prefix); + } + } + + // remove EOM + utstring_body(decoded)[utstring_len(decoded) - 1] = '\0'; + utstring_len(decoded) = strlen(utstring_body(decoded)); +} + +void usage() { + fputs("usage: ch-2 encode|decode text", stderr); +} + +int main(int argc, char* argv[]) { + if (argc != 3) { + usage(); + return EXIT_FAILURE; + } + + UT_string* result; + utstring_new(result); + LZW* lzw = lzw_new(); + + if (strcmp(argv[1], "encode") == 0) { + lzw_encode(lzw, result, argv[2]); + } + else if (strcmp(argv[1], "decode") == 0) { + lzw_decode(lzw, result, argv[2]); + } + else { + usage(); + return EXIT_FAILURE; + } + + printf("%s\n", utstring_body(result)); + + utstring_free(result); + lzw_free(lzw); +} diff --git a/challenge-022/paulo-custodio/c/utarray.h b/challenge-022/paulo-custodio/c/utarray.h new file mode 100644 index 0000000000..1fe8bc1c74 --- /dev/null +++ b/challenge-022/paulo-custodio/c/utarray.h @@ -0,0 +1,252 @@ +/* +Copyright (c) 2008-2022, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +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 OWNER +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. +*/ + +/* a dynamic array implementation using macros + */ +#ifndef UTARRAY_H +#define UTARRAY_H + +#define UTARRAY_VERSION 2.3.0 + +#include <stddef.h> /* size_t */ +#include <string.h> /* memset, etc */ +#include <stdlib.h> /* exit */ + +#ifdef __GNUC__ +#define UTARRAY_UNUSED __attribute__((__unused__)) +#else +#define UTARRAY_UNUSED +#endif + +#ifndef utarray_oom +#define utarray_oom() exit(-1) +#endif + +typedef void (ctor_f)(void *dst, const void *src); +typedef void (dtor_f)(void *elt); +typedef void (init_f)(void *elt); +typedef struct { + size_t sz; + init_f *init; + ctor_f *copy; + dtor_f *dtor; +} UT_icd; + +typedef struct { + unsigned i,n;/* i: index of next available slot, n: num slots */ + UT_icd icd; /* initializer, copy and destructor functions */ + char *d; /* n slots of size icd->sz*/ +} UT_array; + +#define utarray_init(a,_icd) do { \ + memset(a,0,sizeof(UT_array)); \ + (a)->icd = *(_icd); \ +} while(0) + +#define utarray_done(a) do { \ + if ((a)->n) { \ + if ((a)->icd.dtor) { \ + unsigned _ut_i; \ + for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ + } \ + } \ + free((a)->d); \ + } \ + (a)->n=0; \ +} while(0) + +#define utarray_new(a,_icd) do { \ + (a) = (UT_array*)malloc(sizeof(UT_array)); \ + if ((a) == NULL) { \ + utarray_oom(); \ + } \ + utarray_init(a,_icd); \ +} while(0) + +#define utarray_free(a) do { \ + utarray_done(a); \ + free(a); \ +} while(0) + +#define utarray_reserve(a,by) do { \ + if (((a)->i+(by)) > (a)->n) { \ + char *utarray_tmp; \ + while (((a)->i+(by)) > (a)->n) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ + utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \ + if (utarray_tmp == NULL) { \ + utarray_oom(); \ + } \ + (a)->d=utarray_tmp; \ + } \ +} while(0) + +#define utarray_push_back(a,p) do { \ + utarray_reserve(a,1); \ + if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ + else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ +} while(0) + +#define utarray_pop_back(a) do { \ + if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ + else { (a)->i--; } \ +} while(0) + +#define utarray_extend_back(a) do { \ + utarray_reserve(a,1); \ + if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ + else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ + (a)->i++; \ +} while(0) + +#define utarray_len(a) ((a)->i) + +#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) +#define _utarray_eltptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) + +#define utarray_insert(a,p,j) do { \ + if ((j) > (a)->i) utarray_resize(a,j); \ + utarray_reserve(a,1); \ + if ((j) < (a)->i) { \ + memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ + ((a)->i - (j))*((a)->icd.sz)); \ + } \ + if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ + else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ + (a)->i++; \ +} while(0) + +#define utarray_inserta(a,w,j) do { \ + if (utarray_len(w) == 0) break; \ + if ((j) > (a)->i) utarray_resize(a,j); \ + utarray_reserve(a,utarray_len(w)); \ + if ((j) < (a)->i) { \ + memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ + _utarray_eltptr(a,j), \ + ((a)->i - (j))*((a)->icd.sz)); \ + } \ + if ((a)->icd.copy) { \ + unsigned _ut_i; \ + for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ + (a)->icd.copy(_utarray_eltptr(a, (j) + _ut_i), _utarray_eltptr(w, _ut_i)); \ + } \ + } else { \ + memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ + utarray_len(w)*((a)->icd.sz)); \ + } \ + (a)->i += utarray_len(w); \ +} while(0) + +#define utarray_resize(dst,num) do { \ + unsigned _ut_i; \ + if ((dst)->i > (unsigned)(num)) { \ + if ((dst)->icd.dtor) { \ + for (_ut_i = (num); _ut_i < (dst)->i; ++_ut_i) { \ + (dst)->icd.dtor(_utarray_eltptr(dst, _ut_i)); \ + } \ + } \ + } else if ((dst)->i < (unsigned)(num)) { \ + utarray_reserve(dst, (num) - (dst)->i); \< |
