Beispiel #1
0
func Test_InitSorted(t *testing.T) {
	data := sort.IntSlice{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
	tree := Tree{}
	tree.InitSorted(data.Len())
	check(t, data, &tree, tree.root)
	check_iter(t, data, &tree)

	data = sort.IntSlice{}
	f := map[int]struct{}{}
	tree = Tree{}
	for i := 100; i > 0; i-- {
		v := rand.Intn(1000)
		if _, ok := f[v]; ok {
			continue
		}
		data = append(data, v)
	}
	sort.Sort(data)
	tree.InitSorted(data.Len())
	check(t, data, &tree, tree.root)
	check_iter(t, data, &tree)
}
//Be careful to use same partioning as in lecture
//and return total number of comparisons
func Quicksort(input sort.IntSlice, ps pivotSelector) int {
	if input.Len() < 2 {
		return 0
	}
	input.Swap(0, ps(input))
	i := 1
	for j := 1; j < input.Len(); j++ {
		if input.Less(j, 0) {
			input.Swap(i, j)
			i++
		}
	}
	input.Swap(0, i-1)
	comparisons := input.Len() - 1
	comparisons += Quicksort(input[:i-1], ps)
	comparisons += Quicksort(input[i:], ps)
	return comparisons
}
Beispiel #3
0
func (f *File) saveUsingXrefStream() error {
	info, err := os.Stat(f.filename)
	if err != nil {
		return err
	}

	file, err := os.OpenFile(f.filename, os.O_RDWR|os.O_APPEND, 0666)
	if err != nil {
		return err
	}
	defer func() {
		err := file.Close()
		if err != nil {
			panic(err)
		}
	}()

	offset := info.Size() + 1

	n, err := writeLineBreakTo(file)
	if err != nil {
		return err
	}
	offset += n

	xrefs := map[Integer]crossReference{}

	xrefs[0] = crossReference{0, 0, 65535}

	free := sort.IntSlice{0}
	for i := range f.objects {
		switch typed := f.objects[i].(type) {
		case crossReference:
			// no-op, don't need to write unchanged objects to file
			// however, we do need to handle the free list
			// xrefs[Integer(i)] = typed
			if typed[0] == 0 {
				free = append(free, int(i))
			}
		case IndirectObject:
			xrefs[Integer(i)] = crossReference{1, uint(offset - 1), typed.GenerationNumber}
			n, err = typed.writeTo(file)
			if err != nil {
				return err
			}
			offset += n

			n, err = writeLineBreakTo(file)
			if err != nil {
				return err
			}
			offset += n
		case freeObject:
			xrefs[Integer(i)] = crossReference{0, 0, uint(typed)}
			free = append(free, int(i))
		default:
			panic(fmt.Sprintf("unhandled type: %T", typed))
		}
	}

	// Figure out the highest object number to set Size properly
	var maxObjNum uint
	for objNum := range f.objects {
		if objNum > maxObjNum {
			maxObjNum = objNum
		}
	}

	// add an xref for the xrefstream
	xrefstreamObjectNumber := uint(maxObjNum + 1)
	maxObjNum++
	xref := crossReference{1, uint(offset - 1), 0}
	xrefs[Integer(xrefstreamObjectNumber)] = xref
	f.objects[xrefstreamObjectNumber] = xref

	// fill in the free linked list
	free.Sort()
	for i := 0; i < free.Len()-1; i++ {
		xref := xrefs[Integer(free[i])]
		xref[1] = uint(free[i+1])
		xrefs[Integer(free[i])] = xref
	}

	objects := make(sort.IntSlice, 0, len(xrefs))
	for objectNumber := range xrefs {
		objects = append(objects, int(objectNumber))
	}
	objects.Sort()

	// group into consecutive sets
	groups := []sort.IntSlice{}
	groupStart := 0
	for i := range objects {
		if i == 0 {
			continue
		}

		if objects[i] != objects[i-1]+1 {
			groups = append(groups, objects[groupStart:i])
			groupStart = i
		}
	}
	groups = append(groups, objects[groupStart:])

	// Create the xrefstream dictionary (the trailer)
	trailer := Dictionary{}
	trailer[Name("Size")] = Integer(maxObjNum + 1)

	// Prev
	if f.prev != 0 {
		trailer[Name("Prev")] = f.prev
	}

	// Root
	trailer[Name("Root")] = f.Root

	// Encrypt
	if len(f.Encrypt) != 0 {
		trailer[Name("Encrypt")] = f.Encrypt
	}

	// Info
	if f.Info.ObjectNumber != 0 {
		trailer[Name("Info")] = f.Info
	}

	// ID
	if len(f.ID) != 0 {
		trailer[Name("ID")] = f.ID
	}

	// Add xrefstream specific things to trailer
	trailer["Type"] = Name("XRef")

	// Index
	index := Array{}
	// fmt.Println(groups)
	for _, group := range groups {
		index = append(index, Integer(group[0]), Integer(len(group)))
	}
	trailer["Index"] = index

	// layout for the stream (W)
	maxXref := [3]uint{}
	for _, xref := range xrefs {
		for i := 0; i < len(xref); i++ {
			if xref[i] > maxXref[i] {
				maxXref[i] = xref[i]
			}
		}
	}
	nBytes := [3]int{}
	for i := range nBytes {
		nBytes[i] = nBytesForInt(int(maxXref[i]))
	}
	trailer["W"] = Array{Integer(nBytes[0]), Integer(nBytes[1]), Integer(nBytes[2])}

	// log.Println(xrefs)

	stream := &bytes.Buffer{}
	for _, group := range groups {
		for _, objectNumber := range group {
			xref := xrefs[Integer(objectNumber)]
			for i := range xref {
				_, err = stream.Write(intToBytes(xref[i], nBytes[i]))
				if err != nil {
					return err
				}
			}
		}
	}

	xrefstream := IndirectObject{
		ObjectReference: ObjectReference{
			ObjectNumber: xrefstreamObjectNumber,
		},
		Object: Stream{
			Dictionary: trailer,
			Stream:     stream.Bytes(),
		},
	}
	_, err = f.Add(xrefstream)
	if err != nil {
		return err
	}

	_, err = xrefstream.writeTo(file)
	if err != nil {
		return err
	}

	fmt.Fprintf(file, "\nstartxref\n%d\n%%%%EOF", offset-1)

	return nil
}
Beispiel #4
0
func (f *File) saveUsingXrefTable() error {
	info, err := os.Stat(f.filename)
	if err != nil {
		return err
	}

	file, err := os.OpenFile(f.filename, os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		return err
	}
	defer func() {
		err := file.Close()
		if err != nil {
			panic(err)
		}
	}()

	offset := info.Size() + 1

	n, err := writeLineBreakTo(file)
	if err != nil {
		return err
	}
	offset += n

	xrefs := map[Integer]crossReference{}

	xrefs[0] = crossReference{0, 0, 65535}

	free := sort.IntSlice{}
	for i := range f.objects {
		switch typed := f.objects[i].(type) {
		case crossReference:
			// no-op, don't need to write unchanged objects to file
			// however, we do need to handle the free list
			// xrefs[Integer(i)] = typed
			if typed[0] == 0 {
				free = append(free, int(i))
			}
		case IndirectObject:
			xrefs[Integer(i)] = crossReference{1, uint(offset - 1), typed.GenerationNumber}
			n, err = typed.writeTo(file)
			if err != nil {
				return err
			}
			offset += n

			n, err = writeLineBreakTo(file)
			if err != nil {
				return err
			}
			offset += n
		case freeObject:
			xrefs[Integer(i)] = crossReference{0, 0, uint(typed)}
			free = append(free, int(i))
		default:
			panic(fmt.Sprintf("unhandled type: %T", typed))
		}
	}

	// fill in the free linked list
	free.Sort()
	for i := 0; i < free.Len()-1; i++ {
		xref := xrefs[Integer(free[i])]
		xref[1] = uint(free[i+1])
		xrefs[Integer(free[i])] = xref
	}

	objects := make(sort.IntSlice, 0, len(xrefs))
	for objectNumber := range xrefs {
		objects = append(objects, int(objectNumber))
	}
	objects.Sort()

	// group into consecutive sets
	groups := []sort.IntSlice{}
	groupStart := 0
	for i := range objects {
		if i == 0 {
			continue
		}

		if objects[i] != objects[i-1]+1 {
			groups = append(groups, objects[groupStart:i])
			groupStart = i
		}
	}
	// add remaining group
	groups = append(groups, objects[groupStart:])

	// write as an xref table to file
	fmt.Fprintf(file, "xref\n")
	for _, group := range groups {
		fmt.Fprintf(file, "%d %d\n", group[0], len(group))
		for _, objectNumber := range group {
			xref := xrefs[Integer(objectNumber)]
			fmt.Fprintf(file, "%010d %05d ", xref[1], xref[2])
			switch xref[0] {
			case 0:
				// f entries
				fmt.Fprintf(file, "f\r\n")
			case 1:
				// n entries
				fmt.Fprintf(file, "n\r\n")
			case 2:
				panic("can't be in xref table")
			default:
				panic("unhandled case")
			}
		}
	}

	// Setup create the trailer
	fmt.Fprintf(file, "\ntrailer\n")
	trailer := Dictionary{}

	// Size
	// Figure out the highest object number to set Size properly
	var maxObjNum uint
	for objNum := range f.objects {
		if objNum > maxObjNum {
			maxObjNum = objNum
		}
	}
	trailer[Name("Size")] = Integer(maxObjNum + 1)

	// Prev
	if f.prev != 0 {
		trailer[Name("Prev")] = f.prev
	}

	// Root
	trailer[Name("Root")] = f.Root

	// Encrypt
	if len(f.Encrypt) != 0 {
		trailer[Name("Encrypt")] = f.Encrypt
	}

	// Info
	if f.Info.ObjectNumber != 0 {
		trailer[Name("Info")] = f.Info
	}

	// ID
	if len(f.ID) != 0 {
		trailer[Name("ID")] = f.ID
	}

	_, err = trailer.writeTo(file)
	if err != nil {
		return err
	}

	fmt.Fprintf(file, "\nstartxref\n%d\n%%%%EOF", offset-1)

	return nil
}