aboutsummaryrefslogtreecommitdiff
path: root/simplify_path.c
blob: 6617a5489c44e122fee40e93e0bff668779c3e2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// 71. Simplify Path
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// given a string 'path', which is an absolute path (starting with a slash) to a
// file or directory in a unix-style file system, convert it to the simplified
// canonical path

char *go_upper(char *head, char *tail) {
  for (; *tail != '/' && tail != head; tail--)
    ;
  if (tail == head) {
    *head = '/';
    tail++;
  }
  *tail = '\0';
  return tail;
}

char *go_lower(char *tail, char *level) {
  while ((*tail++ = *level++) != '\0')
    ;
  return tail - 1;
}

char *next_level(char **level, char *path) {
  *level = malloc(sizeof(char) * 200);
  int l = 0;
  (*level)[l++] = *path++;
  for (; *path == '/'; path++)
    ;
  for (; *path != '/' && *path != '\0'; path++)
    (*level)[l++] = *path;
  (*level)[l] = '\0';
  return path;
}

char *simplifyPath(char *path) {
  char *head = malloc(sizeof(char) * strlen(path));
  char *tail = head, *level;
  *tail++ = '/';
  while (*path != '\0') {
    path = next_level(&level, path);
    if (!strcmp(level, "/.") || !strcmp(level, "/"))
      continue;
    else if (!strcmp(level, "/.."))
      tail = go_upper(head, tail);
    else
      tail = go_lower(tail, level);
    free(level);
  }
  while (*(head + 1) == '/')
    head++;
  return head;
}

int main() {
  char p1[] = {"/home/"}, p2[] = {"/../"}, p3[] = {"/home//foo/"};
  printf("%s\n", simplifyPath(p1)); // expect: /home
  printf("%s\n", simplifyPath(p2)); // expect: /
  printf("%s\n", simplifyPath(p3)); // expect: /home/foo
}