class Protocol::HTTP::Reference

A relative reference, excluding any authority.

def self.[] reference

def self.[] reference
	if reference.is_a? self
		return reference
	else
		return self.parse(reference)
	end
end

def self.parse(path = '/', parameters = nil)

Generate a reference from a path and user parameters. The path may contain a `#fragment` or `?query=parameters`.
def self.parse(path = '/', parameters = nil)
	base, fragment = path.split('#', 2)
	path, query_string = base.split('?', 2)
	
	self.new(path, query_string, fragment, parameters)
end

def + other

def + other
	other = self.class[other]
	
	self.class.new(
		expand_path(self.path, other.path),
		other.query_string,
		other.fragment,
		other.parameters,
	)
end

def <=> other

def <=> other
	to_ary <=> other.to_ary
end

def append(buffer)

def append(buffer)
	if query_string?
		buffer << URL.escape_path(@path) << '?' << @query_string
		buffer << '&' << URL.encode(@parameters) if parameters?
	else
		buffer << URL.escape_path(@path)
		buffer << '?' << URL.encode(@parameters) if parameters?
	end
	
	if fragment?
		buffer << '#' << URL.escape(@fragment)
	end
	
	return buffer
end

def dup(path = nil, parameters = nil, merge = true)

def dup(path = nil, parameters = nil, merge = true)
	if merge and @parameters
		if parameters
			parameters = @parameters.merge(parameters)
		else
			parameters = @parameters
		end
	end
	
	if path
		path = expand_path(@path, path)
	else
		path = @path
	end
	
	self.class.new(path, @query_string, @fragment, parameters)
end

def expand_path(base, relative)

def expand_path(base, relative)
	if relative.start_with? '/'
		return relative
	else
		path = split(base)
		# drop the last path element for relative computations, e.g.
		# /foo/bar/index.html -> /foo/bar/#{relative}
		path.pop 
		
		parts = split(relative)
		
		parts.each do |part|
			if part == '..'
				path.pop
			else
				path << part
			end
		end
		
		return path.join('/')
	end
end

def fragment?

def fragment?
	@fragment and !@fragment.empty?
end

def freeze

def freeze
	return self if frozen?
	
	@path.freeze
	@query_string.freeze
	@fragment.freeze
	@parameters.freeze
	
	super
end

def initialize(path = '/', query_string = nil, fragment = nil, parameters = nil)

def initialize(path = '/', query_string = nil, fragment = nil, parameters = nil)
	@path = path
	@query_string = query_string
	@fragment = fragment
	@parameters = parameters
end

def parameters?

def parameters?
	@parameters and !@parameters.empty?
end

def query_string?

def query_string?
	@query_string and !@query_string.empty?
end

def split(path)

def split(path)
	if path.empty?
		[path]
	else
		path.split('/', -1)
	end
end

def to_ary

def to_ary
	[@path, @query_string, @fragment, @parameters]
end

def to_str

def to_str
	append(String.new)
end