File: qring.ml

package info (click to toggle)
xen-api-libs 0.5.2-3
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 1,940 kB
  • sloc: ml: 13,925; sh: 2,930; ansic: 1,699; makefile: 1,240; python: 83
file content (141 lines) | stat: -rw-r--r-- 3,550 bytes parent folder | download
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
(*
 * Copyright (C) 2006-2009 Citrix Systems Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; version 2.1 only. with the special
 * exception on linking described in file LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *)
type t = {
	sz: int;
	data: string;
	mutable prod: int;
	mutable cons: int;
	mutable pwrap: bool;
}

exception Data_limit
exception Full

let make sz = { sz = sz; data = String.create sz; prod = 0; cons = 0; pwrap = false }

let to_consume ring =
	if ring.pwrap then
		ring.sz - (ring.cons - ring.prod)
	else
		ring.prod - ring.cons

let to_fill ring =
	if ring.pwrap then
		ring.cons - ring.prod
	else
		ring.cons + (ring.sz - ring.prod)

let is_full ring = ring.pwrap && ring.prod = ring.cons
let is_empty ring = not ring.pwrap && ring.prod = ring.cons

let adv_cons ring i =
	ring.cons <- ring.cons + i;
	if ring.cons >= ring.sz then (
		ring.cons <- ring.cons - ring.sz;
		ring.pwrap <- false;
	)

let adv_prod ring i =
	ring.prod <- ring.prod + i;
	if ring.prod >= ring.sz then (
		ring.prod <- ring.prod - ring.sz;
		ring.pwrap <- true;
	)

let consume ring sz =
	let max = to_consume ring in
	let sz =
		if sz > 0 then
			if sz > max then max else sz
		else
			if max + sz > 0 then max + sz else 0
		in
	let out = String.create sz in
	if ring.pwrap then (
		let left_end = ring.sz - ring.cons in
		if sz > left_end then (
			String.blit ring.data ring.cons out 0 left_end;
			String.blit ring.data 0 out left_end (sz - left_end);
		) else
			String.blit ring.data ring.cons out 0 sz;
	) else
		String.blit ring.data ring.cons out 0 sz;
	adv_cons ring sz;
	out

let consume_all ring = consume ring (max_int)

let skip ring n =
	let max = to_consume ring in
	let n = if n > max then max else n in
	adv_cons ring n

let feed_data ring data =
	let len = String.length data in
	let max = to_fill ring in
	if len > max then
		raise Data_limit;
	if ring.prod + len > ring.sz then (
		let firstblitsz = ring.sz - ring.prod in
		String.blit data 0 ring.data ring.prod firstblitsz;
		String.blit data firstblitsz ring.data 0 (len - firstblitsz);
	) else
		String.blit data 0 ring.data ring.prod len;
	adv_prod ring len;
	()

(* read and search directly to the qring.
 * since we have give a continuous buffer, we limit our read length to the
 * maximum continous length instead of the full length of the qring left.
 * after the read, piggyback into the new data.
 *)
let read_search ring fread fsearch len =
	let prod = ring.prod in
	let maxlen =
		if ring.pwrap
		then ring.cons - ring.prod
		else ring.sz - ring.prod
		in
	if maxlen = 0 then
		raise Full;
	let len = if maxlen < len then maxlen else len in
	let n = fread ring.data prod len in
	if n > 0 then (
		adv_prod ring n;
		fsearch ring.data prod n 
	);
	n

let search ring c =
	let search_from_to f t =
		let found = ref false in
		let i = ref f in
		while not !found && !i < t
		do
			if ring.data.[!i] = c then
				found := true
			else
				incr i
		done;
		if not !found then
			raise Not_found;
		!i - f
		in
	if is_empty ring then
		raise Not_found;
	if ring.pwrap then (
		try search_from_to ring.cons ring.sz
		with Not_found -> search_from_to 0 ring.prod
	) else
		search_from_to ring.cons ring.prod