Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/leptonica/src/stringcode.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/leptonica/src/stringcode.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,785 @@ +/*====================================================================* + - Copyright (C) 2001 Leptonica. 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 ANY + - 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. + *====================================================================*/ + +/*! + * \file stringcode.c + * <pre> + * + * Generation of code for storing and extracting serializable + * leptonica objects (such as pixa, recog, ...). + * + * The input is a set of files with serialized data. + * The output is two files, that must be compiled and linked: + * ~ autogen.*.c: code for base64 unencoding the strings and + * deserializing the result. + * ~ autogen.*.h: function prototypes and base64 encoded strings + * of the input data + * + * This should work for any data structures in leptonica that have + * *Write() and *Read() serialization functions. An array of 20 + * of these, including the Pix, is given below. (The Pix is a special + * case, because it is serialized by standardized compression + * techniques, instead of a file format determined by leptonica.) + * + * Each time the generator function is invoked, three sets of strings are + * produced, which are written into their respective string arrays: + * ~ string of serialized, gzipped and base 64 encoded data + * ~ case string for base64 decoding, gunzipping and deserialization, + * to return the data struct in memory + * ~ description string for selecting which struct to return + * To create the two output files, a finalize function is invoked. + * + * There are two ways to do this, both shown in prog/autogentest1.c. + * ~ Explicitly call strcodeGenerate() for each file with the + * serialized data structure, followed by strcodeFinalize(). + * ~ Put the filenames of the serialized data structures in a file, + * and call strcodeCreateFromFile(). + * + * The generated code in autogen.X.c and autogen.X.h (where X is an + * integer supplied to strcodeCreate()) is then compiled, and the + * original data can be regenerated using the function l_autodecode_X(). + * A test example is found in the two prog files: + * prog/autogentest1.c -- generates autogen.137.c, autogen.137.h + * prog/autogentest2.c -- uses autogen.137.c, autogen.137.h + * In general, the generator (e.g., autogentest1) would be compiled and + * run before compiling and running the application (e.g., autogentest2). + * + * L_STRCODE *strcodeCreate() + * static void strcodeDestroy() (called as part of finalize) + * void strcodeCreateFromFile() + * l_int32 strcodeGenerate() + * l_int32 strcodeFinalize() + * l_int32 l_getStructStrFromFile() (useful externally) + * + * Static helpers + * static l_int32 l_getIndexFromType() + * static l_int32 l_getIndexFromStructname() + * static l_int32 l_getIndexFromFile() + * static char *l_genDataString() + * static char *l_genCaseString() + * static char *l_genDescrString() + * </pre> + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" +#include "stringcode.h" + +#define TEMPLATE1 "stringtemplate1.txt" /* for assembling autogen.*.c */ +#define TEMPLATE2 "stringtemplate2.txt" /* for assembling autogen.*.h */ + + /*! Associations between names and functions */ +struct L_GenAssoc +{ + l_int32 index; + char type[16]; /* e.g., "PIXA" */ + char structname[16]; /* e.g., "Pixa" */ + char reader[16]; /* e.g., "pixaRead" */ + char memreader[20]; /* e.g., "pixaReadMem" */ +}; + + /*! Number of serializable data types */ +static const l_int32 l_ntypes = 19; + /*! Serializable data types */ +static const struct L_GenAssoc l_assoc[] = { + {0, "INVALID", "invalid", "invalid", "invalid" }, + {1, "BOXA", "Boxa", "boxaRead", "boxaReadMem" }, + {2, "BOXAA", "Boxaa", "boxaaRead", "boxaaReadMem" }, + {3, "L_DEWARP", "Dewarp", "dewarpRead", "dewarpReadMem" }, + {4, "L_DEWARPA", "Dewarpa", "dewarpaRead", "dewarpaReadMem" }, + {5, "L_DNA", "L_Dna", "l_dnaRead", "l_dnaReadMem" }, + {6, "L_DNAA", "L_Dnaa", "l_dnaaRead", "l_dnaaReadMem" }, + {7, "DPIX", "DPix", "dpixRead", "dpixReadMem" }, + {8, "FPIX", "FPix", "fpixRead", "fpixReadMem" }, + {9, "NUMA", "Numa", "numaRead", "numaReadMem" }, + {10, "NUMAA", "Numaa", "numaaRead", "numaaReadMem" }, + {11, "PIX", "Pix", "pixRead", "pixReadMem" }, + {12, "PIXA", "Pixa", "pixaRead", "pixaReadMem" }, + {13, "PIXAA", "Pixaa", "pixaaRead", "pixaaReadMem" }, + {14, "PIXACOMP", "Pixacomp", "pixacompRead", "pixacompReadMem" }, + {15, "PIXCMAP", "Pixcmap", "pixcmapRead", "pixcmapReadMem" }, + {16, "PTA", "Pta", "ptaRead", "ptaReadMem" }, + {17, "PTAA", "Ptaa", "ptaaRead", "ptaaReadMem" }, + {18, "RECOG", "Recog", "recogRead", "recogReadMem" }, + {19, "SARRAY", "Sarray", "sarrayRead", "sarrayReadMem" } +}; + +static l_int32 l_getIndexFromType(const char *type, l_int32 *pindex); +static l_int32 l_getIndexFromStructname(const char *sn, l_int32 *pindex); +static l_int32 l_getIndexFromFile(const char *file, l_int32 *pindex); +static char *l_genDataString(const char *filein, l_int32 ifunc); +static char *l_genCaseString(l_int32 ifunc, l_int32 itype); +static char *l_genDescrString(const char *filein, l_int32 ifunc, l_int32 itype); + +/*---------------------------------------------------------------------*/ +/* Stringcode functions */ +/*---------------------------------------------------------------------*/ +/*! + * \brief strcodeCreate() + * + * \param[in] fileno integer that labels the two output files + * \return initialized L_StrCode, or NULL on error + * + * <pre> + * Notes: + * (1) This struct exists to build two files containing code for + * any number of data objects. The two files are named + * autogen.[fileno].c + * autogen.[fileno].h + * </pre> + */ +L_STRCODE * +strcodeCreate(l_int32 fileno) +{ +L_STRCODE *strcode; + + lept_mkdir("lept/auto"); + + if ((strcode = (L_STRCODE *)LEPT_CALLOC(1, sizeof(L_STRCODE))) == NULL) + return (L_STRCODE *)ERROR_PTR("strcode not made", __func__, NULL); + + strcode->fileno = fileno; + strcode->function = sarrayCreate(0); + strcode->data = sarrayCreate(0); + strcode->descr = sarrayCreate(0); + return strcode; +} + + +/*! + * \brief strcodeDestroy() + * + * \param[out] pstrcode will be set to null after destroying the sarrays + * \return void + */ +static void +strcodeDestroy(L_STRCODE **pstrcode) +{ +L_STRCODE *strcode; + + if (pstrcode == NULL) { + L_WARNING("ptr address is null!\n", __func__); + return; + } + + if ((strcode = *pstrcode) == NULL) + return; + + sarrayDestroy(&strcode->function); + sarrayDestroy(&strcode->data); + sarrayDestroy(&strcode->descr); + LEPT_FREE(strcode); + *pstrcode = NULL; +} + + +/*! + * \brief strcodeCreateFromFile() + * + * \param[in] filein containing filenames of serialized data + * \param[in] fileno integer that labels the two output files + * \param[in] outdir [optional] if null, files are made in /tmp/lept/auto + * \return 0 if OK, 1 on error + * + * <pre> + * Notes: + * (1) The %filein has one filename on each line. + * Comment lines begin with "#". + * (2) The output is 2 files: + * autogen.[fileno].c + * autogen.[fileno].h + * </pre> + */ +l_ok +strcodeCreateFromFile(const char *filein, + l_int32 fileno, + const char *outdir) +{ +char *fname; +const char *type; +l_uint8 *data; +size_t nbytes; +l_int32 i, n, index; +SARRAY *sa; +L_STRCODE *strcode; + + if (!filein) + return ERROR_INT("filein not defined", __func__, 1); + + if ((data = l_binaryRead(filein, &nbytes)) == NULL) + return ERROR_INT("data not read from file", __func__, 1); + sa = sarrayCreateLinesFromString((char *)data, 0); + LEPT_FREE(data); + if (!sa) + return ERROR_INT("sa not made", __func__, 1); + if ((n = sarrayGetCount(sa)) == 0) { + sarrayDestroy(&sa); + return ERROR_INT("no filenames in the file", __func__, 1); + } + + strcode = strcodeCreate(fileno); + + for (i = 0; i < n; i++) { + fname = sarrayGetString(sa, i, L_NOCOPY); + if (fname[0] == '#') continue; + if (l_getIndexFromFile(fname, &index)) { + L_ERROR("File %s has no recognizable type\n", __func__, fname); + } else { + type = l_assoc[index].type; + L_INFO("File %s is type %s\n", __func__, fname, type); + strcodeGenerate(strcode, fname, type); + } + } + strcodeFinalize(&strcode, outdir); + sarrayDestroy(&sa); + return 0; +} + + +/*! + * \brief strcodeGenerate() + * + * \param[in] strcode for accumulating data + * \param[in] filein input file with serialized data + * \param[in] type of data; use the typedef string + * \return 0 if OK, 1 on error. + * + * <pre> + * Notes: + * (1) The generated function name is + * l_autodecode_[fileno]() + * where [fileno] is the index label for the pair of output files. + * (2) To deserialize this data, the function is called with the + * argument 'ifunc', which increments each time strcodeGenerate() + * is called. + * </pre> + */ +l_ok +strcodeGenerate(L_STRCODE *strcode, + const char *filein, + const char *type) +{ +char *strdata, *strfunc, *strdescr; +l_int32 itype; + + if (!strcode) + return ERROR_INT("strcode not defined", __func__, 1); + if (!filein) + return ERROR_INT("filein not defined", __func__, 1); + if (!type) + return ERROR_INT("type not defined", __func__, 1); + + /* Get the index corresponding to type and validate */ + if (l_getIndexFromType(type, &itype) == 1) + return ERROR_INT("data type unknown", __func__, 1); + + /* Generate the encoded data string */ + if ((strdata = l_genDataString(filein, strcode->ifunc)) == NULL) + return ERROR_INT("strdata not made", __func__, 1); + sarrayAddString(strcode->data, strdata, L_INSERT); + + /* Generate the case data for the decoding function */ + strfunc = l_genCaseString(strcode->ifunc, itype); + sarrayAddString(strcode->function, strfunc, L_INSERT); + + /* Generate row of table for function type selection */ + strdescr = l_genDescrString(filein, strcode->ifunc, itype); + sarrayAddString(strcode->descr, strdescr, L_INSERT); + + strcode->n++; + strcode->ifunc++; + return 0; +} + + +/*! + * \brief strcodeFinalize() + * + * \param[in,out] pstrcode destroys and sets to null after .c and .h files + * have been generated + * \param[in] outdir [optional] if NULL, make files in /tmp/lept/auto + * \return 0 if OK; 1 on error + */ +l_int32 +strcodeFinalize(L_STRCODE **pstrcode, + const char *outdir) +{ +char buf[256]; +char *filestr, *casestr, *descr, *datastr, *realoutdir; +l_int32 actstart, end, newstart, fileno, nbytes; +size_t size; +L_STRCODE *strcode; +SARRAY *sa1, *sa2, *sa3; + + lept_mkdir("lept/auto"); + + if (!pstrcode || *pstrcode == NULL) + return ERROR_INT("No input data", __func__, 1); + strcode = *pstrcode; + if (!outdir) { + L_INFO("no outdir specified; writing to /tmp/lept/auto\n", __func__); + realoutdir = stringNew("/tmp/lept/auto"); + } else { + realoutdir = stringNew(outdir); + } + + /* ------------------------------------------------------- */ + /* Make the output autogen.*.c file */ + /* ------------------------------------------------------- */ + + /* Make array of textlines from TEMPLATE1 */ + filestr = (char *)l_binaryRead(TEMPLATE1, &size); + sa1 = sarrayCreateLinesFromString(filestr, 1); + LEPT_FREE(filestr); + sa3 = sarrayCreate(0); + + /* Copyright notice */ + sarrayParseRange(sa1, 0, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa1, actstart, end); + + /* File name comment */ + fileno = strcode->fileno; + snprintf(buf, sizeof(buf), " * autogen.%d.c", fileno); + sarrayAddString(sa3, buf, L_COPY); + + /* More text */ + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa1, actstart, end); + + /* Description of function types by index */ + descr = sarrayToString(strcode->descr, 1); + descr[strlen(descr) - 1] = '\0'; + sarrayAddString(sa3, descr, L_INSERT); + + /* Includes */ + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa1, actstart, end); + snprintf(buf, sizeof(buf), "#include \"autogen.%d.h\"", fileno); + sarrayAddString(sa3, buf, L_COPY); + + /* Header for auto-generated deserializers */ + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa1, actstart, end); + + /* Function name (as comment) */ + snprintf(buf, sizeof(buf), " * \\brief l_autodecode_%d()", fileno); + sarrayAddString(sa3, buf, L_COPY); + + /* Input and return values */ + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa1, actstart, end); + + /* Function name */ + snprintf(buf, sizeof(buf), "l_autodecode_%d(l_int32 index)", fileno); + sarrayAddString(sa3, buf, L_COPY); + + /* Stack vars */ + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa1, actstart, end); + + /* Declaration of nfunc on stack */ + snprintf(buf, sizeof(buf), "l_int32 nfunc = %d;\n", strcode->n); + sarrayAddString(sa3, buf, L_COPY); + + /* Declaration of PROCNAME */ + snprintf(buf, sizeof(buf), " PROCNAME(\"l_autodecode_%d\");", fileno); + sarrayAddString(sa3, buf, L_COPY); + + /* Test input variables */ + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa1, actstart, end); + + /* Insert case string */ + casestr = sarrayToString(strcode->function, 0); + casestr[strlen(casestr) - 1] = '\0'; + sarrayAddString(sa3, casestr, L_INSERT); + + /* End of function */ + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa1, actstart, end); + + /* Flatten to string and output to autogen*.c file */ + filestr = sarrayToString(sa3, 1); + nbytes = strlen(filestr); + snprintf(buf, sizeof(buf), "%s/autogen.%d.c", realoutdir, fileno); + l_binaryWrite(buf, "w", filestr, nbytes); + LEPT_FREE(filestr); + sarrayDestroy(&sa1); + sarrayDestroy(&sa3); + + /* ------------------------------------------------------- */ + /* Make the output autogen.*.h file */ + /* ------------------------------------------------------- */ + + /* Make array of textlines from TEMPLATE2 */ + filestr = (char *)l_binaryRead(TEMPLATE2, &size); + sa2 = sarrayCreateLinesFromString(filestr, 1); + LEPT_FREE(filestr); + sa3 = sarrayCreate(0); + + /* Copyright notice */ + sarrayParseRange(sa2, 0, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + + /* File name comment */ + snprintf(buf, sizeof(buf), " * autogen.%d.h", fileno); + sarrayAddString(sa3, buf, L_COPY); + + /* More text */ + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + + /* Beginning header protection */ + snprintf(buf, sizeof(buf), "#ifndef LEPTONICA_AUTOGEN_%d_H\n" + "#define LEPTONICA_AUTOGEN_%d_H", + fileno, fileno); + sarrayAddString(sa3, buf, L_COPY); + + /* Prototype header text */ + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + + /* Prototype declaration */ + snprintf(buf, sizeof(buf), "void *l_autodecode_%d(l_int32 index);", fileno); + sarrayAddString(sa3, buf, L_COPY); + + /* Prototype trailer text */ + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + + /* Insert serialized data strings */ + datastr = sarrayToString(strcode->data, 1); + datastr[strlen(datastr) - 1] = '\0'; + sarrayAddString(sa3, datastr, L_INSERT); + + /* End header protection */ + snprintf(buf, sizeof(buf), "#endif /* LEPTONICA_AUTOGEN_%d_H */", fileno); + sarrayAddString(sa3, buf, L_COPY); + + /* Flatten to string and output to autogen*.h file */ + filestr = sarrayToString(sa3, 1); + nbytes = strlen(filestr); + snprintf(buf, sizeof(buf), "%s/autogen.%d.h", realoutdir, fileno); + l_binaryWrite(buf, "w", filestr, nbytes); + LEPT_FREE(filestr); + LEPT_FREE(realoutdir); + sarrayDestroy(&sa2); + sarrayDestroy(&sa3); + + /* Cleanup */ + strcodeDestroy(pstrcode); + return 0; +} + + +/*! + * \brief l_getStructStrFromFile() + * + * \param[in] filename + * \param[in] field (L_STR_TYPE, L_STR_NAME, L_STR_READER, L_STR_MEMREADER) + * \param[out] pstr struct string for this file + * \return 0 if found, 1 on error. + * + * <pre> + * Notes: + * (1) For example, if %field == L_STR_NAME, and the file is a serialized + * pixa, this will return "Pixa", the name of the struct. + * (2) Caller must free the returned string. + * </pre> + */ +l_int32 +l_getStructStrFromFile(const char *filename, + l_int32 field, + char **pstr) +{ +l_int32 index; + + if (!pstr) + return ERROR_INT("&str not defined", __func__, 1); + *pstr = NULL; + if (!filename) + return ERROR_INT("filename not defined", __func__, 1); + if (field != L_STR_TYPE && field != L_STR_NAME && + field != L_STR_READER && field != L_STR_MEMREADER) + return ERROR_INT("invalid field", __func__, 1); + + if (l_getIndexFromFile(filename, &index)) + return ERROR_INT("index not retrieved", __func__, 1); + if (field == L_STR_TYPE) + *pstr = stringNew(l_assoc[index].type); + else if (field == L_STR_NAME) + *pstr = stringNew(l_assoc[index].structname); + else if (field == L_STR_READER) + *pstr = stringNew(l_assoc[index].reader); + else /* field == L_STR_MEMREADER */ + *pstr = stringNew(l_assoc[index].memreader); + return 0; +} + + +/*---------------------------------------------------------------------*/ +/* Static helpers */ +/*---------------------------------------------------------------------*/ +/*! + * \brief l_getIndexFromType() + * + * \param[in] type e.g., "PIXA" + * \param[out] pindex found index + * \return 0 if found, 1 if not. + * + * <pre> + * Notes: + * (1) For valid type, %found == true and %index > 0. + * </pre> + */ +static l_int32 +l_getIndexFromType(const char *type, + l_int32 *pindex) +{ +l_int32 i, found; + + if (!pindex) + return ERROR_INT("&index not defined", __func__, 1); + *pindex = 0; + if (!type) + return ERROR_INT("type string not defined", __func__, 1); + + found = 0; + for (i = 1; i <= l_ntypes; i++) { + if (strcmp(type, l_assoc[i].type) == 0) { + found = 1; + *pindex = i; + break; + } + } + return !found; +} + + +/*! + * \brief l_getIndexFromStructname() + * + * \param[in] sn structname e.g., "Pixa" + * \param[out] pindex found index + * \return 0 if found, 1 if not. + * + * <pre> + * Notes: + * (1) This is used to identify the type of serialized file; + * the first word in the file is the structname. + * (2) For valid structname, %found == true and %index > 0. + * </pre> + */ +static l_int32 +l_getIndexFromStructname(const char *sn, + l_int32 *pindex) +{ +l_int32 i, found; + + if (!pindex) + return ERROR_INT("&index not defined", __func__, 1); + *pindex = 0; + if (!sn) + return ERROR_INT("sn string not defined", __func__, 1); + + found = 0; + for (i = 1; i <= l_ntypes; i++) { + if (strcmp(sn, l_assoc[i].structname) == 0) { + found = 1; + *pindex = i; + break; + } + } + return !found; +} + + +/*! + * \brief l_getIndexFromFile() + * + * \param[in] filename + * \param[out] pindex found index + * \return 0 if found, 1 on error. + */ +static l_int32 +l_getIndexFromFile(const char *filename, + l_int32 *pindex) +{ +char buf[256]; +char *word; +FILE *fp; +l_int32 notfound, format; +SARRAY *sa; + + if (!pindex) + return ERROR_INT("&index not defined", __func__, 1); + *pindex = 0; + if (!filename) + return ERROR_INT("filename not defined", __func__, 1); + + /* Open the stream, read lines until you find one with more + * than a newline, and grab the first word. */ + if ((fp = fopenReadStream(filename)) == NULL) + return ERROR_INT_1("stream not opened", filename, __func__, 1); + do { + if ((fgets(buf, sizeof(buf), fp)) == NULL) { + fclose(fp); + return ERROR_INT_1("fgets read fail", filename, __func__, 1); + } + } while (buf[0] == '\n'); + fclose(fp); + sa = sarrayCreateWordsFromString(buf); + word = sarrayGetString(sa, 0, L_NOCOPY); + + /* Find the index associated with the word. If it is not + * found, test to see if the file is a compressed pix. */ + notfound = l_getIndexFromStructname(word, pindex); + sarrayDestroy(&sa); + if (notfound) { /* maybe a Pix */ + if (findFileFormat(filename, &format) == 0) { + l_getIndexFromStructname("Pix", pindex); + } else { + return ERROR_INT_1("no file type identified", + filename, __func__, 1); + } + } + + return 0; +} + + +/*! + * \brief l_genDataString() + * + * \param[in] filein input file of serialized data + * \param[in] ifunc index into set of functions in output file + * \return encoded ascii data string, or NULL on error reading from file + */ +static char * +l_genDataString(const char *filein, + l_int32 ifunc) +{ +char buf[80]; +char *cdata1, *cdata2, *cdata3; +l_uint8 *data1, *data2; +l_int32 csize1, csize2; +size_t size1, size2; +SARRAY *sa; + + if (!filein) + return (char *)ERROR_PTR("filein not defined", __func__, NULL); + + /* Read it in, gzip it, encode, and reformat. We gzip because some + * serialized data has a significant amount of ascii content. */ + if ((data1 = l_binaryRead(filein, &size1)) == NULL) + return (char *)ERROR_PTR("bindata not returned", __func__, NULL); + data2 = zlibCompress(data1, size1, &size2); + cdata1 = encodeBase64(data2, size2, &csize1); + cdata2 = reformatPacked64(cdata1, csize1, 4, 72, 1, &csize2); + LEPT_FREE(data1); + LEPT_FREE(data2); + LEPT_FREE(cdata1); + + /* Prepend the string declaration signature and put it together */ + sa = sarrayCreate(3); + snprintf(buf, sizeof(buf), "static const char *l_strdata_%d =\n", ifunc); + sarrayAddString(sa, buf, L_COPY); + sarrayAddString(sa, cdata2, L_INSERT); + sarrayAddString(sa, ";\n", L_COPY); + cdata3 = sarrayToString(sa, 0); + sarrayDestroy(&sa); + return cdata3; +} + + +/*! + * \brief l_genCaseString() + * + * \param[in] ifunc index into set of functions in generated file + * \param[in] itype index into type of function to be used + * \return case string for this decoding function + * + * <pre> + * Notes: + * (1) %ifunc and %itype have been validated, so no error can occur + * </pre> + */ +static char * +l_genCaseString(l_int32 ifunc, + l_int32 itype) +{ +char buf[256]; +char *code = NULL; + + snprintf(buf, sizeof(buf), " case %d:\n", ifunc); + stringJoinIP(&code, buf); + snprintf(buf, sizeof(buf), + " data1 = decodeBase64(l_strdata_%d, strlen(l_strdata_%d), " + "&size1);\n", ifunc, ifunc); + stringJoinIP(&code, buf); + stringJoinIP(&code, + " data2 = zlibUncompress(data1, size1, &size2);\n"); + snprintf(buf, sizeof(buf), + " result = (void *)%s(data2, size2);\n", + l_assoc[itype].memreader); + stringJoinIP(&code, buf); + stringJoinIP(&code, " lept_free(data1);\n"); + stringJoinIP(&code, " lept_free(data2);\n"); + stringJoinIP(&code, " break;\n"); + return code; +} + + +/*! + * \brief l_genDescrString() + * + * \param[in] filein input file of serialized data + * \param[in] ifunc index into set of functions in generated file + * \param[in] itype index into type of function to be used + * \return description string for this decoding function + */ +static char * +l_genDescrString(const char *filein, + l_int32 ifunc, + l_int32 itype) +{ +char buf[256]; +char *tail; + + if (!filein) + return (char *)ERROR_PTR("filein not defined", __func__, NULL); + + splitPathAtDirectory(filein, NULL, &tail); + snprintf(buf, sizeof(buf), " * %-2d %-10s %-14s %s", + ifunc, l_assoc[itype].type, l_assoc[itype].reader, tail); + + LEPT_FREE(tail); + return stringNew(buf); +}
