Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] View of /smlnj-lib/trunk/Dev/CSV/list-csv.sml
ViewVC logotype

View of /smlnj-lib/trunk/Dev/CSV/list-csv.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4057 - (download) (annotate)
Fri Mar 6 02:00:10 2015 UTC (4 years ago) by jhr
File size: 1842 byte(s)
  working on csv library
(* list-csv.sml
 *
 * COPYRIGHT (c) 2015 The Fellowship of SML/NJ (http://www.smlnj.org)
 * All rights reserved.
 *
 * Support for reading and writing comma-separated-value files.
 *)

structure ListCSV : CSV where type 'a seq = 'a list =
  struct

    structure SS = Substring

    type 'a seq = 'a list

    exception Error

    fun parse ln = let
	  fun splitNext start = let
		fun extract ss = SS.string(SS.trimr (SS.size ss) start)
		fun scan (ss, quoted) = (case (SS.getc ss, quoted)
		       of (NONE, false) => (extract ss, ss)
			| (NONE, true) => raise Error
			| (SOME(#",", ss'), false) => (extract ss, ss')
			| (SOME(#"\"", ss'), true) => (case SS.getc ss
			     of NONE => (extract ss, ss')
			      | SOME(#",", ss') => (extract ss, ss')
			      | _ => raise Error
			    (* end case *))
			| (SOME(#"\"", ss'), false) => scan(ss', quoted) (* error? *)
			| (SOME(_, ss'), _) => scan(ss', quoted)
		      (* end case *))
		in
		  case SS.getc start
		   of SOME(#"\"", ss') => scan(ss', true)
		    | _ => scan (start, false)
		  (* end case *)
		end
	  and scanLine (ss, fields) = if SS.isEmpty ss
		then List.rev fields
		else let
		  val (fld, ss) = splitNext ss
		  in
		    scanLine (ss, fld::fields)
		  end
	  in
	    SOME(scanLine (SS.full ln, []))
	      handle Error => NONE
	  end

  (* convert a CSV line to a sequence of its fields; returns NONE on error *)
    fun fromString s = parse s

    val hasComma = CharVector.exists (fn #"," => true | _ => false)

    fun cvtField s = if hasComma s
	  then concat["\"", s, "\""]  (* what if it has a quote? *)
	  else s

  (* convert a sequence to a string *)
    fun toString flds = String.concatWith "," (List.map cvtField flds)

    fun fmt cvt = let
	  fun cvt' x = cvtField (cvt x)
	  in
	    fn flds => String.concatWith "," (List.map cvt' flds)
	  end

  end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0