Exemple #1
0
static int
path_init(PathPathObject *self, PyObject *args, PyObject *kwds)
{
  int w, h;
  if (!PyArg_ParseTuple(args, "(ii)", &w, &h))
    return -1;
  self->path = pathNew(w,h);
  if (self->path == NULL) {
    PyErr_SetString(PyExc_ValueError, "invalid dimensions");
    return -1;
  }
  return 0;
}
Exemple #2
0
void pathNormalize(Path* path)
{
  // Split the path into components.
  Slice components[MAX_COMPONENTS];
  int numComponents = 0;
  
  char* start = path->chars;
  char* end = path->chars;

  // Split into parts and handle "." and "..".
  int leadingDoubles = 0;
  for (;;)
  {
    if (*end == '\0' || isSeparator(*end))
    {
      // Add the current component.
      if (start != end)
      {
        size_t length = end - start;
        if (length == 1 && start[0] == '.')
        {
          // Skip "." components.
        }
        else if (length == 2 && start[0] == '.' && start[1] == '.')
        {
          // Walk out of directories on "..".
          if (numComponents > 0)
          {
            // Discard the previous component.
            numComponents--;
          }
          else
          {
            // Can't back out any further, so preserve the "..".
            leadingDoubles++;
          }
        }
        else
        {
          if (numComponents >= MAX_COMPONENTS)
          {
            fprintf(stderr, "Path cannot have more than %d path components.\n",
                    MAX_COMPONENTS);
            exit(1);
          }
          
          components[numComponents].start = start;
          components[numComponents].end = end;
          numComponents++;
        }
      }
      
      // Skip over separators.
      while (*end != '\0' && isSeparator(*end)) end++;
      
      start = end;
      if (*end == '\0') break;
    }
    
    end++;
  }
  
  // Preserve the path type. We don't want to turn, say, "./foo" into "foo"
  // because that changes the semantics of how that path is handled when used
  // as an import string.
  bool needsSeparator = false;

  Path* result = pathNew("");
  size_t prefixLength = absolutePrefixLength(path->chars);
  if (prefixLength > 0)
  {
    // It's an absolute path, so preserve the absolute prefix.
    Slice slice;
    slice.start = path->chars;
    slice.end = path->chars + prefixLength;
    appendSlice(result, slice);
  }
  else if (leadingDoubles > 0)
  {
    // Add any leading "..".
    for (int i = 0; i < leadingDoubles; i++)
    {
      if (needsSeparator) pathAppendChar(result, '/');
      pathAppendString(result, "..");
      needsSeparator = true;
    }
  }
  else if (path->chars[0] == '.' && isSeparator(path->chars[1]))
  {
    // Preserve a leading "./", since we use that to distinguish relative from
    // logical imports.
    pathAppendChar(result, '.');
    needsSeparator = true;
  }
  
  for (int i = 0; i < numComponents; i++)
  {
    if (needsSeparator) pathAppendChar(result, '/');
    appendSlice(result, components[i]);
    needsSeparator = true;
  }
  
  if (result->length == 0) pathAppendChar(result, '.');
  
  // Copy back into the original path.
  free(path->chars);
  path->capacity = result->capacity;
  path->chars = result->chars;
  path->length = result->length;
}