0

I am trying to replicate the C stdio library using Unix system calls. To start, I am trying to mimic/recreate fopen using only the open UNIX system call.

I have a File class where I want the constructor to open a file that I pass to the constructor in a mode that I also pass in. I want to create a pointer to the first byte in the file that I have opened using open, but am unsure of how to do this. In the file class, I have a private member char* curPtr, which I would like to use to represent the current location of where I am in a file (when reading or writing, which I will use further down the line).

I do not know how to "link" the file descriptor that is returned from open with the curPtr data member. I currently have some code implemented below which is basically type casting the file descriptor, which is an int, to a char* (Like this: curPtr = (char*)fileDescriptor;), but I dont know if this is correct. I want to use curPtr* to index through the file byte by byte I have opened and be able to print out or write individual characters at the location to pointed at by curPtr*.

File Class:

class File {
public:
  class File_Exception: public std::exception {
  };
  static const int bufsiz = 8192;
  static const int eof = -1;

  File(const char *name, const char *mode = "r");

  // Close the file.  Make sure any buffered data is written to disk,
  // and free the buffer if there is one.
  ~File();

  int fgetc();
  int fputc(int c);

private:
  const char* fileName;         //stores the pointer to our file.
  int fileMode;           //stores our file mode.
  char* fileBuffer;       //Buffer

  char* curPtr;       //I want to use this pointer to point to the current location we are in a file.

  int fileDescriptor;   //The file descriptor for this particular file object.

  bool canWeRead = false;     //flag to indicate if we have read access
  bool canWeWrite = false;    //flag to indicate if we have write access

  int errorState = 0;     //0 indicates we have no errors. 1 indicates error

};

File Class Constructor

File::File(const char *name, const char *mode) {
  int fileMode = 0;    //Initializing mode to 0

  fileName = name;    //Setting the file name of this File object to the name we pass in.

  switch(*mode){
    case 'r':
      fileMode = O_RDONLY | O_CREAT;
      canWeRead = true;
      canWeWrite = false;
      break;
    case 'r+':            
      fileMode = O_RDWR | O_CREAT;
      canWeRead = true;
      canWeWrite = true;
      break;
    case 'w':
      fileMode = O_WRONLY | O_CREAT;
      canWeRead = false;
      canWeWrite = true;
      break;
    case 'w+':           
      fileMode = O_RDWR | O_CREAT | O_TRUNC;
      canWeRead = true;
      canWeWrite = true;
      break;
    
    default:    //We should never reach the default case, so I assert(0)
      assert(0);
  }

  fileDescriptor = open(name, fileMode);
  assert(fileDescriptor >= 0);    //If we dont get a positive nonnegative int, we have a problem.

  //How do I set the value of curPtr to the first char in my File object?
   curPtr = (char*)fileDescriptor; //I think that this works?
}
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • C doesn't have classes or constructors or destructors or exceptions, perhaps there is some other language with the letter C in its name you want to use? – n. m. could be an AI May 13 '21 at 18:53
  • Sorry, I meant that I am implementing this in C++ – Aviv Weinstein May 13 '21 at 18:54
  • 1
    `curPtr = (char*)fileDescriptor;` is totally wrong. You want to maintain a character buffer in your File class and set `curPtr` to point to that bugger. You seem to have `char* fileBuffer`, are you sure you understand its purpose? On an unrelated note, `'r+'` doesn't do what you think it does. [Crank up the warning level](https://stackoverflow.com/questions/57842756/why-should-i-always-enable-compiler-warnings) in your compiler. – n. m. could be an AI May 13 '21 at 19:02
  • Ok! I think you are correct in that I dont/didnt fully understand the purpose of the ```char* fileBuffer```. Based on your comment, I now think that I should be indexing ```curPtr``` through my ```fileBuffer```. This would relate to my ```fgetc``` and ```fputc```. Each time I would call either of those two functions, I would be indexing through the ```fileBuffer``` (forward or back). Does that sound like I have a better handle on this? – Aviv Weinstein May 13 '21 at 19:19
  • You are mixing up concepts from `mmap()` and POSIX files (those you open with `open` or `creat` and then read using `read` and write using `write`). You can't have an pointer that allows you to address a file byte by byte unless you `mmap()` it to some memory area. You have to use `read()` to read your file in chunks, using a memory buffer. C `stdio` is also AFAIK supposed to be buffered, so remember to also implement that. – mcilloni May 13 '21 at 19:24
  • Ok, I see! I am supposed to fill my ```fileBuffer``` using ```read```. Thank you so much @mcilloni, I completely zoned out on being able to use ```read```. Then once my ```fileBuffer``` has been filled, I can index through that. Do I have that correct? For this assignment, I am not able to use ```stdio``` functions – Aviv Weinstein May 13 '21 at 20:05

0 Answers0