view modules/file.tp @ 347:ff7ea11b4b60

Add length method to executable bytearrays
author Michael Pavone <pavone@retrodev.com>
date Fri, 10 Apr 2015 00:48:12 -0700
parents dcb495cf2b97
children
line wrap: on
line source
{
	_getStdin <- {
		_stdin <- (file fromFD: 0)
		_getStdin <- { _stdin }
		_stdin
	}
	_getStdout <- {
		_stdout <- (file fromFD: 1)
		_getStdout <- { _stdout }
		_stdout
	}
	_getStderr <- {
		_stderr <- (file fromFD: 2)
		_getStderr <- { _stderr }
		_stderr
	}
	#{
		fromFD <- :_fd {
			_buffers <- #[]
			_readPos <- 0
			_buffered <- 0
			_bufferChunk <- 4096
			_eof? <- false
			_addBuffer <- {
				newbuf <- bytearray normal: _bufferChunk
				justRead <- os readFrom: _fd to: newbuf
				if: justRead > 0 {
					_buffered <- _buffered + justRead
					_buffers append: (newbuf shrinkTo: justRead)
				} else: {
					_eof? <- true
				}
			}
			_lineIter <- :f {
				iter <- #{
					foreach <- :self fun {
						idx <- 0
						while: { not: (f eof?) } do: {
							line <- f nextLine
							fun: idx line
							idx <- idx + 1
						}
						self
					}

					map <- :fun {
						new <- #[]
						foreach: :idx el {
							new append: (fun: el)
						}
						new
					}

					filter <- :fun {
						new <- #[]
						foreach: :idx el {
							if: (fun: el) {
								new append: el
							}
						}
						new
					}

					fold:with <- :acc :fun {
						foreach: :idx el {
							acc <- fun: acc el
						}
						acc
					}

					foldr:with <- :acc :fun {
						(map: :el { el }) foldr: acc with: fun
					}
				}
				_lineIter <- { iter }
				iter
			}
			#{
				fd <- { _fd }
				read <- :bytes {
					while: { bytes > _buffered && (not: _eof?)} do: {
						_addBuffer:
					}
					nextBuffers <- #[]
					pieces <- #[]
					toRead <- bytes
					i <- 0
					while: { toRead > 0 && i < (_buffers length) } do: {
						curBuf <- _buffers get: i
						if: toRead >= (curBuf length) - _readPos {
							pieces append: (curBuf stringFrom: _readPos to: (curBuf length))
							_buffered <- _buffered - ((curBuf length) - _readPos)
							toRead <- toRead - ((curBuf length) - _readPos)
							_readPos <- 0
						} else: {
							nextPos <- _readPos + toRead
							pieces append: (curBuf stringFrom: _readPos to: nextPos)
							_readPos <- nextPos
							_buffered <- _buffered - toRead
							toRead <- 0
							nextBuffers append: curBuf
						}
						i <- i + 1
					}

					while: {i < (_buffers length)} do: {
						nextBuffers append: (_buffers get: i)
						i <- i + 1
					}
					_buffers <- nextBuffers
					pieces join: ""
				}
				readAll <- {
					while: { not: _eof? } do: {
						_addBuffer:
					}
					read: _buffered
				}
				write <- :data {
					//TODO: write buffering for small writes
					os write: _fd data
				}
				nextLine <- {
					nl <- "\n" byte: 0
					notfound <- true
					pos <- 0
					i <- 0
					while: { notfound } do: {
						while: { notfound && i < (_buffers length) } do: {
							curBuf <- _buffers get: i
							start <- if: i = 0 { _readPos } else: { 0 }
							curBuf findChar: nl from: start :idx {
								notfound <- false
								pos <- pos + idx + 1
							} else: {
								pos <- pos + (curBuf length)
							}

							i <- i + 1
						}

						if: notfound && (not: _eof?) {
							_addBuffer:
						} else: {
							notfound <- false
						}
					}
					read: pos - _readPos
				}
				lines <- {
					_lineIter: self
				}
				close <- {
					os close: _fd
				}
				eof? <- { _eof? && _buffered <= 0 }
			}
		}

		open <- :filename {
			fromFD: (os open: filename (os O_RDONLY))
		}

		openWrite <- :filename {
			fromFD: (os open: filename ((os O_WRONLY) or (os O_CREAT) or (os O_TRUNC)) 0x1B6)
		}

		openAppend <- :filename {
			fromFD: (os open: filename ((os O_RDWR) or (os O_CREAT) or (os O_APPEND)) 0x1B6)
		}

		stdin <- { _getStdin: }
		stdout <- { _getStdout: }
		stderr <- { _getStderr: }
	}
}