Append dotted path segments from rel_path (extension-stripped) to output buffer.
| 1188 | |
| 1189 | // Append dotted path segments from rel_path (extension-stripped) to output buffer. |
| 1190 | static char *append_path_segments(char *out, const char *rel_path, size_t plen, bool has_name) { |
| 1191 | const char *start = rel_path; |
| 1192 | const char *end_ptr = rel_path + plen; |
| 1193 | while (start < end_ptr) { |
| 1194 | const char *slash = (const char *)memchr(start, '/', end_ptr - start); |
| 1195 | const char *part_end = slash ? slash : end_ptr; |
| 1196 | size_t part_len = (size_t)(part_end - start); |
| 1197 | |
| 1198 | if (part_len > 0) { |
| 1199 | bool is_last = (part_end == end_ptr); |
| 1200 | if (!should_skip_fqn_part(start, part_len, is_last, has_name)) { |
| 1201 | /* Drop a leading '.' from a dotfile / hidden-dir segment |
| 1202 | * (".env" -> "env", ".github" -> "github"). Otherwise the QN |
| 1203 | * separator '.' plus the segment's own leading '.' produce a |
| 1204 | * malformed "proj..env" double-dot, and a root dotfile's empty |
| 1205 | * stem collides with the project QN. */ |
| 1206 | const char *seg = start; |
| 1207 | size_t seg_len = part_len; |
| 1208 | if (seg[0] == '.') { |
| 1209 | seg++; |
| 1210 | seg_len--; |
| 1211 | } |
| 1212 | if (seg_len > 0) { |
| 1213 | *out++ = '.'; |
| 1214 | memcpy(out, seg, seg_len); |
| 1215 | out += seg_len; |
| 1216 | } |
| 1217 | } |
| 1218 | } |
| 1219 | start = part_end + SKIP_ONE; |
| 1220 | } |
| 1221 | return out; |
| 1222 | } |
| 1223 | |
| 1224 | char *cbm_fqn_compute(CBMArena *a, const char *project, const char *rel_path, const char *name) { |
| 1225 | if (!project) |
no test coverage detected