lean-migrate / tasks /path /source.c
Hrushi's picture
Upload folder using huggingface_hub
bf9c466 verified
/* tasks/path/source.c
* Path canonicalization in C.
* Agents must migrate this to Rust using Vec<String> for segment lists.
*
* Key invariants to preserve:
* - ".." at root is clamped (no going above "/")
* - "." segments are removed
* - joining an absolute path (starts with "/") replaces the base
* - double slashes are collapsed
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_SEGMENTS 256
#define MAX_SEG_LEN 256
/* Normalize a path in-place (modifies path[] buffer).
* segments[] is a working array, out_segments[] receives the result.
* Returns number of output segments. */
int normalize_path(const char *path, char out_segments[][MAX_SEG_LEN], int max_out) {
char buf[4096];
strncpy(buf, path, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
/* Tokenise on '/' */
char *segs[MAX_SEGMENTS];
int n = 0;
char *tok = strtok(buf, "/");
while (tok && n < MAX_SEGMENTS) {
segs[n++] = tok;
tok = strtok(NULL, "/");
}
/* Stack-based resolution */
char *stack[MAX_SEGMENTS];
int top = 0;
for (int i = 0; i < n; i++) {
if (strcmp(segs[i], ".") == 0) {
/* skip */
} else if (strcmp(segs[i], "..") == 0) {
if (top > 0) top--; /* clamp at root */
} else {
stack[top++] = segs[i];
}
}
int count = top < max_out ? top : max_out;
for (int i = 0; i < count; i++) {
strncpy(out_segments[i], stack[i], MAX_SEG_LEN - 1);
out_segments[i][MAX_SEG_LEN - 1] = '\0';
}
return count;
}
/* Join base and rel path segments.
* If rel starts with '/' it replaces base entirely. */
int join_paths(
const char *base, const char *rel,
char out_segments[][MAX_SEG_LEN], int max_out)
{
char combined[8192];
if (rel[0] == '/') {
/* Absolute rel — ignore base */
snprintf(combined, sizeof(combined), "%s", rel);
} else {
snprintf(combined, sizeof(combined), "%s/%s", base, rel);
}
return normalize_path(combined, out_segments, max_out);
}
/* Depth = number of segments after normalization */
int path_depth(const char *path) {
char segs[MAX_SEGMENTS][MAX_SEG_LEN];
return normalize_path(path, segs, MAX_SEGMENTS);
}
/* Example usage */
int main(void) {
char out[MAX_SEGMENTS][MAX_SEG_LEN];
int n = normalize_path("usr/local/../bin", out, MAX_SEGMENTS);
printf("normalize(usr/local/../bin): ");
for (int i = 0; i < n; i++) printf("%s%s", out[i], i + 1 < n ? "/" : "");
printf("\n");
n = join_paths("usr/local", "bin", out, MAX_SEGMENTS);
printf("join(usr/local, bin): ");
for (int i = 0; i < n; i++) printf("%s%s", out[i], i + 1 < n ? "/" : "");
printf("\n");
printf("depth(usr/local/bin): %d\n", path_depth("usr/local/bin"));
return 0;
}