File xcodes.icn

Summary

###########################################################################

	File:     xcodes.icn

	Subject:  Procedures to save and restore Icon data

	Author:   Bob Alexander

	Date:     November 19, 1997

###########################################################################

   This file is in the public domain.

###########################################################################

	Contributor:  Ralph E. Griswold

###########################################################################

  Note:  This version handles the encoding of records using canonical
  names:  record0, record1, ... . This allows programs to decode files
  by providing declarations for these names when the original declarations
  are not available.  This version also provides for procedures and
  files present in the encoded file that are not in the decoding program.

  This version should be merged with the ordinary version.

  Description
  -----------

     These procedures provide a way of storing Icon values in files
  and retrieving them.  The procedure xencode(x,f) stores x in file f
  such that it can be converted back to x by xdecode(f).  These
  procedures handle several kinds of values, including structures of
  arbitrary complexity and even loops.  The following sequence will
  output x and recreate it as y:

	f := open("xstore","w")
	xencode(x,f)
	close(f)
	f := open("xstore")
	y := xdecode(f)
	close(f)

  For "scalar" types -- null, integer, real, cset, and string, the
  above sequence will result in the relationship

	x === y

     For structured types -- list, set, table, and record types --
  y is, for course, not identical to x, but it has the same "shape" and
  its elements bear the same relation to the original as if they were
  encoded and decoded individually.

     Files, co-expressions, and windows cannot generally be restored in any
  way that makes much sense.  These objects are restored as empty lists so
  that (1) they will be unique objects and (2) will likely generate
  run-time errors if they are (probably erroneously) used in
  computation.  However, the special files &input, &output, and &errout are
  restored.

     Not much can be done with functions and procedures, except to preserve
  type and identification.

     The encoding of strings and csets handles all characters in a way
  that it is safe to write the encoding to a file and read it back.

     xdecode() fails if given a file that is not in xcode format or it
  the encoded file contains a record for which there is no declaration
  in the program in which the decoding is done.  Of course, if a record
  is declared differently in the encoding and decoding programs, the
  decoding may be bogus.

     xencoden() and xdecoden() perform the same operations, except
  xencoden() and xdecoden() take the name of a file, not a file.

     xencodet() and xdecodet() are like xencode() and xdecode()
  except that the trailing argument is a type name.  If the encoded
  decoded value is not of that type, they fail.  xencodet() does
  not take an opt argument.

###########################################################################

  Complete calling sequences
  --------------------------

	xencode(x, f, p) # returns f

	where

		x is the object to encode

		f is the file to write (default &output)

		p is a procedure that writes a line on f using the
		  same interface as write() (the first parameter is
		  always a the value passed as "file") (default: write)


	xencode(f, p) # returns the restored object

	where

		f is the file to read (default &input)

		p is a procedure that reads a line from f using the
		  same interface as read() (the parameter is
		  always a the value passed as "file") (default: read)


  The "p" parameter is not normally used for storage in text files, but
  it provides the flexibility to store the data in other ways, such as
  a string in memory.  If "p" is provided, then "f" can be any
  arbitrary data object -- it need not be a file.

  For example, to "write" x to an Icon string:

	record StringFile(s)

	procedure main()
	   ...
	   encodeString := xencode(x,StringFile(""),WriteString).s
	   ...
	end

	procedure WriteString(f,s[])
	  every f.s ||:= !s
	  f.s ||:= "\n"
	  return
	end

###########################################################################

  Notes on the encoding
  ---------------------

     Values are encoded as a sequence of one or more lines written to
  a plain text file.  The first or only line of a value begins with a
  single character that unambiguously indicates its type.  The
  remainder of the line, for some types, contains additional value
  information.  Then, for some types, additional lines follow
  consisting of additional object encodings that further specify the
  object.  The null value is a special case consisting of an empty
  line.

     Each object other than &null is assigned an integer tag as it is
  encoded.  The tag is not, however, written to the output file.  On
  input, tags are assigned in the same order as objects are decoded, so
  each restored object is associated with the same integer tag as it
  was when being written.  In encoding, any recurrence of an object is
  represented by the original object's tag.  Tag references are
  represented as integers, and are easily recognized since no object's
  representation begins with a digit.

     Where a structure contains elements, the encodings of the
  elements follow the structure's specification on following lines.
  Note that the form of the encoding contains the information needed to
  separate consecutive elements.

     Here are some examples of values and their encodings:

       x                     encode(x)
  -------------------------------------------------------

       1                     N1
       2.0                   N2.0
       &null                 
       "\377"                "\377"
       '\376\377'            '\376\377'
       procedure main        p
                             "main"
       co-expression #1 (0)  C
       []                    L
                             N0
       set()                 "S"
                             N0
       table("a")            T
                             N0
                             "a"
       ["hi","there"]        L
                             N2
                             "hi"
                             "there"

  A loop is illustrated by

       L2 := []
       put(L2,L2)

  for which

       x                     encode(x)
  -------------------------------------------------------

       L2                    L
                             N1
                             2

  The "2" on the third line is a tag referring to the list L2.  The tag
  ordering specifies that an object is tagged *after* its describing
  objects, thus the list L2 has the tag 2 (the integer 1 has tag 1).

     Of course, you don't have to know all this to use xencode and
  xdecode.

###########################################################################

  Links:  escape

###########################################################################

  See also:  codeobj.icn

###########################################################################
Procedures:
xdecode, xdecode_1, xdecoden, xdecodet, xencode, xencode_1, xencoden, xencodet

Records:
xcode_rec

Links:
escape.icn

This file is part of the (main) package.

Source code.

Details
Procedures:

xdecode(file, readProc)

: read structure from file


xdecode_1(data)


xdecoden(name)


xdecodet(file, typ)


xencode(x, file, writeProc)

: write structure to file


xencode_1(data, x)


xencoden(x, name, opt)


xencodet(x, file, typ)


Records:

xcode_rec(file, ioProc, done, nextTag)



This page produced by UniDoc on 2021/04/15 @ 23:59:54.