home *** CD-ROM | disk | FTP | other *** search
- /*
- Listing 9.16 and 9.17: Writes an array to a disk file.
- Author: Craig Yellick
- Excerpted from "Clipper 5: A Developer's Guide"
- Copyright (c) 1991 M&T Books
- 501 Galveston Drive
- Redwood City, CA 94063-4728
- (415) 366-3600
- */
-
- function SaveArray(a_, fileName)
- /*
- General-purpose function for saving an array to a disk file.
- This is only the public interface. The real work is done by
- recursive calls to the ElementOut() function.
-
- Pass an array (or a reference to an array) and the name of the
- file to store the array.
-
- SaveArray({1,2,3,4}, "NUMS.ARY")
-
- This function returns .t. if successful, .f. if not.
- */
-
- local cnt := len(a_)
- local success := .f.
- local handle := fcreate(fileName)
-
- if handle != -1
- success := ElementOut(handle, a_)
- fclose(handle)
- endif
-
- return success
-
-
- static function ElementOut(handle, a_)
- /*
- Given a file handle and an array, write the contents of the
- array to the file in the following form.
-
- LL T WW E... T WW E...
-
- Where LL is a two byte integer representing the number of
- elements in the array, T is a character representing the data
- type of the first element, WW is a two byte integer
- representing the width of the element; followed by repetitions
- of that basic pattern.
-
- Nested arrays are handled by calling ElementOut() when ever an
- array is encountered within the elements in the array
- currently being processed. (Know as recursion.) The LL length
- bytes are written following an "A" data type and the process
- gets repeated. Isn't recursion wonderful?
-
- This is a static function and therefore not visible to any
- functions outside of the source code file containing it. All
- calls from the outside must be made to SaveArray().
-
- */
-
- local success := .t.
- local i, buffer
- local cnt := len(a_)
-
- // Write the overall array size.
- fwrite(handle, i2bin(cnt))
-
- // Process each element in the array.
- for i = 1 to cnt
-
- /*
- Special handling for the nil and code block data types.
- Both will be labeled type "Z" and for consistency wit the
- other data types, will have a width of one and an element
- value of "Z". However, a nil will be placed in the array
- when it comes time to load it from the file.
- */
- if (a_[i] = nil) .or. (valtype(a_[i]) = "B")
- buffer := "Z" +i2bin(1) +"Z"
-
- else
- /*
- Each element is encoded as follows.
- Data type: C,D,L,N.
- Width: Number of characters needed.
- Element Value: String version of the value.
- */
-
- buffer := valtype(a_[i])
- do case
- case buffer = "C"
- buffer += i2bin(len(a_[i])) // Width of the string
- buffer += a_[i]
-
- case buffer = "D"
- buffer += i2bin(8) // Dates are 8 wide
- buffer += dtoc(a_[i])
-
- case buffer = "L"
- buffer += i2bin(1) // Logicals are 1 wide
- buffer += if(a_[i], "T", "F")
-
- case buffer = "N"
- // Convert number to string, trim spaces, and
- // calculated width of number based on the string.
- buffer += i2bin(len(ltrim(str(a_[i]))))
- buffer += ltrim(str(a_[i]))
-
- otherwise
- // Type "A" for arrays will be handled
- // after we write the type.
- endcase
- endif
-
- // Write the buffer, constructed above, to the file.
- if fwrite(handle, buffer, len(buffer)) != len(buffer)
- success := .f.
- exit
- endif
-
- /*
- If this is a nested array, it's recursion time!
-
- Call ElementOut() again, it will append a series
- of types/widths/values to the current file.
- */
- if left(buffer, 1) == "A"
- ElementOut(handle, a_[i])
- endif
- next i
-
- return success
-
- // end of file CHP0916.PRG
-