/* * parseForProtos() * * Input: filein (output of cpp) * prestring (<optional> string that prefaces each decl; * use NULL to omit) * Return: parsestr (string of function prototypes), or NULL on error * * Notes: * (1) We parse the output of cpp: * cpp -ansi <filein> * Three plans were attempted, with success on the third. * (2) Plan 1. A cursory examination of the cpp output indicated that * every function was preceeded by a cpp comment statement. * So we just need to look at statements beginning after comments. * Unfortunately, this is NOT the case. Some functions start * without cpp comment lines, typically when there are no * comments in the source that immediately precede the function. * (3) Plan 2. Consider the keywords in the language that start * parts of the cpp file. Some, like 'typedef', 'enum', * 'union' and 'struct', are followed after a while by '{', * and eventually end with '}, plus an optional token and a * final ';' Others, like 'extern' and 'static', are never * the beginnings of global function definitions. Function * prototypes have one or more sets of '(' followed eventually * by a ')', and end with ';'. But function definitions have * tokens, followed by '(', more tokens, ')' and then * immediately a '{'. We would generate a prototype from this * by adding a ';' to all tokens up to the ')'. So we use * these special tokens to decide what we are parsing. And * whenever a function definition is found and the prototype * extracted, we skip through the rest of the function * past the corresponding '}'. This token ends a line, and * is often on a line of its own. But as it turns out, * the only keyword we need to consider is 'static'. * (4) Plan 3. Consider the parentheses and braces for various * declarations. A struct, enum, or union has a pair of * braces followed by a semicolon. They cannot have parentheses * before the left brace, but a struct can have lots of parentheses * within the brace set. A function prototype has no braces. * A function declaration can have sets of left and right * parentheses, but these are followed by a left brace. * So plan 3 looks at the way parentheses and braces are * organized. Once the beginning of a function definition * is found, the prototype is extracted and we search for * the ending right brace. * (5) To find the ending right brace, it is necessary to do some * careful parsing. For example, in this file, we have * left and right braces as characters, and these must not * be counted. Somewhat more tricky, the file fhmtauto.c * generates code, and includes a right brace in a string. * So we must not include braces that are in strings. But how * do we know if something is inside a string? Keep state, * starting with not-inside, and every time you hit a double quote * that is not escaped, toggle the condition. Any brace * found in the state of being within a string is ignored. * (6) When a prototype is extracted, it is put in a canonical * form (i.e., cleaned up). Finally, we check that it is * not static and save it. (If static, it is ignored). * (7) The @prestring for unix is NULL; it is included here so that * you can use Microsoft's declaration for importing or * exporting to a dll. See environ.h for examples of use. * Here, we set: @prestring = "LEPT_DLL ". Note in particular * the space character that will separate 'LEPT_DLL' from * the standard unix prototype that follows. */ char * parseForProtos(const char *filein, const char *prestring) { char *strdata, *str, *newstr, *parsestr, *secondword; l_int32 nbytes, start, next, stop, charindex, found; SARRAY *sa, *saout, *satest; PROCNAME("parseForProtos"); if (!filein) return (char *)ERROR_PTR("filein not defined", procName, NULL); /* Read in the cpp output into memory, one string for each * line in the file, omitting blank lines. */ strdata = (char *)arrayRead(filein, &nbytes); sa = sarrayCreateLinesFromString(strdata, 0); saout = sarrayCreate(0); next = 0; while (1) { /* repeat after each non-static prototype is extracted */ searchForProtoSignature(sa, next, &start, &stop, &charindex, &found); if (!found) break; /* fprintf(stderr, " start = %d, stop = %d, charindex = %d\n", start, stop, charindex); */ str = captureProtoSignature(sa, start, stop, charindex); /* Make sure it is not static. Note that 'extern' has * been prepended to the prototype, so the 'static' * keyword, if it exists, would be the second word. */ satest = sarrayCreateWordsFromString(str); secondword = sarrayGetString(satest, 1, 0); if (strcmp(secondword, "static")) { /* not static */ if (prestring) { /* prepend it to the prototype */ newstr = stringJoin(prestring, str); sarrayAddString(saout, newstr, L_INSERT); FREE(str); } else sarrayAddString(saout, str, L_INSERT); } else FREE(str); sarrayDestroy(&satest); skipToEndOfFunction(sa, stop, charindex, &next); if (next == -1) break; } /* Flatten into a string with newlines between prototypes */ parsestr = sarrayToString(saout, 1); FREE(strdata); sarrayDestroy(&sa); sarrayDestroy(&saout); return parsestr; }
/*! * \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_int32 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; PROCNAME("strcodeCreateFromFile"); if (!filein) return ERROR_INT("filein not defined", procName, 1); if ((data = l_binaryRead(filein, &nbytes)) == NULL) return ERROR_INT("data not read from file", procName, 1); sa = sarrayCreateLinesFromString((char *)data, 0); LEPT_FREE(data); if (!sa) return ERROR_INT("sa not made", procName, 1); if ((n = sarrayGetCount(sa)) == 0) { sarrayDestroy(&sa); return ERROR_INT("no filenames in the file", procName, 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", procName, fname); } else { type = l_assoc[index].type; L_INFO("File %s is type %s\n", procName, fname, type); strcodeGenerate(strcode, fname, type); } } strcodeFinalize(&strcode, outdir); return 0; }
/*! * kernelCreateFromFile() * * Input: filename * Return: kernel, or null on error * * Notes: * (1) The file contains, in the following order: * - Any number of comment lines starting with '#' are ignored * - The height and width of the kernel * - The y and x values of the kernel origin * - The kernel data, formatted as lines of numbers (integers * or floats) for the kernel values in row-major order, * and with no other punctuation. * (Note: this differs from kernelCreateFromString(), * where each line must begin and end with a double-quote * to tell the compiler it's part of a string.) * - The kernel specification ends when a blank line, * a comment line, or the end of file is reached. * (2) All lines must be left-justified. * (3) See kernelCreateFromString() for a description of the string * format for the kernel data. As an example, here are the lines * of a valid kernel description file In the file, all lines * are left-justified: * # small 3x3 kernel * 3 3 * 1 1 * 25.5 51 24.3 * 70.2 146.3 73.4 * 20 50.9 18.4 */ L_KERNEL * kernelCreateFromFile(const char *filename) { char *filestr, *line; l_int32 nlines, i, j, first, index, w, h, cx, cy, n; l_float32 val; size_t size; NUMA *na, *nat; SARRAY *sa; L_KERNEL *kel; PROCNAME("kernelCreateFromFile"); if (!filename) return (L_KERNEL *)ERROR_PTR("filename not defined", procName, NULL); filestr = (char *)l_binaryRead(filename, &size); sa = sarrayCreateLinesFromString(filestr, 1); FREE(filestr); nlines = sarrayGetCount(sa); /* Find the first data line. */ for (i = 0; i < nlines; i++) { line = sarrayGetString(sa, i, L_NOCOPY); if (line[0] != '#') { first = i; break; } } /* Find the kernel dimensions and origin location. */ line = sarrayGetString(sa, first, L_NOCOPY); if (sscanf(line, "%d %d", &h, &w) != 2) return (L_KERNEL *)ERROR_PTR("error reading h,w", procName, NULL); line = sarrayGetString(sa, first + 1, L_NOCOPY); if (sscanf(line, "%d %d", &cy, &cx) != 2) return (L_KERNEL *)ERROR_PTR("error reading cy,cx", procName, NULL); /* Extract the data. This ends when we reach eof, or when we * encounter a line of data that is either a null string or * contains just a newline. */ na = numaCreate(0); for (i = first + 2; i < nlines; i++) { line = sarrayGetString(sa, i, L_NOCOPY); if (line[0] == '\0' || line[0] == '\n' || line[0] == '#') break; nat = parseStringForNumbers(line, " \t\n"); numaJoin(na, nat, 0, -1); numaDestroy(&nat); } sarrayDestroy(&sa); n = numaGetCount(na); if (n != w * h) { numaDestroy(&na); fprintf(stderr, "w = %d, h = %d, num ints = %d\n", w, h, n); return (L_KERNEL *)ERROR_PTR("invalid integer data", procName, NULL); } kel = kernelCreate(h, w); kernelSetOrigin(kel, cy, cx); index = 0; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { numaGetFValue(na, index, &val); kernelSetElement(kel, i, j, val); index++; } } numaDestroy(&na); return kel; }
int main(int argc, char **argv) { l_int32 ignore; size_t nbytesin, nbytesout; char *infile, *instring, *outstring; SARRAY *sa1, *sa2, *sa3, *sa4, *sa5; char buf[256]; static char mainName[] = "string_reg"; if (argc != 2) return ERROR_INT(" Syntax: string_reg infile", mainName, 1); infile = argv[1]; instring = (char *)l_binaryRead(infile, &nbytesin); if (!instring) return ERROR_INT("file not read", mainName, 1); sa1 = sarrayCreateWordsFromString(instring); sa2 = sarrayCreateLinesFromString(instring, 0); sa3 = sarrayCreateLinesFromString(instring, 1); outstring = sarrayToString(sa1, 0); nbytesout = strlen(outstring); l_binaryWrite("/tmp/junk1.txt", "w", outstring, nbytesout); lept_free(outstring); outstring = sarrayToString(sa1, 1); nbytesout = strlen(outstring); l_binaryWrite("/tmp/junk2.txt", "w", outstring, nbytesout); lept_free(outstring); outstring = sarrayToString(sa2, 0); nbytesout = strlen(outstring); l_binaryWrite("/tmp/junk3.txt", "w", outstring, nbytesout); lept_free(outstring); outstring = sarrayToString(sa2, 1); nbytesout = strlen(outstring); l_binaryWrite("/tmp/junk4.txt", "w", outstring, nbytesout); lept_free(outstring); outstring = sarrayToString(sa3, 0); nbytesout = strlen(outstring); l_binaryWrite("/tmp/junk5.txt", "w", outstring, nbytesout); lept_free(outstring); outstring = sarrayToString(sa3, 1); nbytesout = strlen(outstring); l_binaryWrite("/tmp/junk6.txt", "w", outstring, nbytesout); lept_free(outstring); sprintf(buf, "diff -s /tmp/junk6.txt %s", infile); ignore = system(buf); /* write/read/write; compare /tmp/junkout5 with /tmp/junkout6 */ sarrayWrite("/tmp/junk7.txt", sa2); sarrayWrite("/tmp/junk8.txt", sa3); sa4 = sarrayRead("/tmp/junk8.txt"); sarrayWrite("/tmp/junk9.txt", sa4); sa5 = sarrayRead("/tmp/junk9.txt"); ignore = system("diff -s /tmp/junk8.txt /tmp/junk9.txt"); sarrayDestroy(&sa1); sarrayDestroy(&sa2); sarrayDestroy(&sa3); sarrayDestroy(&sa4); sarrayDestroy(&sa5); lept_free(instring); return 0; }
/* * parseForProtos() * * Input: filein (output of cpp) * prestring (<optional> string that prefaces each decl; * use NULL to omit) * Return: parsestr (string of function prototypes), or NULL on error * * Notes: * (1) We parse the output of cpp: * cpp -ansi <filein> * Three plans were attempted, with success on the third. * (2) Plan 1. A cursory examination of the cpp output indicated that * every function was preceded by a cpp comment statement. * So we just need to look at statements beginning after comments. * Unfortunately, this is NOT the case. Some functions start * without cpp comment lines, typically when there are no * comments in the source that immediately precede the function. * (3) Plan 2. Consider the keywords in the language that start * parts of the cpp file. Some, like 'typedef', 'enum', * 'union' and 'struct', are followed after a while by '{', * and eventually end with '}, plus an optional token and a * final ';' Others, like 'extern' and 'static', are never * the beginnings of global function definitions. Function * prototypes have one or more sets of '(' followed eventually * by a ')', and end with ';'. But function definitions have * tokens, followed by '(', more tokens, ')' and then * immediately a '{'. We would generate a prototype from this * by adding a ';' to all tokens up to the ')'. So we use * these special tokens to decide what we are parsing. And * whenever a function definition is found and the prototype * extracted, we skip through the rest of the function * past the corresponding '}'. This token ends a line, and * is often on a line of its own. But as it turns out, * the only keyword we need to consider is 'static'. * (4) Plan 3. Consider the parentheses and braces for various * declarations. A struct, enum, or union has a pair of * braces followed by a semicolon. They cannot have parentheses * before the left brace, but a struct can have lots of parentheses * within the brace set. A function prototype has no braces. * A function declaration can have sets of left and right * parentheses, but these are followed by a left brace. * So plan 3 looks at the way parentheses and braces are * organized. Once the beginning of a function definition * is found, the prototype is extracted and we search for * the ending right brace. * (5) To find the ending right brace, it is necessary to do some * careful parsing. For example, in this file, we have * left and right braces as characters, and these must not * be counted. Somewhat more tricky, the file fhmtauto.c * generates code, and includes a right brace in a string. * So we must not include braces that are in strings. But how * do we know if something is inside a string? Keep state, * starting with not-inside, and every time you hit a double quote * that is not escaped, toggle the condition. Any brace * found in the state of being within a string is ignored. * (6) When a prototype is extracted, it is put in a canonical * form (i.e., cleaned up). Finally, we check that it is * not static and save it. (If static, it is ignored). * (7) The @prestring for unix is NULL; it is included here so that * you can use Microsoft's declaration for importing or * exporting to a dll. See environ.h for examples of use. * Here, we set: @prestring = "LEPT_DLL ". Note in particular * the space character that will separate 'LEPT_DLL' from * the standard unix prototype that follows. */ char * parseForProtos(const char *filein, const char *prestring) { char *strdata, *str, *newstr, *parsestr, *secondword; l_int32 start, next, stop, charindex, found; size_t nbytes; SARRAY *sa, *saout, *satest; PROCNAME("parseForProtos"); if (!filein) return (char *)ERROR_PTR("filein not defined", procName, NULL); /* Read in the cpp output into memory, one string for each * line in the file, omitting blank lines. */ strdata = (char *)l_binaryRead(filein, &nbytes); sa = sarrayCreateLinesFromString(strdata, 0); saout = sarrayCreate(0); next = 0; while (1) { /* repeat after each non-static prototype is extracted */ searchForProtoSignature(sa, next, &start, &stop, &charindex, &found); if (!found) break; /* fprintf(stderr, " start = %d, stop = %d, charindex = %d\n", start, stop, charindex); */ str = captureProtoSignature(sa, start, stop, charindex); /* Make sure that the signature found by cpp is neither * static nor extern. We get 'extern' declarations from * header files, and with some versions of cpp running on * #include <sys/stat.h> we get something of the form: * extern ... (( ... )) ... ( ... ) { ... * For this, the 1st '(' is the lp, the 2nd ')' is the rp, * and there is a lot of garbage between the rp and the lb. * It is easiest to simply reject any signature that starts * with 'extern'. Note also that an 'extern' token has been * prepended to each prototype, so the 'static' or * 'extern' keywords we are looking for, if they exist, * would be the second word. */ satest = sarrayCreateWordsFromString(str); secondword = sarrayGetString(satest, 1, L_NOCOPY); if (strcmp(secondword, "static") && /* not static */ strcmp(secondword, "extern")) { /* not extern */ if (prestring) { /* prepend it to the prototype */ newstr = stringJoin(prestring, str); sarrayAddString(saout, newstr, L_INSERT); LEPT_FREE(str); } else { sarrayAddString(saout, str, L_INSERT); } } else { LEPT_FREE(str); } sarrayDestroy(&satest); skipToEndOfFunction(sa, stop, charindex, &next); if (next == -1) break; } /* Flatten into a string with newlines between prototypes */ parsestr = sarrayToString(saout, 1); LEPT_FREE(strdata); sarrayDestroy(&sa); sarrayDestroy(&saout); return parsestr; }
/*! * \brief strcodeFinalize() * * \param[in,out] pstrcode destroys after .c and .h files have been generated * \param[in] outdir [optional] if NULL, files are made in /tmp/lept/auto * \return void */ 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; PROCNAME("strcodeFinalize"); lept_mkdir("lept/auto"); if (!pstrcode || *pstrcode == NULL) return ERROR_INT("No input data", procName, 1); strcode = *pstrcode; if (!outdir) { L_INFO("no outdir specified; writing to /tmp/lept/auto\n", procName); realoutdir = stringNew("/tmp/lept/auto"); } else { realoutdir = stringNew(outdir); } /* ------------------------------------------------------- */ /* Make the output autogen.*.c file */ /* ------------------------------------------------------- */ /* Make array of textlines from TEMPLATE1 */ if ((filestr = (char *)l_binaryRead(TEMPLATE1, &size)) == NULL) return ERROR_INT("filestr not made", procName, 1); if ((sa1 = sarrayCreateLinesFromString(filestr, 1)) == NULL) return ERROR_INT("sa1 not made", procName, 1); LEPT_FREE(filestr); if ((sa3 = sarrayCreate(0)) == NULL) return ERROR_INT("sa3 not made", procName, 1); /* 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), " * 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 */ if ((filestr = sarrayToString(sa3, 1)) == NULL) return ERROR_INT("filestr from sa3 not made", procName, 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 */ if ((filestr = (char *)l_binaryRead(TEMPLATE2, &size)) == NULL) return ERROR_INT("filestr not made", procName, 1); if ((sa2 = sarrayCreateLinesFromString(filestr, 1)) == NULL) return ERROR_INT("sa2 not made", procName, 1); LEPT_FREE(filestr); if ((sa3 = sarrayCreate(0)) == NULL) return ERROR_INT("sa3 not made", procName, 1); /* 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 */ if ((filestr = sarrayToString(sa3, 1)) == NULL) return ERROR_INT("filestr from sa3 not made", procName, 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 sudokuReadFile() * * \param[in] filename of formatted sudoku file * \return array of 81 numbers, or NULL on error * * <pre> * Notes: * (1) The file format has: * * any number of comment lines beginning with '#' * * a set of 9 lines, each having 9 digits (0-9) separated * by a space * </pre> */ l_int32 * sudokuReadFile(const char *filename) { char *str, *strj; l_uint8 *data; l_int32 i, j, nlines, val, index, error; l_int32 *array; size_t size; SARRAY *saline, *sa1, *sa2; PROCNAME("sudokuReadFile"); if (!filename) return (l_int32 *)ERROR_PTR("filename not defined", procName, NULL); data = l_binaryRead(filename, &size); sa1 = sarrayCreateLinesFromString((char *)data, 0); sa2 = sarrayCreate(9); /* Filter out the comment lines; verify that there are 9 data lines */ nlines = sarrayGetCount(sa1); for (i = 0; i < nlines; i++) { str = sarrayGetString(sa1, i, L_NOCOPY); if (str[0] != '#') sarrayAddString(sa2, str, L_COPY); } LEPT_FREE(data); sarrayDestroy(&sa1); nlines = sarrayGetCount(sa2); if (nlines != 9) { sarrayDestroy(&sa2); L_ERROR("file has %d lines\n", procName, nlines); return (l_int32 *)ERROR_PTR("invalid file", procName, NULL); } /* Read the data into the array, verifying that each data * line has 9 numbers. */ error = FALSE; array = (l_int32 *)LEPT_CALLOC(81, sizeof(l_int32)); for (i = 0, index = 0; i < 9; i++) { str = sarrayGetString(sa2, i, L_NOCOPY); saline = sarrayCreateWordsFromString(str); if (sarrayGetCount(saline) != 9) { error = TRUE; sarrayDestroy(&saline); break; } for (j = 0; j < 9; j++) { strj = sarrayGetString(saline, j, L_NOCOPY); if (sscanf(strj, "%d", &val) != 1) error = TRUE; else array[index++] = val; } sarrayDestroy(&saline); if (error) break; } sarrayDestroy(&sa2); if (error) { LEPT_FREE(array); return (l_int32 *)ERROR_PTR("invalid data", procName, NULL); } return array; }
/* * fmorphautogen2() * * Input: sela * fileindex * filename (<optional>; can be null) * Return: 0 if OK; 1 on error * * Notes: * (1) This function uses morphtemplate2.txt to create a * low-level file that contains the low-level functions for * implementing dilation and erosion for every sel * in the input sela. * (2) The fileindex parameter is inserted into the output * filename, as described below. * (3) If filename == NULL, the output file is fmorphgenlow.<n>.c, * where <n> is equal to the 'fileindex' parameter. * (4) If filename != NULL, the output file is <filename>low.<n>.c. */ l_int32 fmorphautogen2(SELA *sela, l_int32 fileindex, const char *filename) { char *filestr, *linestr, *fname; char *str_doc1, *str_doc2, *str_doc3, *str_doc4, *str_def1; char bigbuf[L_BUF_SIZE]; char breakstring[] = " break;"; char staticstring[] = "static void"; l_int32 i, nsels, nbytes, actstart, end, newstart; l_int32 argstart, argend, loopstart, loopend, finalstart, finalend; size_t size; SARRAY *sa1, *sa2, *sa3, *sa4, *sa5, *sa6; SEL *sel; PROCNAME("fmorphautogen2"); if (!sela) return ERROR_INT("sela not defined", procName, 1); if (fileindex < 0) fileindex = 0; if ((nsels = selaGetCount(sela)) == 0) return ERROR_INT("no sels in sela", procName, 1); /* Make the array of textlines from morphtemplate2.txt */ if ((filestr = (char *)l_binaryRead(TEMPLATE2, &size)) == NULL) return ERROR_INT("filestr not made", procName, 1); sa1 = sarrayCreateLinesFromString(filestr, 1); LEPT_FREE(filestr); if (!sa1) return ERROR_INT("sa1 not made", procName, 1); /* Make the array of static function names */ if ((sa2 = sarrayCreate(2 * nsels)) == NULL) { sarrayDestroy(&sa1); return ERROR_INT("sa2 not made", procName, 1); } for (i = 0; i < nsels; i++) { sprintf(bigbuf, "fdilate_%d_%d", fileindex, i); sarrayAddString(sa2, bigbuf, L_COPY); sprintf(bigbuf, "ferode_%d_%d", fileindex, i); sarrayAddString(sa2, bigbuf, L_COPY); } /* Make the static prototype strings */ sa3 = sarrayCreate(2 * nsels); /* should be ok */ for (i = 0; i < 2 * nsels; i++) { fname = sarrayGetString(sa2, i, L_NOCOPY); sprintf(bigbuf, "static void %s%s", fname, PROTOARGS); sarrayAddString(sa3, bigbuf, L_COPY); } /* Make strings containing function names */ sprintf(bigbuf, " * l_int32 fmorphopgen_low_%d()", fileindex); str_doc1 = stringNew(bigbuf); sprintf(bigbuf, " * void fdilate_%d_*()", fileindex); str_doc2 = stringNew(bigbuf); sprintf(bigbuf, " * void ferode_%d_*()", fileindex); str_doc3 = stringNew(bigbuf); sprintf(bigbuf, " * fmorphopgen_low_%d()", fileindex); str_doc4 = stringNew(bigbuf); sprintf(bigbuf, "fmorphopgen_low_%d(l_uint32 *datad,", fileindex); str_def1 = stringNew(bigbuf); /* Output to this sa */ sa4 = sarrayCreate(0); /* Copyright notice and info header */ sarrayParseRange(sa1, 0, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa4, sa1, actstart, end); /* Insert function names as documentation */ sarrayAddString(sa4, str_doc1, L_INSERT); sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa4, sa1, actstart, end); sarrayAddString(sa4, str_doc2, L_INSERT); sarrayAddString(sa4, str_doc3, L_INSERT); sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa4, sa1, actstart, end); /* Insert static protos */ for (i = 0; i < 2 * nsels; i++) { if ((linestr = sarrayGetString(sa3, i, L_COPY)) == NULL) { sarrayDestroy(&sa1); sarrayDestroy(&sa2); sarrayDestroy(&sa3); sarrayDestroy(&sa4); return ERROR_INT("linestr not retrieved", procName, 1); } sarrayAddString(sa4, linestr, L_INSERT); } /* Insert function header */ sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa4, sa1, actstart, end); sarrayAddString(sa4, str_doc4, L_INSERT); sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa4, sa1, actstart, end); sarrayAddString(sa4, str_def1, L_INSERT); sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa4, sa1, actstart, end); /* Generate and insert the dispatcher code */ for (i = 0; i < 2 * nsels; i++) { sprintf(bigbuf, " case %d:", i); sarrayAddString(sa4, bigbuf, L_COPY); sprintf(bigbuf, " %s(datad, w, h, wpld, datas, wpls);", sarrayGetString(sa2, i, L_NOCOPY)); sarrayAddString(sa4, bigbuf, L_COPY); sarrayAddString(sa4, breakstring, L_COPY); } /* Finish the dispatcher and introduce the low-level code */ sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa4, sa1, actstart, end); /* Get the range for the args common to all functions */ sarrayParseRange(sa1, newstart, &argstart, &argend, &newstart, "--", 0); /* Get the range for the loop code common to all functions */ sarrayParseRange(sa1, newstart, &loopstart, &loopend, &newstart, "--", 0); /* Get the range for the ending code common to all functions */ sarrayParseRange(sa1, newstart, &finalstart, &finalend, &newstart, "--", 0); /* Do all the static functions */ for (i = 0; i < 2 * nsels; i++) { /* Generate the function header and add the common args */ sarrayAddString(sa4, staticstring, L_COPY); fname = sarrayGetString(sa2, i, L_NOCOPY); sprintf(bigbuf, "%s(l_uint32 *datad,", fname); sarrayAddString(sa4, bigbuf, L_COPY); sarrayAppendRange(sa4, sa1, argstart, argend); /* Declare and define wplsN args, as necessary */ if ((sel = selaGetSel(sela, i/2)) == NULL) { sarrayDestroy(&sa1); sarrayDestroy(&sa2); sarrayDestroy(&sa3); sarrayDestroy(&sa4); return ERROR_INT("sel not returned", procName, 1); } sa5 = sarrayMakeWplsCode(sel); sarrayJoin(sa4, sa5); sarrayDestroy(&sa5); /* Add the function loop code */ sarrayAppendRange(sa4, sa1, loopstart, loopend); /* Insert barrel-op code for *dptr */ sa6 = sarrayMakeInnerLoopDWACode(sel, i); sarrayJoin(sa4, sa6); sarrayDestroy(&sa6); /* Finish the function code */ sarrayAppendRange(sa4, sa1, finalstart, finalend); } /* Output to file */ filestr = sarrayToString(sa4, 1); nbytes = strlen(filestr); if (filename) snprintf(bigbuf, L_BUF_SIZE, "%slow.%d.c", filename, fileindex); else sprintf(bigbuf, "%slow.%d.c", OUTROOT, fileindex); l_binaryWrite(bigbuf, "w", filestr, nbytes); sarrayDestroy(&sa1); sarrayDestroy(&sa2); sarrayDestroy(&sa3); sarrayDestroy(&sa4); LEPT_FREE(filestr); return 0; }
/*! * \brief fmorphautogen1() * * \param[in] sela * \param[in] fileindex * \param[in] filename [optional]; can be null * \return 0 if OK; 1 on error * * <pre> * Notes: * (1) This function uses morphtemplate1.txt to create a * top-level file that contains two functions. These * functions will carry out dilation, erosion, * opening or closing for any of the sels in the input sela. * (2) The fileindex parameter is inserted into the output * filename, as described below. * (3) If filename == NULL, the output file is fmorphgen.<n>.c, * where <n> is equal to the 'fileindex' parameter. * (4) If filename != NULL, the output file is <filename>.<n>.c. * </pre> */ l_int32 fmorphautogen1(SELA *sela, l_int32 fileindex, const char *filename) { char *filestr; char *str_proto1, *str_proto2, *str_proto3; char *str_doc1, *str_doc2, *str_doc3, *str_doc4; char *str_def1, *str_def2, *str_proc1, *str_proc2; char *str_dwa1, *str_low_dt, *str_low_ds, *str_low_ts; char *str_low_tsp1, *str_low_dtp1; char bigbuf[L_BUF_SIZE]; l_int32 i, nsels, nbytes, actstart, end, newstart; size_t size; SARRAY *sa1, *sa2, *sa3; PROCNAME("fmorphautogen1"); if (!sela) return ERROR_INT("sela not defined", procName, 1); if (fileindex < 0) fileindex = 0; if ((nsels = selaGetCount(sela)) == 0) return ERROR_INT("no sels in sela", procName, 1); /* Make array of textlines from morphtemplate1.txt */ if ((filestr = (char *)l_binaryRead(TEMPLATE1, &size)) == NULL) return ERROR_INT("filestr not made", procName, 1); sa2 = sarrayCreateLinesFromString(filestr, 1); LEPT_FREE(filestr); if (!sa2) return ERROR_INT("sa2 not made", procName, 1); /* Make array of sel names */ sa1 = selaGetSelnames(sela); /* Make strings containing function call names */ sprintf(bigbuf, "PIX *pixMorphDwa_%d(PIX *pixd, PIX *pixs, " "l_int32 operation, char *selname);", fileindex); str_proto1 = stringNew(bigbuf); sprintf(bigbuf, "PIX *pixFMorphopGen_%d(PIX *pixd, PIX *pixs, " "l_int32 operation, char *selname);", fileindex); str_proto2 = stringNew(bigbuf); sprintf(bigbuf, "l_int32 fmorphopgen_low_%d(l_uint32 *datad, l_int32 w,\n" " l_int32 h, l_int32 wpld,\n" " l_uint32 *datas, l_int32 wpls,\n" " l_int32 index);", fileindex); str_proto3 = stringNew(bigbuf); sprintf(bigbuf, " * PIX *pixMorphDwa_%d()", fileindex); str_doc1 = stringNew(bigbuf); sprintf(bigbuf, " * PIX *pixFMorphopGen_%d()", fileindex); str_doc2 = stringNew(bigbuf); sprintf(bigbuf, " * pixMorphDwa_%d()", fileindex); str_doc3 = stringNew(bigbuf); sprintf(bigbuf, " * pixFMorphopGen_%d()", fileindex); str_doc4 = stringNew(bigbuf); sprintf(bigbuf, "pixMorphDwa_%d(PIX *pixd,", fileindex); str_def1 = stringNew(bigbuf); sprintf(bigbuf, "pixFMorphopGen_%d(PIX *pixd,", fileindex); str_def2 = stringNew(bigbuf); sprintf(bigbuf, " PROCNAME(\"pixMorphDwa_%d\");", fileindex); str_proc1 = stringNew(bigbuf); sprintf(bigbuf, " PROCNAME(\"pixFMorphopGen_%d\");", fileindex); str_proc2 = stringNew(bigbuf); sprintf(bigbuf, " pixt2 = pixFMorphopGen_%d(NULL, pixt1, operation, selname);", fileindex); str_dwa1 = stringNew(bigbuf); sprintf(bigbuf, " fmorphopgen_low_%d(datad, w, h, wpld, datat, wpls, index);", fileindex); str_low_dt = stringNew(bigbuf); sprintf(bigbuf, " fmorphopgen_low_%d(datad, w, h, wpld, datas, wpls, index);", fileindex); str_low_ds = stringNew(bigbuf); sprintf(bigbuf, " fmorphopgen_low_%d(datat, w, h, wpls, datas, wpls, index+1);", fileindex); str_low_tsp1 = stringNew(bigbuf); sprintf(bigbuf, " fmorphopgen_low_%d(datat, w, h, wpls, datas, wpls, index);", fileindex); str_low_ts = stringNew(bigbuf); sprintf(bigbuf, " fmorphopgen_low_%d(datad, w, h, wpld, datat, wpls, index+1);", fileindex); str_low_dtp1 = stringNew(bigbuf); /* Make the output sa */ sa3 = sarrayCreate(0); /* Copyright notice and info header */ sarrayParseRange(sa2, 0, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); /* Insert function names as documentation */ sarrayAddString(sa3, str_doc1, L_INSERT); sarrayAddString(sa3, str_doc2, L_INSERT); /* Add '#include's */ sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); /* Insert function prototypes */ sarrayAddString(sa3, str_proto1, L_INSERT); sarrayAddString(sa3, str_proto2, L_INSERT); sarrayAddString(sa3, str_proto3, L_INSERT); /* Add static globals */ sprintf(bigbuf, "\nstatic l_int32 NUM_SELS_GENERATED = %d;", nsels); sarrayAddString(sa3, bigbuf, L_COPY); sprintf(bigbuf, "static char SEL_NAMES[][80] = {"); sarrayAddString(sa3, bigbuf, L_COPY); for (i = 0; i < nsels - 1; i++) { sprintf(bigbuf, " \"%s\",", sarrayGetString(sa1, i, L_NOCOPY)); sarrayAddString(sa3, bigbuf, L_COPY); } sprintf(bigbuf, " \"%s\"};", sarrayGetString(sa1, i, L_NOCOPY)); sarrayAddString(sa3, bigbuf, L_COPY); /* Start pixMorphDwa_*() function description */ sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); sarrayAddString(sa3, str_doc3, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); /* Finish pixMorphDwa_*() function definition */ sarrayAddString(sa3, str_def1, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); sarrayAddString(sa3, str_proc1, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); sarrayAddString(sa3, str_dwa1, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); /* Start pixFMorphopGen_*() function description */ sarrayAddString(sa3, str_doc4, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); /* Finish pixFMorphopGen_*() function definition */ sarrayAddString(sa3, str_def2, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); sarrayAddString(sa3, str_proc2, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); sarrayAddString(sa3, str_low_dt, L_COPY); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); sarrayAddString(sa3, str_low_ds, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); sarrayAddString(sa3, str_low_tsp1, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); sarrayAddString(sa3, str_low_dt, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); sarrayAddString(sa3, str_low_ts, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); sarrayAddString(sa3, str_low_dtp1, L_INSERT); sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); sarrayAppendRange(sa3, sa2, actstart, end); /* Output to file */ filestr = sarrayToString(sa3, 1); nbytes = strlen(filestr); if (filename) snprintf(bigbuf, L_BUF_SIZE, "%s.%d.c", filename, fileindex); else sprintf(bigbuf, "%s.%d.c", OUTROOT, fileindex); l_binaryWrite(bigbuf, "w", filestr, nbytes); sarrayDestroy(&sa1); sarrayDestroy(&sa2); sarrayDestroy(&sa3); LEPT_FREE(filestr); return 0; }
int main(int argc, char **argv) { char *str; l_uint8 *data1, *data2; l_int32 i, n, same1, same2; size_t size1, size2, slice, total, start, end; FILE *fp; L_DNA *da; SARRAY *sa; L_BYTEA *lba1, *lba2, *lba3, *lba4, *lba5; static char mainName[] = "byteatest"; if (argc != 1) return ERROR_INT("syntax: byteatest", mainName, 1); lept_mkdir("bytea"); /* Test basic init, join and split */ lba1 = l_byteaInitFromFile("feyn.tif"); lba2 = l_byteaInitFromFile("test24.jpg"); size1 = l_byteaGetSize(lba1); size2 = l_byteaGetSize(lba2); l_byteaJoin(lba1, &lba2); lba3 = l_byteaInitFromMem(lba1->data, size1); lba4 = l_byteaInitFromMem(lba1->data + size1, size2); /* Split by hand */ l_binaryWrite("/tmp/bytea/junk1.dat", "w", lba3->data, lba3->size); l_binaryWrite("/tmp/bytea/junk2.dat", "w", lba4->data, lba4->size); filesAreIdentical("feyn.tif", "/tmp/bytea/junk1.dat", &same1); filesAreIdentical("test24.jpg", "/tmp/bytea/junk2.dat", &same2); if (same1 && same2) fprintf(stderr, "OK for join file\n"); else fprintf(stderr, "Error: files are different!\n"); /* Split by function */ l_byteaSplit(lba1, size1, &lba5); l_binaryWrite("/tmp/bytea/junk3.dat", "w", lba1->data, lba1->size); l_binaryWrite("/tmp/bytea/junk4.dat", "w", lba5->data, lba5->size); filesAreIdentical("feyn.tif", "/tmp/bytea/junk3.dat", &same1); filesAreIdentical("test24.jpg", "/tmp/bytea/junk4.dat", &same2); if (same1 && same2) fprintf(stderr, "OK for split file\n"); else fprintf(stderr, "Error: files are different!\n"); l_byteaDestroy(&lba1); l_byteaDestroy(&lba2); l_byteaDestroy(&lba3); l_byteaDestroy(&lba4); l_byteaDestroy(&lba5); /* Test appending with strings */ data1 = l_binaryRead("kernel_reg.c", &size1); sa = sarrayCreateLinesFromString((char *)data1, 1); lba1 = l_byteaCreate(0); n = sarrayGetCount(sa); for (i = 0; i < n; i++) { str = sarrayGetString(sa, i, L_NOCOPY); l_byteaAppendString(lba1, str); l_byteaAppendString(lba1, (char *)"\n"); } data2 = l_byteaGetData(lba1, &size2); l_binaryWrite("/tmp/bytea/junk5.dat", "w", data2, size2); filesAreIdentical("kernel_reg.c", "/tmp/bytea/junk5.dat", &same1); if (same1) fprintf(stderr, "OK for appended string data\n"); else fprintf(stderr, "Error: appended string data is different!\n"); lept_free(data1); sarrayDestroy(&sa); l_byteaDestroy(&lba1); /* Test appending with binary data */ slice = 1000; total = nbytesInFile("breviar-a38.jp2"); lba1 = l_byteaCreate(100); n = 1 + total / slice; fprintf(stderr, "******************************************************\n"); fprintf(stderr, "* Testing error checking: ignore two reported errors *\n"); for (i = 0, start = 0; i <= n; i++, start += slice) { data1 = l_binaryReadSelect("breviar-a38.jp2", start, slice, &size1); l_byteaAppendData(lba1, data1, size1); lept_free(data1); } fprintf(stderr, "******************************************************\n"); data2 = l_byteaGetData(lba1, &size2); l_binaryWrite("/tmp/bytea/junk6.dat", "w", data2, size2); filesAreIdentical("breviar-a38.jp2", "/tmp/bytea/junk6.dat", &same1); if (same1) fprintf(stderr, "OK for appended binary data\n"); else fprintf(stderr, "Error: appended binary data is different!\n"); l_byteaDestroy(&lba1); /* Test search */ convertToPdf("test24.jpg", L_JPEG_ENCODE, 0, "/tmp/bytea/junk7.pdf", 0, 0, 100, NULL, NULL, 0); lba1 = l_byteaInitFromFile("/tmp/bytea/junk7.pdf"); l_byteaFindEachSequence(lba1, (l_uint8 *)" 0 obj\n", 7, &da); /* l_dnaWriteStream(stderr, da); */ n = l_dnaGetCount(da); if (n == 6) fprintf(stderr, "OK for search: found 6 instances\n"); else fprintf(stderr, "Error in search: found %d instances, not 6\n", n); l_byteaDestroy(&lba1); l_dnaDestroy(&da); /* Test write to file */ lba1 = l_byteaInitFromFile("feyn.tif"); fp = lept_fopen("/tmp/bytea/junk8.dat", "wb"); size1 = l_byteaGetSize(lba1); for (start = 0; start < size1; start += 1000) { end = L_MIN(start + 1000 - 1, size1 - 1); l_byteaWriteStream(fp, lba1, start, end); } lept_fclose(fp); filesAreIdentical("feyn.tif", "/tmp/bytea/junk8.dat", &same1); if (same1) fprintf(stderr, "OK for written binary data\n"); else fprintf(stderr, "Error: written binary data is different!\n"); l_byteaDestroy(&lba1); return 0; }
main(int argc, char **argv) { char *str; l_uint8 *data1, *data2; l_int32 i, n, start, end, same1, same2; size_t size1, size2; FILE *fp; L_DNA *da; SARRAY *sa; L_BYTEA *lba1, *lba2, *lba3, *lba4, *lba5; static char mainName[] = "byteatest"; if (argc != 1) exit(ERROR_INT("syntax: whatever11", mainName, 1)); /* Test basic init, join and split */ lba1 = l_byteaInitFromFile("feyn.tif"); lba2 = l_byteaInitFromFile("test24.jpg"); size1 = l_byteaGetSize(lba1); size2 = l_byteaGetSize(lba2); l_byteaJoin(lba1, &lba2); lba3 = l_byteaInitFromMem(lba1->data, size1); lba4 = l_byteaInitFromMem(lba1->data + size1, size2); /* Split by hand */ l_binaryWrite("junk1", "w", lba3->data, lba3->size); l_binaryWrite("junk2", "w", lba4->data, lba4->size); filesAreIdentical("feyn.tif", "junk1", &same1); filesAreIdentical("test24.jpg", "junk2", &same2); if (same1 && same2) fprintf(stderr, "OK for join file\n"); else fprintf(stderr, "Error: files are different!\n"); /* Split by function */ l_byteaSplit(lba1, size1, &lba5); l_binaryWrite("junk3", "w", lba1->data, lba1->size); l_binaryWrite("junk4", "w", lba5->data, lba5->size); filesAreIdentical("feyn.tif", "junk3", &same1); filesAreIdentical("test24.jpg", "junk4", &same2); if (same1 && same2) fprintf(stderr, "OK for split file\n"); else fprintf(stderr, "Error: files are different!\n"); l_byteaDestroy(&lba1); l_byteaDestroy(&lba2); l_byteaDestroy(&lba3); l_byteaDestroy(&lba4); l_byteaDestroy(&lba5); /* Test appending */ data1 = l_binaryRead("whatever10.c", &size1); sa = sarrayCreateLinesFromString((char *)data1, 1); lba1 = l_byteaCreate(0); n = sarrayGetCount(sa); for (i = 0; i < n; i++) { str = sarrayGetString(sa, i, L_NOCOPY); l_byteaAppendString(lba1, str); l_byteaAppendString(lba1, (char *)"\n"); } data2 = l_byteaGetData(lba1, &size2); l_binaryWrite("junk1.txt", "w", data2, size2); filesAreIdentical("whatever10.c", "junk1.txt", &same1); if (same1) fprintf(stderr, "OK for appended file\n"); else fprintf(stderr, "Error: appended file is different!\n"); lept_free(data1); sarrayDestroy(&sa); l_byteaDestroy(&lba1); /* Test search */ convertToPdf("test24.jpg", L_JPEG_ENCODE, 0, "junk3.pdf", 0, 0, 100, NULL, 0, NULL); lba1 = l_byteaInitFromFile("junk3.pdf"); l_byteaFindEachSequence(lba1, (l_uint8 *)" 0 obj\n", 7, &da); l_dnaWriteStream(stderr, da); l_byteaDestroy(&lba1); l_dnaDestroy(&da); /* Test write to file */ lba1 = l_byteaInitFromFile("feyn.tif"); fp = lept_fopen("junk5", "wb"); size1 = l_byteaGetSize(lba1); for (start = 0; start < size1; start += 1000) { end = L_MIN(start + 1000 - 1, size1 - 1); l_byteaWriteStream(fp, lba1, start, end); } lept_fclose(fp); l_byteaDestroy(&lba1); return 0; }