File: mstring.ml

package info (click to toggle)
camlimages 2.00-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 3,536 kB
  • ctags: 2,325
  • sloc: ml: 10,848; ansic: 2,396; makefile: 599; sh: 30
file content (174 lines) | stat: -rw-r--r-- 5,150 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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*            Franois Pessaux, projet Cristal, INRIA Rocquencourt     *)
(*            Pierre Weis, projet Cristal, INRIA Rocquencourt          *)
(*            Jun Furuse, projet Cristal, INRIA Rocquencourt           *)
(*                                                                     *)
(*  Copyright 1999,2000,2001,2002,2001,2002                            *)
(*  Institut National de Recherche en Informatique et en Automatique.  *)
(*  Distributed only by permission.                                    *)
(*                                                                     *)
(***********************************************************************)

(*
 * String utilities
 *)

(* split a string according to char_sep predicate *)
let split_str char_sep str =
  let len = String.length str in
  if len = 0 then [] else
    let rec skip_sep cur =
      if cur >= len then cur
      else if char_sep str.[cur] then skip_sep (succ cur)
      else cur  in
    let rec split beg cur =
      if cur >= len then 
	if beg = cur then []
	else [String.sub str beg (len - beg)]
      else if char_sep str.[cur] 
	   then 
	     let nextw = skip_sep cur in
	      (String.sub str beg (cur - beg))
		::(split nextw nextw)
	   else split beg (succ cur) in
    let wstart = skip_sep 0 in
    split wstart wstart

(* split a string according to char_sep predicate *)
let split_str_quoted char_sep str =
  let len = String.length str in
  if len = 0 then [] 
  else begin
    let cword = ref "" in
      let rec skip_sep cur = 
	if cur >= len then cur
	else if char_sep str.[cur] then skip_sep (succ cur)
	else cur  
      in
      let rec close_quote cur =
	if cur >= len then cur
	else if str.[cur] = '"' then cur
	else begin
	  cword := !cword ^ String.make 1 str.[cur];
	  close_quote (succ cur) 
	end
      in
    let rec split beg cur =
      if cur >= len then 
	if beg = cur then []
	else [!cword]
      else begin
	if str.[cur] = '"' then begin
	  let endquote = close_quote (succ cur) in
	  split beg (succ endquote)
	end else if char_sep str.[cur] then 
	  let nextw = skip_sep cur in
	  let word = !cword in
	  cword := "";
	  word :: (split nextw nextw)
	else begin
	  cword := !cword ^ String.make 1 str.[cur];
	  split beg (succ cur) 
	end
      end
    in
    let wstart = skip_sep 0 in
    split wstart wstart
  end

(* extract the . suffix (dot excluded) of a string *)
let get_suffix s =
  try
    let dotpos = succ (String.rindex s '.') in
      String.sub s dotpos (String.length s - dotpos)
  with
    Not_found -> ""

(* HEX/DEC conversions *)
let hex_to_dec c = match c with
    '0'..'9' -> Char.code c - 48
  | 'a'..'f' -> Char.code c - 87 (* 87 = Char.code 'a' - 10 *)
  | 'A'..'F' -> Char.code c - 55 (* 55 = Char.code 'A' - 10 *)
  | _ -> failwith "hex_to_dec"

let dec_to_hex i =
  if i < 10 then Char.chr (i + 48)  (* 48 = Char.code '0' *)
  else Char.chr (i + 55)            (* 55 = Char.code 'A' - 10 *)

(* Converting a hex stored string *)
let hex_to_string s =
  let len = String.length s / 2 in
  let res = String.create len in
    for i = 0 to len - 1 do
      res.[i] <- Char.chr ( 16 * (hex_to_dec s.[i+i]) + hex_to_dec s.[i+i+1])
      done;
    res

let gensym =
  let cnter = ref 0 in
  (fun n ->
    incr cnter;
    n ^ string_of_int !cnter)

let rem_trailing_sp s =
  let l = String.length s in
  let pos = ref (l - 1) in
  while !pos >= 0 && List.mem s.[!pos] [' '; '\t'] do decr pos done;
  if !pos = l - 1 then s
  else String.sub s 0 (succ !pos)

let catenate_sep sep =
  function 
      [] -> ""
    | x::l -> List.fold_left (fun s s' -> s^sep^s') x l

(* Filters CRLF:
 *  CR -> LF
 *  CRLF -> LF
 *  LF -> LF
 * We do this on successive chunks of a stream, so we need to consider
 * the case when the chunk finishes on CR.
 * Assume len > 0
 *)

let norm_crlf lastwascr buf offs len =
  let rpos = ref offs
  and wpos = ref 0
  and dest = String.create (len + 1) (* we need one more char *)
  and limit = offs + len - 1  
  and lastiscr = ref false in
  if lastwascr then
    if buf.[!rpos] = '\n' then begin
      dest.[!wpos] <- '\n';
      incr rpos; incr wpos
    end
    else begin
      dest.[!wpos] <- '\n'; incr wpos
    end;

  while !rpos < limit do
    match buf.[!rpos] with
      '\n' -> dest.[!wpos] <- '\n'; incr rpos; incr wpos
    | '\r' -> 
	if buf.[!rpos + 1] = '\n'
	then begin dest.[!wpos] <- '\n'; rpos := !rpos + 2; incr wpos end
	else begin dest.[!wpos] <- '\n'; incr rpos; incr wpos end
    | c -> dest.[!wpos] <- c; incr rpos; incr wpos 
  done;
  begin match buf.[offs+len-1] with
    '\n' -> dest.[!wpos] <- '\n'; incr wpos
  | '\r' -> lastiscr := true
  | c -> dest.[!wpos] <- c; incr wpos
  end;
  String.sub dest 0 !wpos, !lastiscr

let hexchar c = 
  let s = String.make 3 '%'
  and i = Char.code c in
  s.[1] <- dec_to_hex (i/16);
  s.[2] <- dec_to_hex (i mod 16);
  s