27 * |
27 * |
28 */ |
28 */ |
29 |
29 |
30 #include "c2html.h" |
30 #include "c2html.h" |
31 |
31 |
32 #include "ucx/list.h" |
32 #include <cx/array_list.h> |
33 #include "ucx/utils.h" |
33 #include <cx/printf.h> |
34 |
34 |
35 #define try_write(wfnc, str, n, buf, written, maxlen) \ |
35 size_t c2html_format( |
36 { \ |
36 CxList const *lines, |
37 size_t m = maxlen-written; \ |
37 void *outbuf, |
38 written += wfnc(str, 1, n > m ? m : n, buf); \ |
38 cx_write_func wfnc, |
|
39 c2html_highlighter_func highlighter, |
|
40 int showln |
|
41 ) { |
|
42 /* total written bytes */ |
|
43 size_t written = 0; |
|
44 |
|
45 /* compute width of line numbering */ |
|
46 int lnw = 0; |
|
47 if (showln) { |
|
48 size_t no_lines = cxListSize(lines); |
|
49 for (size_t p = 1; p < no_lines; p *= 10) lnw++; |
39 } |
50 } |
40 |
51 |
41 static size_t formatlines(c2html_highlighter_func highlighter, UcxList *in, |
52 /* start code formatting */ |
42 void *outbuf, write_func wfnc, size_t maxlen, int showlineno) { |
53 written += wfnc("<div class=\"c2html-code\">\n", 1, 26, outbuf); |
43 /* total written bytes */ |
|
44 size_t written = 0; |
|
45 |
|
46 /* compute width of line numbering */ |
|
47 int lnw = 0; |
|
48 if (showlineno) { |
|
49 size_t lines = ucx_list_size(in); |
|
50 for (size_t p = 1; p < lines ; p*=10) lnw++; |
|
51 } |
|
52 |
|
53 /* start monospace formatting */ |
|
54 try_write(wfnc, "<pre>\n", 6, outbuf, written, maxlen); |
|
55 |
54 |
56 /* process lines */ |
55 /* process lines */ |
57 size_t lineno = 0; |
56 int lineno = 0; |
58 c2html_highlighter_data* hd = malloc(sizeof(c2html_highlighter_data)); |
57 c2html_highlighter_data hd; |
59 hd->multiline_comment = 0; |
58 hd.multiline_comment = 0; |
60 hd->primary_buffer = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND); |
59 cxBufferInit(&hd.primary_buffer, NULL, 256, NULL, CX_BUFFER_AUTO_EXTEND); |
61 hd->secondary_buffer = ucx_buffer_new(NULL, 32, UCX_BUFFER_AUTOEXTEND); |
60 cxBufferInit(&hd.secondary_buffer, NULL, 32, NULL, CX_BUFFER_AUTO_EXTEND); |
62 UcxBuffer *line = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND); |
61 CxBuffer out_line; |
63 |
62 cxBufferInit(&out_line, NULL, 128, NULL, CX_BUFFER_AUTO_EXTEND); |
64 UCX_FOREACH(sourceline, in) { |
63 |
|
64 CxIterator in_lines = cxListIterator(lines); |
|
65 cx_foreach(char*, in_line, in_lines) { |
65 /* increase line number and clean line buffer */ |
66 /* increase line number and clean line buffer */ |
66 lineno++; |
67 lineno++; |
67 ucx_buffer_clear(line); |
68 cxBufferClear(&out_line); |
68 |
69 |
69 /* write line number */ |
70 /* write line number */ |
70 if (showlineno) { |
71 if (showln) { |
71 ucx_bprintf(line, "<a class=\"c2html-lineno\" name=\"l%d\" " |
72 cx_bprintf(&out_line, "<a class=\"c2html-lineno\" name=\"l%d\" " |
72 "href=\"#l%d\">%*d </a>", |
73 "href=\"#l%d\">%*d </a>", |
73 lineno, lineno, lnw, lineno); |
74 lineno, lineno, lnw, lineno); |
74 } |
75 } |
75 |
76 |
76 /* process code line */ |
77 /* process code line */ |
77 highlighter(sourceline->data, line, hd); |
78 highlighter(in_line, &out_line, &hd); |
78 |
79 |
79 /* write code line */ |
80 /* write code line */ |
80 try_write(wfnc, line->space, line->size, outbuf, written, maxlen); |
81 written += wfnc(out_line.space, 1, out_line.size, outbuf); |
81 |
|
82 if (written == maxlen) break; |
|
83 } |
82 } |
84 |
83 |
85 /* end monospace formatting */ |
84 /* end code formatting */ |
86 try_write(wfnc, "</pre>\n", 7, outbuf, written, maxlen); |
85 written += wfnc("</div>\n", 1, 7, outbuf); |
87 |
86 |
88 /* cleanup and return */ |
87 /* cleanup and return */ |
89 ucx_buffer_free(hd->primary_buffer); |
88 cxBufferDestroy(&hd.primary_buffer); |
90 ucx_buffer_free(hd->secondary_buffer); |
89 cxBufferDestroy(&hd.secondary_buffer); |
91 free(hd); |
90 cxBufferDestroy(&out_line); |
92 ucx_buffer_free(line); |
91 |
93 |
|
94 return written; |
92 return written; |
95 } |
93 } |
96 |
94 |
97 size_t c2html_formatn(void* inputbuffer, read_func rfnc, |
95 size_t c2html_bformat( |
98 char* ibuf, size_t ibuflen, void* outputbuffer, write_func wfnc, |
96 char const *inputbuffer, |
99 size_t maxlen, c2html_highlighter_func hltr, int showln) { |
97 size_t inputbuflen, |
100 |
98 void *outbuf, |
101 UcxBuffer *content = ucx_buffer_new(NULL, ibuflen*2, UCX_BUFFER_AUTOEXTEND); |
99 cx_write_func wfnc, |
102 ucx_stream_copy(inputbuffer, content, rfnc, (write_func) ucx_buffer_write, |
100 c2html_highlighter_func highlighter, |
103 ibuf, ibuflen, (size_t)-1); |
101 int showln |
|
102 ) { |
|
103 /* a rough estimate for the number of lines */ |
|
104 size_t est_cap = 16 + inputbuflen / 40; |
104 |
105 |
105 size_t n = c2html_bformatn(content->space, content->size, |
106 /* create the line pointer array */ |
106 outputbuffer, wfnc, maxlen, hltr, showln); |
107 CxList *lines = cxArrayListCreateSimple(CX_STORE_POINTERS, est_cap); |
107 |
108 cxListAdd(lines, inputbuffer); |
108 ucx_buffer_free(content); |
109 for (size_t i = 1; i < inputbuflen; i++) { |
|
110 if (inputbuffer[i] == '\n' && i + 1 < inputbuflen) { |
|
111 cxListAdd(lines, inputbuffer + i + 1); |
|
112 } |
|
113 } |
|
114 |
|
115 /* invoke the other function */ |
|
116 size_t n = c2html_format(lines, outbuf, wfnc, highlighter, showln); |
|
117 |
|
118 /* cleanup and return */ |
|
119 cxListDestroy(lines); |
109 return n; |
120 return n; |
110 } |
121 } |
111 |
|
112 size_t c2html_format(void* inputbuffer, read_func rfnc, |
|
113 char* ibuf, size_t ibuflen, void* outputbuffer, write_func wfnc, |
|
114 c2html_highlighter_func hltr, int showln) { |
|
115 return c2html_formatn(inputbuffer, rfnc, ibuf, ibuflen, |
|
116 outputbuffer, wfnc, (size_t)-1, hltr, showln); |
|
117 } |
|
118 |
|
119 size_t c2html_fformat(FILE* inputfile, char *ibuf, size_t ibuflen, |
|
120 void* outputbuffer, write_func wfnc, |
|
121 c2html_highlighter_func hltr, int showln) { |
|
122 return c2html_format(inputfile, (read_func) fread, ibuf, ibuflen, |
|
123 outputbuffer, wfnc, hltr, showln); |
|
124 } |
|
125 |
|
126 void c2html_fformatf(FILE *inputfile, char *ibuf, size_t ibuflen, |
|
127 FILE* outputfile, c2html_highlighter_func hltr, int showln) { |
|
128 c2html_format(inputfile, (read_func) fread, ibuf, ibuflen, |
|
129 outputfile, (write_func) fwrite, hltr, showln); |
|
130 } |
|
131 |
|
132 size_t c2html_bformatn(const char* inputbuffer, size_t inputbuflen, |
|
133 void* outputbuffer, write_func wfnc, |
|
134 size_t maxlen, c2html_highlighter_func hltr, int showln) { |
|
135 UcxList *lines = ucx_list_append(NULL, (char*)inputbuffer); |
|
136 for (size_t i = 1 ; i < inputbuflen ; i++) { |
|
137 if (inputbuffer[i] == '\n' && i+1 < inputbuflen) { |
|
138 ucx_list_append(lines, (char*)inputbuffer+i+1); |
|
139 } |
|
140 } |
|
141 |
|
142 size_t n = formatlines(hltr, lines, outputbuffer, wfnc, maxlen, showln); |
|
143 |
|
144 ucx_list_free(lines); |
|
145 return n; |
|
146 } |
|
147 |
|
148 size_t c2html_bformat(const char* inputbuffer, size_t inputbuflen, |
|
149 void* outputbuffer, write_func wfnc, |
|
150 c2html_highlighter_func hltr, int showln) { |
|
151 return c2html_bformatn(inputbuffer, inputbuflen, outputbuffer, wfnc, |
|
152 (size_t)-1, hltr, showln); |
|
153 } |
|
154 |
|
155 void c2html_bformatf(const char* inputbuffer, size_t inputbuflen, |
|
156 FILE* outputfile, c2html_highlighter_func hltr, int showln) { |
|
157 c2html_bformatn(inputbuffer, inputbuflen, outputfile, |
|
158 (write_func) fwrite, (size_t)-1, hltr, showln); |
|
159 } |
|