import string

def textopen(pathOrFile, mode='r'):  
  if mode == 'r':
    return _TextFileLinefeedAdaptor(pathOrFile)
  elif mode == 'r+':
    try:
      exception = NotImplementedError
    except:
      exception = Exception
    raise exception, "'r+' mode is not implemented"
  else:
    return open(pathOrFile)

class _TextFileLinefeedAdaptor:
  BLOCK_SIZE = 512

  def __init__(self, pathOrFile):
    import types
    file = pathOrFile
    if isinstance(file, types.StringType):
      file = open(file, "rb")
    self.file = file
    self.buffer = None
  
  def __getattr__(self, name):
    if name in ('closed', 'mode', 'name', 'softspace'):
      return getattr(self.file, name)
    else:
      raise AttributeError, name
  
  def close(self):
    self.file.close()
  
  def readline(self):
    buffer = self.buffer
    if not buffer:
      buffer = self.file.read(self.BLOCK_SIZE)
      if not buffer:
        return ''

    crpos = string.find(buffer, '\r')
    lfpos = string.find(buffer, '\n')
    
    if max(crpos, lfpos) < 0:
      self.buffer = None
      return buffer + self.readline()
    if lfpos < 0 or 0 <= crpos < lfpos:
      line = buffer[:crpos] + '\n'
      otherchar = '\n'
      nextpos = crpos + 1
    else:
      line = buffer[:lfpos + 1]
      otherchar = '\r'
      nextpos = lfpos + 1
    if nextpos == len(buffer):
      buffer = self.file.read(self.BLOCK_SIZE)
      nextpos = 0
      
    if buffer and buffer[nextpos] == otherchar:
      nextpos = nextpos + 1
    self.buffer = buffer[nextpos:]
    return line
  
  def readlines(self):
    lines = []
    while 1:
      line = self.readline()
      if line == '':
        break
      lines.append(line)
    return lines
  
  def read(self, length=None):
    self.seek(self.tell())
    if length:
      return self.file.read(length)
    else:
      self.file.read()
  
  def rewind(self):
    self.seek(0)
  
  def seek(self, position):
    self.file.seek(position)
    self.buffer = None
  
  def tell(self):
    return self.file.tell() - len(self.buffer or "")

def _test():
  _testlength(1)
  for index in range(-2, 3):
    _testlength(_TextFileLinefeedAdaptor.BLOCK_SIZE + index)

def _testlength(length):
  import tempfile
  import string
  lines = []
  for line in '1', '2', '3':
    lines.append(line * length)
  separators = {'UNIX': '\n', 'MacOS': '\r', 'DOS': '\n\r'}
  for separator in separators.keys():
    filename = tempfile.mktemp()
    try:
      file = open(filename, 'wb')
      # leave the separator off the last line, to test that case too
      file.write(string.join(lines, separators[separator]))
      file.close()
      file = textopen(filename, 'r')
      for index in range(len(lines)):
        expected = lines[index]
        if index != len(lines) - 1:
          expected = expected + '\n'
        actual = file.readline()
        if expected != actual:
          print 'Platform %s:\n  expected: %s\n  read: %s' % (separator, `expected`, `actual`)
    finally:
      try:
        file.close()
      except:
        pass
      import os
      os.remove(filename)