Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source libSC Path canon.c
Document Actions

canon.c

by Michael L Powell last modified 2007-01-26 03:24

Click here to get the file

Size 3.7 kB - File type text/plain

File contents

/*ident	"@(#)Path:canon.c	3.1" */
/******************************************************************************
*
* C++ Standard Components, Release 3.0.
*
* Copyright (c) 1991, 1992 AT&T and Unix System Laboratories, Inc.
* Copyright (c) 1988, 1989, 1990 AT&T.  All Rights Reserved.
*
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T and Unix System
* Laboratories, Inc.  The copyright notice above does not evidence
* any actual or intended publication of such source code.
*
******************************************************************************/

#include "Pathlib.h"

static int component_is(const char * scan, const char * what, int whatlen)
{
	return ((strncmp(scan, what, whatlen) == 0) && (scan[whatlen] == '/' || scan[whatlen] == 0));
}

static void skip_component(const char * & scan)
{
	while (*scan != 0 && *scan != '/')
		scan++;
	while (*scan == '/')
		scan++;
}

static void copy_component(const char * buf, char * & put, const char * & scan)
{
	// remember to separate it from the previous component (if present) with a slash
	if (put > buf && put[-1] != '/')			
		*put++ = '/';
#if 0
	char * rem = put;
#endif
	while (*scan != 0 && *scan != '/')
		*put++ = *scan++;
#if 0
	if ((Path::get_max_file_length() != -1) && (put - rem > Path::get_max_file_length()))
	{
		char save = *put;
		*put = 0;
		int r = Path::filename_too_long.raise(rem);
		*put = save;
		if (r != 0)
			put = rem + Path::get_max_file_length();
	}
#endif
	while (*scan == '/')
		scan++;
}

static int has_preceding_component_and_its_not_dotdot(const char * buf, const char * p)
{
	if (p == buf)
		return 0;
	if (p == buf + 1)
		return (p[-1] != '/');
	if (p[-1] == '.' && p[-2] == '.' && (p == buf + 2 || p[-3] == '/'))
		return 0;
	return 1;
}			
	
static void handle_dotdot(const char * buf, char * & put, const char * & scan)
{
	// If there is no previous component and this is an absolute path, then
	// just ignore the .., otherwise, contract off the previous component if possible.
	// A contraction is possible iff there is a preceding component other than ..

	if (put == buf+1 && *buf == '/')
	{
		skip_component(scan);
	}
	else if (has_preceding_component_and_its_not_dotdot(buf, put))
	{
		// reset put to before the preceding component, then skip the ..
		while (put != buf && *--put != '/')
			;
		if (put == buf && *put == '/')
			put++;
		skip_component(scan);
	}
	else
	{
		copy_component(buf, put, scan);
	}
}

/* unixlike_slashes:
*	Initialize scan to point to beginning of buf
* gnulike_slashes:
*	Initialize scan to point to the second / in the rightmost //
* 	(beginning of buf if there is no //)
*/
static void init_scan(const char * buf, const char * & scan)
{
	//if (Path::get_slash_style() == Path::unixlike_slashes)
	{
		scan = buf;
	}
#if 0
	else
	{
		for (scan = buf + strlen(buf) - 1; scan >= buf; scan--)
		{
			if (scan[0] == '/' && scan[1] == '/')
			{
				scan++;
				break;
			}
		}
		if (scan < buf)
			scan = buf;
	}
#endif
}

static void canonicalize(char * buf)
{
	const char *scan;
	init_scan(buf, scan);
	char *put = buf;
	if (*scan == '/')  // absolute path name
	{
		*put++ = '/';
		do scan++;
		while (*scan == '/');
	}
	while (*scan)
	{
		// INVARIANT: scan is pointing at beginning of next component (i.e., NOT at /).

		if (component_is(scan, ".", 1))
			skip_component(scan);
		else if (component_is(scan, "..", 2))
			handle_dotdot(buf, put, scan);
		else
			copy_component(buf, put, scan);
	}
	if (put == buf) // if it is the empty relative path
		*put++ = '.';
	*put = 0;
}

void Path::canonicalize()
{
	//char *buf = new char [rep.length() + 1];
	char *buf = new char [rep.length() + 3]; // should be +2 but add one
						 // more for safety
	rep.dump(buf);
	::canonicalize(buf);
	rep = buf;
	delete buf;
#if 0
	check_length();
#endif
}
« April 2014 »
Su Mo Tu We Th Fr Sa
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
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: