From 22f703cab05b7cd368f4de9e03991b7664dc5022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 1 Sep 2014 13:56:46 +0200 Subject: Initial import of argyll version 1.5.1-8 --- target/alphix.c | 468 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 target/alphix.c (limited to 'target/alphix.c') diff --git a/target/alphix.c b/target/alphix.c new file mode 100644 index 0000000..68dfd48 --- /dev/null +++ b/target/alphix.c @@ -0,0 +1,468 @@ + +/* + * Argyll Color Correction System + * + * Alphabetic index class. + * + * Author: Graeme W. Gill + * Date: 22/8/2005 + * + * Copyright 2005, Graeme W. Gill + * All rights reserved. + * + * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- + * see the License.txt file for licencing details. + */ + +/* TTBD: + It would be nice if it was possible to add a delimeter between + the X and Y identifiers so that number + number or alpha + alpha + identification was possible. + */ + +#include +#include +#include +#include "numsup.h" +#include "alphix.h" + +/* Return the alpha index for the given raw index number */ +/* Return NULL on error */ +static char *torawix(alphix *p, int ix) { + int i, j, n; + int z = 0; + char *rv, *v; + + if (ix < 0 || ix >= p->rmct) + return NULL; /* Index range error */ + + if ((rv = malloc((p->nd+1) * sizeof(char))) == NULL) + return NULL; + + for (v = rv, j = 0, i = p->nd-1; i >= 0; j++, i--) { + char c; + n = ix / p->ds[i].b; + ix -= n * p->ds[i].b; + c = p->ds[i].seq[n]; + if (p->ds[i].z && z == 0 && c == '0') + c = ' '; + if (z != 0 || c != ' ') { + *v++ = p->ds[i].seq[n]; + z = 1; + } + } + *v = '\000'; + + return rv; +} + +/* Return the the raw index number given the alpha index */ +/* return -1 on error */ +static int fromanat(alphix *p, char *ax) { + char *v, *tb, _tb[11]; + int cl; + int i, k, rv = 0; + + if (p->nd > 10) { + if ((tb = malloc((p->nd+1) * sizeof(char))) == NULL) + return -1; /* Malloc error */ + } else + tb = _tb; + + /* Pack the string out to the right number of digits with spaces. */ + cl = strlen(ax); + for (v = tb; cl < p->nd; v++, cl++) + *v = ' '; + strcpy(v, ax); + + /* For each digit, convert to numerical and accumulate */ + for (v = tb, i = p->nd-1; i >= 0; v++, i--) { + for (k = 0; k < p->ds[i].n; k++) { + if (*v == p->ds[i].seq[k] + || (p->ds[i].z && *v == ' ' && p->ds[i].seq[k] == '0')) { + rv += k * p->ds[i].b; + break; + } + } + if (k >= p->ds[i].n) { + if (tb != _tb) + free(tb); + return -1; /* Unknown digit */ + } + } + + if (tb != _tb) + free(tb); + + return rv; +} + +/* Working from the end of the string, */ +/* return a pointer to the maximum number of characters */ +/* that are legaly part of this alpha index. */ +static char *find_start(alphix *p, char *ax) { + int i, k; + char *v; + + v = ax + strlen(ax) - 1; /* start at last character */ + for (i = 0; v >= ax && i < p->nd; v--, i++) { /* working backwards */ + for (k = 0; k < p->ds[i].n; k++) { /* Locate */ + if (*v == p->ds[i].seq[k]) + break; /* Found */ + } + if (k >= p->ds[i].n) /* Not found */ + break; + } + return v+1; +} + +/* Convert from cooked index to raw index. */ +/* Return -1 if out of range */ +static int cookedtoraw(alphix *p, int ix) { + int i; + + if (p->nr == 0) + return ix; + + for (i = 0; i < p->nr; i++) { + if (ix >= p->rs[i].c0 && ix <= p->rs[i].c1) { + ix = ix - p->rs[i].c0 + p->rs[i].r0; + return ix; + } + } + return -1; +} + +/* Convert from raw index to cooked index. */ +/* Return -1 if out of range */ +static int rawtocooked(alphix *p, int ix) { + int i; + + if (p->nr == 0) + return ix; + + for (i = 0; i < p->nr; i++) { + if (ix >= p->rs[i].r0 && ix <= p->rs[i].r1) { + ix = ix - p->rs[i].r0 + p->rs[i].c0; + return ix; + } + } + return -1; +} + +/* Return the maximum possible length of count */ +static int alphix_maxlen(alphix *p) { + return p->cmct; +} + +/* Return the alpha index for the given index number (0 based) */ +/* Return NULL on error */ +/* (Free after use) */ +static char *alphix_aix(alphix *p, int ix) { + if ((ix = cookedtoraw(p, ix)) < 0) + return NULL; + return torawix(p, ix); +} + +/* Return the index number for the given alpha index */ +int alphix_nix(alphix *p, char *ax) { + int rv; + if ((rv = fromanat(p, ax)) < 0) + return -1; + return rawtocooked(p, rv); +} + +/* Destroy ourselves */ +static void +alphix_del(alphix *p) { + int i; + for (i = 0; i < p->nd; i++) + free(p->ds[i].seq); + free (p->ds); + free (p->rs); + free (p); +} + +/* Constructor: */ +alphix *new_alphix(char *pattern) { + alphix *p; + char *pp = pattern; + int i; + + if ((p = (alphix *)calloc(1,sizeof(alphix))) == NULL) + error("alphix: malloc failed"); + + p->maxlen = alphix_maxlen; + p->aix = alphix_aix; + p->nix = alphix_nix; + p->del = alphix_del; + + /* We now need to parse the pattern to setup our index sequence: */ + /* For all digits */ + for (p->nd = 0; ; p->nd++) { + + if (*pp == '\000' || *pp == ';') { + break; + } + + /* We are starting a new digit sequence */ + if (p->nd >= p->_nd) { /* Allocate space for current digit */ + p->_nd = 2 + p->_nd; + if ((p->ds = (dig *)realloc(p->ds, p->_nd * sizeof(dig))) == NULL) + error ("alphix: realloc failed"); + } + + p->ds[p->nd].n = 0; + p->ds[p->nd].seq = NULL; + p->ds[p->nd]._n = 0; + p->ds[p->nd].z = 0; + + /* For all symbols in this digit */ + for (p->ds[p->nd].n = 0; ;) { + char c, c1, c2; + + /* We are adding another character to the sequence */ + if (*pp == '\000' || *pp == ';' || *pp == ',') + break; /* Done this digit */ + if (pp[1] == '-' && pp[2] != '\000' && pp[2] != ';' && pp[2] != ',') { + c1 = pp[0]; + c2 = pp[2]; + pp += 3; + } else { + c1 = c2 = *pp; + pp++; + } + if (c1 == '@') { + c1 = '0'; + p->ds[p->nd].z = 1; + } + if (c2 == '@') { + c2 = '0'; + p->ds[p->nd].z = 1; + } + + /* Expand digit sequence */ + for (c = c1; c <= c2; c++) { + + if (p->ds[p->nd].n >= p->ds[p->nd]._n) { /* Allocate space for next character */ + p->ds[p->nd]._n = 20 + p->ds[p->nd]._n; + if ((p->ds[p->nd].seq = (char *)realloc(p->ds[p->nd].seq, p->ds[p->nd]._n * sizeof(char))) == NULL) + error ("alphix: realloc failed"); + } + p->ds[p->nd].seq[p->ds[p->nd].n++] = c; + } + } + if (*pp == '\000' || *pp == ';') + continue; + pp++; + + } + + /* Compute the native maximum index count */ + for (p->rmct = 1, i = 0; i < p->nd; i++) { + p->ds[i].b = p->rmct; + p->rmct *= p->ds[i].n; + } + + /* Search for valid ranges */ + if (*pp == ';') { + char *v, *tb, _tb[11]; + + pp++; + if (p->nd > 10) { + if ((tb = malloc((p->nd+1) * sizeof(char))) == NULL) + error ("alphix: malloc failed"); + } else + tb = _tb; + + /* For each range */ + for (p->nr = 0; ; p->nr++) { + + if (*pp == '\000' || *pp == ';') + break; + + /* We are adding a new range */ + if (p->nr >= p->_nr) { /* Allocate space for current range */ + p->_nr = 2 + p->_nr; + if ((p->rs = (rngsq *)realloc(p->rs, p->_nr * sizeof(rngsq))) == NULL) + error ("alphix: realloc failed"); + } + + /* Locate the end of the range start */ + for(v = tb; *pp != '\000' && *pp != '-' && *pp != ','; v++, pp++) + *v = *pp; + *v = '\000'; + p->rs[p->nr].r0 = p->rs[p->nr].r1 = fromanat(p, tb); + if (p->rs[p->nr].r0 < 0) + error("alphix: range start definition error on '%s'",tb); + + + if (*pp != '-') { /* oops - bad definition */ + error("alphix: range definition error - missing '-'"); + } + + /* Locate the end of the range end */ + for(v = tb, pp++; *pp != '\000' && *pp != ','; v++, pp++) + *v = *pp; + *v = '\000'; + p->rs[p->nr].r1 = fromanat(p, tb); + if (p->rs[p->nr].r1 < 0) + error("alphix: range end definition error on '%s'",tb); + + if (p->rs[p->nr].r1 < p->rs[p->nr].r0) /* Hmm */ + error("alphix: range definition error, end < start "); + + /* Compute cooked index range */ + p->rs[p->nr].c0 = 0; + p->rs[p->nr].c1 = p->rs[p->nr].r1 - p->rs[p->nr].r0; + if (p->nr > 0) { + int ofs = p->rs[p->nr-1].c1+1; + p->rs[p->nr].c0 += ofs; + p->rs[p->nr].c1 += ofs; + } + + if (*pp == '\000' || *pp == ';') + continue; + pp++; + } + + if (tb != _tb) + free(tb); + } + + /* Compute cooked actual range */ + p->cmct = p->rmct; + if (p->nr > 0) { + p->cmct = p->rs[p->nr-1].c1+1; + } + +#ifdef NEVER + // ########################################################### + /* Debug stuff */ + printf("~1 There are %d digits, %d ranges, raw max = %d, cooked max = %d\n", + p->nd,p->nr,p->rmct, p->maxlen(p)); + + /* Digit sequences */ + for (i = 0; i < p->nd; i++) { + printf(" ~1 Digit %d has %d symbols\n",i,p->ds[i].n); + for (j = 0; j < p->ds[i].n; j++) + printf(" ~1 symbol %d = '%c'\n",j,p->ds[i].seq[j]); + } + + /* Ranges */ + for (i = 0; i < p->nr; i++) { + printf(" ~1 Range %d is raw %d - %d, cooked %d - %d\n", + i,p->rs[i].r0, p->rs[i].r1, p->rs[i].c0, p->rs[i].c1); + } + + /* Itterate the sequence */ + for (i = 0; i < p->cmct; i++) { + char *v; + v = p->aix(p, i); + printf("ix %d -> '%s'\n",i,v); + free(v); + } + // ########################################################### +#endif /* NEVER */ + + return p; +} + + +/* ==================================================================== */ +/* Utility function: */ +/* Given the strip and patch alphix objects, and order flag, */ +/* Return a patch location. Free the returned string after use. */ +/* Return NULL on error */ +char *patch_location( + alphix *saix, /* Strip alpha index object */ + alphix *paix, /* Patch alpha index object */ + int ixord, /* Index order, 0 = strip then patch */ + int six, /* Strip index */ + int pix /* Patch index */ +) { + char *sl, *pl, *rv; + int ll; + + if ((sl = saix->aix(saix, six)) == NULL) + return NULL; + + if ((pl = paix->aix(paix, pix)) == NULL) { + free (sl); + return NULL; + } + ll = strlen(sl) + strlen(pl) + 1; + if ((rv = malloc(ll * sizeof(char))) == NULL) { + free (pl); + free (sl); + return NULL; + } + + if (ixord == 0) { + strcpy (rv, sl); + strcat (rv, pl); + } else { + strcpy (rv, pl); + strcat (rv, sl); + } + return rv; +} + +/* ==================================================================== */ +/* Utility function: */ +/* Given the strip and patch alphix objects, and order flag, */ +/* and a corresonding patch location string, return an index */ +/* number suitable for sorting location strings. */ +/* The sort order is in order of strips, then patches within each strip */ +/* Return -1 on error */ +int patch_location_order( + alphix *saix, /* Strip alpha index object */ + alphix *paix, /* Patch alpha index object */ + int ixord, /* Index order, 0 = strip then patch */ + char *_ax /* Patch location string */ +) { + char *ax; /* Copy of input string */ + char *v; + alphix *rh; /* Least significant, right hand alphix */ + alphix *lh; /* Most significant, left hand alphix */ + int ri, li; /* Right hand and left hand index numbers */ + + if ((ax = malloc(strlen(_ax)+1)) == NULL) + return -1; + strcpy(ax,_ax); + + if (ixord == 0) { + lh = saix; /* Strip is left hand */ + rh = paix; /* Patch is right hand */ + } else { + rh = saix; /* Strip is right hand */ + lh = paix; /* Patch is left hand */ + } + + /* We need to identify the boundary between */ + /* the right hand and left hand indexes. */ + /* We assume that the sequences are distinguishable ... */ + v = find_start(rh, ax); + + ri = rh->nix(rh, v); + *v = '\000'; + li = lh->nix(lh, ax); + free(ax); + if (ri < 0 || li < 0) + return -1; + + if (ixord == 0) /* Strip is left hand */ + return li * rh->cmct + ri; + else + return ri * lh->cmct + li; +} + + + + + + + + + + -- cgit v1.2.3