Fossil SCM
Make parsing slightly faster and fix a comment. No changes in functionality.
Commit
a36dd09d17f3057f077c46be9c4b1a9f26e0f053bb640698eab474cd3c9599f9
Parent
2c1f8f3592ef00e…
1 file changed
+88
-92
+88
-92
| --- src/markdown.c | ||
| +++ src/markdown.c | ||
| @@ -1168,20 +1168,19 @@ | ||
| 1168 | 1168 | static size_t char_link( |
| 1169 | 1169 | struct Blob *ob, |
| 1170 | 1170 | struct render *rndr, |
| 1171 | 1171 | char *data, |
| 1172 | 1172 | size_t offset, |
| 1173 | - size_t size | |
| 1173 | + size_t size /* parse_inline() ensures that size > 0 */ | |
| 1174 | 1174 | ){ |
| 1175 | 1175 | const int is_img = (offset && data[-1] == '!'); |
| 1176 | 1176 | size_t i = 1, txt_e; |
| 1177 | 1177 | struct Blob *content = 0; |
| 1178 | 1178 | struct Blob *link = 0; |
| 1179 | 1179 | struct Blob *title = 0; |
| 1180 | 1180 | const struct footnote *fn = 0; |
| 1181 | 1181 | int ret; |
| 1182 | - /* ? FIXME: assert( size>0 ); */ | |
| 1183 | 1182 | |
| 1184 | 1183 | /* checking whether the correct renderer exists */ |
| 1185 | 1184 | if( (is_img && !rndr->make.image) || (!is_img && !rndr->make.link) ){ |
| 1186 | 1185 | return 0; |
| 1187 | 1186 | } |
| @@ -1188,104 +1187,101 @@ | ||
| 1188 | 1187 | |
| 1189 | 1188 | /* looking for the matching closing bracket */ |
| 1190 | 1189 | txt_e = matching_bracket_offset(data, data+size); |
| 1191 | 1190 | if( !txt_e ) return 0; |
| 1192 | 1191 | i = txt_e + 1; |
| 1193 | - | |
| 1194 | - /* skip any amount of whitespace or newline */ | |
| 1195 | - /* (this is much more laxist than original markdown syntax) */ | |
| 1196 | - while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; } | |
| 1197 | - | |
| 1198 | - /* allocate temporary buffers to store content, link and title */ | |
| 1199 | - title = new_work_buffer(rndr); | |
| 1200 | - content = new_work_buffer(rndr); | |
| 1201 | - link = new_work_buffer(rndr); | |
| 1202 | 1192 | ret = 0; /* error if we don't get to the callback */ |
| 1203 | 1193 | |
| 1204 | 1194 | /* free-standing footnote refernece */ |
| 1205 | 1195 | if(!is_img && size>3 && data[1]=='^'){ |
| 1206 | - /* free-standing footnote reference */ | |
| 1207 | - fn = get_footnote(rndr, data+2, txt_e-2); | |
| 1208 | - if( !fn ) { | |
| 1209 | - rndr->notes.misref.nUsed++; | |
| 1210 | - fn = &rndr->notes.misref; | |
| 1211 | - } | |
| 1212 | - release_work_buffer(rndr, content); | |
| 1213 | - content = 0; | |
| 1214 | - i = txt_e+1; /* rewinding a closing square bracket */ | |
| 1215 | - | |
| 1216 | - }else if( i<size && data[i]=='(' ){ | |
| 1217 | - | |
| 1218 | - if( i+2<size && data[i+1]=='^' ){ /* span-bounded inline footnote */ | |
| 1219 | - | |
| 1220 | - const size_t k = matching_bracket_offset(data+i, data+size); | |
| 1221 | - if( !k ) goto char_link_cleanup; | |
| 1222 | - fn = add_inline_footnote(rndr, data+(i+2), k-2); | |
| 1223 | - i += k+1; | |
| 1224 | - }else{ /* inline style link */ | |
| 1225 | - size_t span_end = i; | |
| 1226 | - while( span_end<size | |
| 1227 | - && !(data[span_end]==')' && (span_end==i || data[span_end-1]!='\\')) | |
| 1228 | - ){ | |
| 1229 | - span_end++; | |
| 1230 | - } | |
| 1231 | - | |
| 1232 | - if( span_end>=size | |
| 1233 | - || get_link_inline(link, title, data+i+1, span_end-(i+1))<0 | |
| 1234 | - ){ | |
| 1235 | - goto char_link_cleanup; | |
| 1236 | - } | |
| 1237 | - | |
| 1238 | - i = span_end+1; | |
| 1239 | - } | |
| 1240 | - | |
| 1241 | - /* reference style link or span-bounded footnote reference */ | |
| 1242 | - }else if( i<size && data[i]=='[' ){ | |
| 1243 | - char *id_data; | |
| 1244 | - size_t id_size, id_end = i; | |
| 1245 | - int bFootnote; | |
| 1246 | - | |
| 1247 | - while( id_end<size && data[id_end]!=']' ){ id_end++; } | |
| 1248 | - | |
| 1249 | - if( id_end>=size ) goto char_link_cleanup; | |
| 1250 | - bFootnote = data[i+1]=='^'; | |
| 1251 | - | |
| 1252 | - if( i+1==id_end || (bFootnote && i+2==id_end) ){ | |
| 1253 | - /* implicit id - use the contents */ | |
| 1254 | - id_data = data+1; | |
| 1255 | - id_size = txt_e-1; | |
| 1256 | - }else{ | |
| 1257 | - /* explicit id - between brackets */ | |
| 1258 | - id_data = data+i+1; | |
| 1259 | - id_size = id_end-(i+1); | |
| 1260 | - if( bFootnote ){ | |
| 1261 | - id_data++; | |
| 1262 | - id_size--; | |
| 1263 | - } | |
| 1264 | - } | |
| 1265 | - | |
| 1266 | - if( bFootnote ){ | |
| 1267 | - fn = get_footnote(rndr, id_data, id_size); | |
| 1268 | - if( !fn ) { | |
| 1269 | - rndr->notes.misref.nUsed++; | |
| 1270 | - fn = &rndr->notes.misref; | |
| 1271 | - } | |
| 1272 | - }else if( get_link_ref(rndr, link, title, id_data, id_size)<0 ){ | |
| 1273 | - goto char_link_cleanup; | |
| 1274 | - } | |
| 1275 | - | |
| 1276 | - i = id_end+1; | |
| 1277 | - | |
| 1278 | - /* shortcut reference style link */ | |
| 1279 | - }else{ | |
| 1280 | - if( get_link_ref(rndr, link, title, data+1, txt_e-1)<0 ){ | |
| 1281 | - goto char_link_cleanup; | |
| 1282 | - } | |
| 1283 | - /* rewinding a closing square bracket */ | |
| 1284 | - i = txt_e+1; | |
| 1285 | - } | |
| 1286 | - | |
| 1196 | + fn = get_footnote(rndr, data+2, txt_e-2); | |
| 1197 | + if( !fn ) { | |
| 1198 | + rndr->notes.misref.nUsed++; | |
| 1199 | + fn = &rndr->notes.misref; | |
| 1200 | + } | |
| 1201 | + }else{ | |
| 1202 | + | |
| 1203 | + /* skip "inter-bracket-whitespace" - any amount of whitespace or newline */ | |
| 1204 | + /* (this is much more laxist than original markdown syntax) */ | |
| 1205 | + while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; } | |
| 1206 | + | |
| 1207 | + /* allocate temporary buffers to store content, link and title */ | |
| 1208 | + title = new_work_buffer(rndr); | |
| 1209 | + content = new_work_buffer(rndr); | |
| 1210 | + link = new_work_buffer(rndr); | |
| 1211 | + | |
| 1212 | + if( i<size && data[i]=='(' ){ | |
| 1213 | + | |
| 1214 | + if( i+2<size && data[i+1]=='^' ){ /* span-bounded inline footnote */ | |
| 1215 | + | |
| 1216 | + const size_t k = matching_bracket_offset(data+i, data+size); | |
| 1217 | + if( !k ) goto char_link_cleanup; | |
| 1218 | + fn = add_inline_footnote(rndr, data+(i+2), k-2); | |
| 1219 | + i += k+1; | |
| 1220 | + }else{ /* inline style link */ | |
| 1221 | + size_t span_end = i; | |
| 1222 | + while( span_end<size | |
| 1223 | + && !(data[span_end]==')' && (span_end==i || data[span_end-1]!='\\')) | |
| 1224 | + ){ | |
| 1225 | + span_end++; | |
| 1226 | + } | |
| 1227 | + | |
| 1228 | + if( span_end>=size | |
| 1229 | + || get_link_inline(link, title, data+i+1, span_end-(i+1))<0 | |
| 1230 | + ){ | |
| 1231 | + goto char_link_cleanup; | |
| 1232 | + } | |
| 1233 | + | |
| 1234 | + i = span_end+1; | |
| 1235 | + } | |
| 1236 | + | |
| 1237 | + /* reference style link or span-bounded footnote reference */ | |
| 1238 | + }else if( i<size && data[i]=='[' ){ | |
| 1239 | + char *id_data; | |
| 1240 | + size_t id_size, id_end = i; | |
| 1241 | + int bFootnote; | |
| 1242 | + | |
| 1243 | + while( id_end<size && data[id_end]!=']' ){ id_end++; } | |
| 1244 | + | |
| 1245 | + if( id_end>=size ) goto char_link_cleanup; | |
| 1246 | + bFootnote = data[i+1]=='^'; | |
| 1247 | + | |
| 1248 | + if( i+1==id_end || (bFootnote && i+2==id_end) ){ | |
| 1249 | + /* implicit id - use the contents */ | |
| 1250 | + id_data = data+1; | |
| 1251 | + id_size = txt_e-1; | |
| 1252 | + }else{ | |
| 1253 | + /* explicit id - between brackets */ | |
| 1254 | + id_data = data+i+1; | |
| 1255 | + id_size = id_end-(i+1); | |
| 1256 | + if( bFootnote ){ | |
| 1257 | + id_data++; | |
| 1258 | + id_size--; | |
| 1259 | + } | |
| 1260 | + } | |
| 1261 | + | |
| 1262 | + if( bFootnote ){ | |
| 1263 | + fn = get_footnote(rndr, id_data, id_size); | |
| 1264 | + if( !fn ) { | |
| 1265 | + rndr->notes.misref.nUsed++; | |
| 1266 | + fn = &rndr->notes.misref; | |
| 1267 | + } | |
| 1268 | + }else if( get_link_ref(rndr, link, title, id_data, id_size)<0 ){ | |
| 1269 | + goto char_link_cleanup; | |
| 1270 | + } | |
| 1271 | + | |
| 1272 | + i = id_end+1; | |
| 1273 | + | |
| 1274 | + /* shortcut reference style link */ | |
| 1275 | + }else{ | |
| 1276 | + if( get_link_ref(rndr, link, title, data+1, txt_e-1)<0 ){ | |
| 1277 | + goto char_link_cleanup; | |
| 1278 | + } | |
| 1279 | + /* rewinding an "inter-bracket-whitespace" */ | |
| 1280 | + i = txt_e+1; | |
| 1281 | + } | |
| 1282 | + } | |
| 1287 | 1283 | /* building content: img alt is escaped, link content is parsed */ |
| 1288 | 1284 | if( txt_e>1 && content ){ |
| 1289 | 1285 | if( is_img ) blob_append(content, data+1, txt_e-1); |
| 1290 | 1286 | else parse_inline(content, rndr, data+1, txt_e-1); |
| 1291 | 1287 | } |
| 1292 | 1288 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -1168,20 +1168,19 @@ | |
| 1168 | static size_t char_link( |
| 1169 | struct Blob *ob, |
| 1170 | struct render *rndr, |
| 1171 | char *data, |
| 1172 | size_t offset, |
| 1173 | size_t size |
| 1174 | ){ |
| 1175 | const int is_img = (offset && data[-1] == '!'); |
| 1176 | size_t i = 1, txt_e; |
| 1177 | struct Blob *content = 0; |
| 1178 | struct Blob *link = 0; |
| 1179 | struct Blob *title = 0; |
| 1180 | const struct footnote *fn = 0; |
| 1181 | int ret; |
| 1182 | /* ? FIXME: assert( size>0 ); */ |
| 1183 | |
| 1184 | /* checking whether the correct renderer exists */ |
| 1185 | if( (is_img && !rndr->make.image) || (!is_img && !rndr->make.link) ){ |
| 1186 | return 0; |
| 1187 | } |
| @@ -1188,104 +1187,101 @@ | |
| 1188 | |
| 1189 | /* looking for the matching closing bracket */ |
| 1190 | txt_e = matching_bracket_offset(data, data+size); |
| 1191 | if( !txt_e ) return 0; |
| 1192 | i = txt_e + 1; |
| 1193 | |
| 1194 | /* skip any amount of whitespace or newline */ |
| 1195 | /* (this is much more laxist than original markdown syntax) */ |
| 1196 | while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; } |
| 1197 | |
| 1198 | /* allocate temporary buffers to store content, link and title */ |
| 1199 | title = new_work_buffer(rndr); |
| 1200 | content = new_work_buffer(rndr); |
| 1201 | link = new_work_buffer(rndr); |
| 1202 | ret = 0; /* error if we don't get to the callback */ |
| 1203 | |
| 1204 | /* free-standing footnote refernece */ |
| 1205 | if(!is_img && size>3 && data[1]=='^'){ |
| 1206 | /* free-standing footnote reference */ |
| 1207 | fn = get_footnote(rndr, data+2, txt_e-2); |
| 1208 | if( !fn ) { |
| 1209 | rndr->notes.misref.nUsed++; |
| 1210 | fn = &rndr->notes.misref; |
| 1211 | } |
| 1212 | release_work_buffer(rndr, content); |
| 1213 | content = 0; |
| 1214 | i = txt_e+1; /* rewinding a closing square bracket */ |
| 1215 | |
| 1216 | }else if( i<size && data[i]=='(' ){ |
| 1217 | |
| 1218 | if( i+2<size && data[i+1]=='^' ){ /* span-bounded inline footnote */ |
| 1219 | |
| 1220 | const size_t k = matching_bracket_offset(data+i, data+size); |
| 1221 | if( !k ) goto char_link_cleanup; |
| 1222 | fn = add_inline_footnote(rndr, data+(i+2), k-2); |
| 1223 | i += k+1; |
| 1224 | }else{ /* inline style link */ |
| 1225 | size_t span_end = i; |
| 1226 | while( span_end<size |
| 1227 | && !(data[span_end]==')' && (span_end==i || data[span_end-1]!='\\')) |
| 1228 | ){ |
| 1229 | span_end++; |
| 1230 | } |
| 1231 | |
| 1232 | if( span_end>=size |
| 1233 | || get_link_inline(link, title, data+i+1, span_end-(i+1))<0 |
| 1234 | ){ |
| 1235 | goto char_link_cleanup; |
| 1236 | } |
| 1237 | |
| 1238 | i = span_end+1; |
| 1239 | } |
| 1240 | |
| 1241 | /* reference style link or span-bounded footnote reference */ |
| 1242 | }else if( i<size && data[i]=='[' ){ |
| 1243 | char *id_data; |
| 1244 | size_t id_size, id_end = i; |
| 1245 | int bFootnote; |
| 1246 | |
| 1247 | while( id_end<size && data[id_end]!=']' ){ id_end++; } |
| 1248 | |
| 1249 | if( id_end>=size ) goto char_link_cleanup; |
| 1250 | bFootnote = data[i+1]=='^'; |
| 1251 | |
| 1252 | if( i+1==id_end || (bFootnote && i+2==id_end) ){ |
| 1253 | /* implicit id - use the contents */ |
| 1254 | id_data = data+1; |
| 1255 | id_size = txt_e-1; |
| 1256 | }else{ |
| 1257 | /* explicit id - between brackets */ |
| 1258 | id_data = data+i+1; |
| 1259 | id_size = id_end-(i+1); |
| 1260 | if( bFootnote ){ |
| 1261 | id_data++; |
| 1262 | id_size--; |
| 1263 | } |
| 1264 | } |
| 1265 | |
| 1266 | if( bFootnote ){ |
| 1267 | fn = get_footnote(rndr, id_data, id_size); |
| 1268 | if( !fn ) { |
| 1269 | rndr->notes.misref.nUsed++; |
| 1270 | fn = &rndr->notes.misref; |
| 1271 | } |
| 1272 | }else if( get_link_ref(rndr, link, title, id_data, id_size)<0 ){ |
| 1273 | goto char_link_cleanup; |
| 1274 | } |
| 1275 | |
| 1276 | i = id_end+1; |
| 1277 | |
| 1278 | /* shortcut reference style link */ |
| 1279 | }else{ |
| 1280 | if( get_link_ref(rndr, link, title, data+1, txt_e-1)<0 ){ |
| 1281 | goto char_link_cleanup; |
| 1282 | } |
| 1283 | /* rewinding a closing square bracket */ |
| 1284 | i = txt_e+1; |
| 1285 | } |
| 1286 | |
| 1287 | /* building content: img alt is escaped, link content is parsed */ |
| 1288 | if( txt_e>1 && content ){ |
| 1289 | if( is_img ) blob_append(content, data+1, txt_e-1); |
| 1290 | else parse_inline(content, rndr, data+1, txt_e-1); |
| 1291 | } |
| 1292 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -1168,20 +1168,19 @@ | |
| 1168 | static size_t char_link( |
| 1169 | struct Blob *ob, |
| 1170 | struct render *rndr, |
| 1171 | char *data, |
| 1172 | size_t offset, |
| 1173 | size_t size /* parse_inline() ensures that size > 0 */ |
| 1174 | ){ |
| 1175 | const int is_img = (offset && data[-1] == '!'); |
| 1176 | size_t i = 1, txt_e; |
| 1177 | struct Blob *content = 0; |
| 1178 | struct Blob *link = 0; |
| 1179 | struct Blob *title = 0; |
| 1180 | const struct footnote *fn = 0; |
| 1181 | int ret; |
| 1182 | |
| 1183 | /* checking whether the correct renderer exists */ |
| 1184 | if( (is_img && !rndr->make.image) || (!is_img && !rndr->make.link) ){ |
| 1185 | return 0; |
| 1186 | } |
| @@ -1188,104 +1187,101 @@ | |
| 1187 | |
| 1188 | /* looking for the matching closing bracket */ |
| 1189 | txt_e = matching_bracket_offset(data, data+size); |
| 1190 | if( !txt_e ) return 0; |
| 1191 | i = txt_e + 1; |
| 1192 | ret = 0; /* error if we don't get to the callback */ |
| 1193 | |
| 1194 | /* free-standing footnote refernece */ |
| 1195 | if(!is_img && size>3 && data[1]=='^'){ |
| 1196 | fn = get_footnote(rndr, data+2, txt_e-2); |
| 1197 | if( !fn ) { |
| 1198 | rndr->notes.misref.nUsed++; |
| 1199 | fn = &rndr->notes.misref; |
| 1200 | } |
| 1201 | }else{ |
| 1202 | |
| 1203 | /* skip "inter-bracket-whitespace" - any amount of whitespace or newline */ |
| 1204 | /* (this is much more laxist than original markdown syntax) */ |
| 1205 | while( i<size && (data[i]==' ' || data[i]=='\t' || data[i]=='\n') ){ i++; } |
| 1206 | |
| 1207 | /* allocate temporary buffers to store content, link and title */ |
| 1208 | title = new_work_buffer(rndr); |
| 1209 | content = new_work_buffer(rndr); |
| 1210 | link = new_work_buffer(rndr); |
| 1211 | |
| 1212 | if( i<size && data[i]=='(' ){ |
| 1213 | |
| 1214 | if( i+2<size && data[i+1]=='^' ){ /* span-bounded inline footnote */ |
| 1215 | |
| 1216 | const size_t k = matching_bracket_offset(data+i, data+size); |
| 1217 | if( !k ) goto char_link_cleanup; |
| 1218 | fn = add_inline_footnote(rndr, data+(i+2), k-2); |
| 1219 | i += k+1; |
| 1220 | }else{ /* inline style link */ |
| 1221 | size_t span_end = i; |
| 1222 | while( span_end<size |
| 1223 | && !(data[span_end]==')' && (span_end==i || data[span_end-1]!='\\')) |
| 1224 | ){ |
| 1225 | span_end++; |
| 1226 | } |
| 1227 | |
| 1228 | if( span_end>=size |
| 1229 | || get_link_inline(link, title, data+i+1, span_end-(i+1))<0 |
| 1230 | ){ |
| 1231 | goto char_link_cleanup; |
| 1232 | } |
| 1233 | |
| 1234 | i = span_end+1; |
| 1235 | } |
| 1236 | |
| 1237 | /* reference style link or span-bounded footnote reference */ |
| 1238 | }else if( i<size && data[i]=='[' ){ |
| 1239 | char *id_data; |
| 1240 | size_t id_size, id_end = i; |
| 1241 | int bFootnote; |
| 1242 | |
| 1243 | while( id_end<size && data[id_end]!=']' ){ id_end++; } |
| 1244 | |
| 1245 | if( id_end>=size ) goto char_link_cleanup; |
| 1246 | bFootnote = data[i+1]=='^'; |
| 1247 | |
| 1248 | if( i+1==id_end || (bFootnote && i+2==id_end) ){ |
| 1249 | /* implicit id - use the contents */ |
| 1250 | id_data = data+1; |
| 1251 | id_size = txt_e-1; |
| 1252 | }else{ |
| 1253 | /* explicit id - between brackets */ |
| 1254 | id_data = data+i+1; |
| 1255 | id_size = id_end-(i+1); |
| 1256 | if( bFootnote ){ |
| 1257 | id_data++; |
| 1258 | id_size--; |
| 1259 | } |
| 1260 | } |
| 1261 | |
| 1262 | if( bFootnote ){ |
| 1263 | fn = get_footnote(rndr, id_data, id_size); |
| 1264 | if( !fn ) { |
| 1265 | rndr->notes.misref.nUsed++; |
| 1266 | fn = &rndr->notes.misref; |
| 1267 | } |
| 1268 | }else if( get_link_ref(rndr, link, title, id_data, id_size)<0 ){ |
| 1269 | goto char_link_cleanup; |
| 1270 | } |
| 1271 | |
| 1272 | i = id_end+1; |
| 1273 | |
| 1274 | /* shortcut reference style link */ |
| 1275 | }else{ |
| 1276 | if( get_link_ref(rndr, link, title, data+1, txt_e-1)<0 ){ |
| 1277 | goto char_link_cleanup; |
| 1278 | } |
| 1279 | /* rewinding an "inter-bracket-whitespace" */ |
| 1280 | i = txt_e+1; |
| 1281 | } |
| 1282 | } |
| 1283 | /* building content: img alt is escaped, link content is parsed */ |
| 1284 | if( txt_e>1 && content ){ |
| 1285 | if( is_img ) blob_append(content, data+1, txt_e-1); |
| 1286 | else parse_inline(content, rndr, data+1, txt_e-1); |
| 1287 | } |
| 1288 |