View Single Post
Re: inserting stuff into a file
Old
  (#3)
Pierre-Marie Baty
Roi de France
 
Pierre-Marie Baty's Avatar
 
Status: Offline
Posts: 5,049
Join Date: Nov 2003
Location: 46°43'60N 0°43'0W 0.187A
Default Re: inserting stuff into a file - 31-03-2004

I would rather advise NOT to do this in a temporary file. I'm doing something similar in my bot code ; no matter how you will do it, there's no "insert" function in the standard C libs. You have to read what's BEFORE and AFTER the part you want to change in your file, and then reassemble it together.
Code:
void BotNavSaveBrain (player_t *pPlayer)
{
   // this function saves the navigation nodes in the bot's memory in a file to disk. The
   // authentication being made by comparison of the recorded number of walkfaces, this data
   // is written in the file at the very end of the function, to ensure an error in the save
   // process won't let a badly authenticated file on disk.
   MFILE *mfp;
   FILE *fp;
   bot_brain_t *brain;
   char nav_filename[256];
   char section_name_length;
   navnode_t *node;
   int face_index, link_index, array_index;
   char *section_before = NULL, *section_after = NULL;
   int section_before_size, section_after_start, section_after_size;
   brain = &pPlayer->Bot.BotBrain; // quick access to bot brain
   // build the file name
   sprintf (nav_filename, "racc/knowledge/%s/%s.nav", server.mod_name, NormalizeChars (pPlayer->connection_name));
   // get the section name
   section_name_length = strlen (server.map_name) + 1;
   // open the brain for updating (let's read what's before first)
   mfp = mfopen (nav_filename, "rb");
   if (mfp == NULL)
	  TerminateOnError ("BotNavLoadBrain(): Unable to operate on %s's nav brain !\n", pPlayer->connection_name);
   // locate at start of the section to update
   if (mfseekAtSection (mfp, server.map_name) != 0)
	  TerminateOnError ("BotNavSaveBrain(): Unable to locate before section to update in %s's nav brain !\n", pPlayer->connection_name);
   section_before_size = mftell (mfp); // get the size of what's before the section to update
   if (section_before_size == 0)
	  TerminateOnError ("BotNavSaveBrain(): Unable to read before section to update in %s's nav brain !\n", pPlayer->connection_name);
   section_before = (char *) malloc (section_before_size + 1); // allocate memory for what's before
   if (section_before == NULL)
	  TerminateOnError ("BotNavSaveBrain(): malloc() failure for reading before section to update in %s's nav brain !\n", pPlayer->connection_name);
   mfseek (mfp, 0, SEEK_SET); // rewind at start of file
   mfread (section_before, section_before_size, 1, mfp); // and read what's before section to update
   // now locate after the section to update
   if (mfseekAfterSection (mfp, server.map_name) != 0)
   {
	  if (section_before != NULL)
		 free (section_before); // free the memory we mallocated() for what's before section to update
	  TerminateOnError ("BotNavSaveBrain(): Unable to locate after section to update in %s's nav brain !\n", pPlayer->connection_name);
   }
   section_after_start = mftell (mfp); // get the start of what's after the section to update
   mfseek (mfp, 0, SEEK_END);
   section_after_size = mftell (mfp) - section_after_start; // get the size of it
   if (section_after_size > 0)
   {
	  section_after = (char *) malloc (section_after_size + 1); // allocate memory for what's after
	  if (section_after == NULL)
	  {
		 if (section_before != NULL)
			free (section_before); // free the memory we mallocated() for what's before section to update
		 TerminateOnError ("BotNavSaveBrain(): malloc() failure for reading after section to update in %s's nav brain !\n", pPlayer->connection_name);
	  }
	  mfseek (mfp, section_after_start, SEEK_SET); // rewind at where what's after starts
	  mfread (section_after, section_after_size, 1, mfp); // and read what's after section to update
   }
   mfclose (mfp); // everything we wanted to know from the previous brain is read, close the file
   // and finally update the brain
   fp = fopen (nav_filename, "wb");
   if (fp == NULL)
   {
	  if (section_before != NULL)
		 free (section_before); // free the memory we mallocated() for what's before section to update
	  if (section_after != NULL)
		 free (section_after); // free the memory we mallocated() for what's before section to update
	  TerminateOnError ("BotNavSaveBrain(): Unable to operate on %s's nav brain !\n", pPlayer->connection_name);
   }
   fwrite (section_before, section_before_size, 1, fp); // write what's before
   fwrite ("[section]", sizeof ("[section]"), 1, fp); // section tag
   fwrite (server.map_name, section_name_length, 1, fp); // section name
   fwrite ("\0\0\0\0", sizeof (long), 1, fp); // fill the field with zeroes (temporarily)
   // for each navigation node...
   for (face_index = 0; face_index < map.walkfaces_count; face_index++)
   {
	  node = &brain->PathMemory[face_index]; // quick access to node
	  // write the number of links this node has
	  fwrite (&node->links_count, sizeof (char), 1, fp);
	  // for each link of this node...
	  for (link_index = 0; link_index < node->links_count; link_index++)
	  {
		 // translate the pointer address into an array relative index
		 array_index = ((unsigned long) node->links[link_index].node_from - (unsigned long) brain->PathMemory) / sizeof (navnode_t);
		 if ((array_index < 0) || (array_index >= map.walkfaces_count))
			TerminateOnError ("BotNavSaveBrain(): bad node array index %d (max %d), index %d/%d\n", array_index, map.walkfaces_count - 1, link_index, node->links_count);
		 fwrite (&array_index, sizeof (long), 1, fp); // write the walkface index of the link
		 // write the reachability type for this link (normal, ladder, elevator...)
		 fwrite (&node->links[link_index].reachability, sizeof (short), 1, fp);
		 // read the vector origin for this link
		 fwrite (&node->links[link_index].v_origin, sizeof (Vector), 1, fp);
	  }
   }
   if (section_after_size > 0)
	  fwrite (section_after, section_after_size, 1, fp); // and write what's after, if needed
   // now that the map specific data sections have been dumped, we can write the likelevels
   fseek (fp, 0, SEEK_SET); // rewind at start of file
   fseek (fp, sizeof ("RACCNAV"), SEEK_CUR); // skip the "RACCNAV" tag
   fseek (fp, sizeof ("[likelevels]"), SEEK_CUR); // skip the "[likelevels]" tag
   fwrite (&brain->likelevel_ladder, sizeof (long), 1, fp); // write ladder likelevel
   fwrite (&brain->likelevel_falledge, sizeof (long), 1, fp); // write falledge likelevel
   fwrite (&brain->likelevel_elevator, sizeof (long), 1, fp); // write elevator likelevel
   fwrite (&brain->likelevel_platform, sizeof (long), 1, fp); // write platform likelevel
   fwrite (&brain->likelevel_conveyor, sizeof (long), 1, fp); // write conveyor likelevel
   fwrite (&brain->likelevel_train, sizeof (long), 1, fp); // write train likelevel
   fwrite (&brain->likelevel_longjump, sizeof (long), 1, fp); // write train likelevel
   fwrite (&brain->likelevel_swim, sizeof (long), 1, fp); // write the swim likelevel
   fwrite (&brain->likelevel_teleporter, sizeof (long), 1, fp); // write the teleporter likelevel
   // now we're ready to write the authentication tag
   fseek (fp, section_before_size, SEEK_SET); // seek back at start of section
   fseek (fp, sizeof ("[section]"), SEEK_CUR); // skip the [section] tag
   fseek (fp, section_name_length, SEEK_CUR); // skip the section name
   fwrite (&map.walkfaces_count, sizeof (long), 1, fp); // write the # of walkfaces on map
   fclose (fp); // everything is saved, close the file
   if (section_before != NULL)
	  free (section_before); // free the memory we mallocated() for what's before section to update
   if (section_after != NULL)
	  free (section_after); // free the memory we mallocated() for what's before section to update
   return; // and return
}
I could have formatted all this better somehow, but as usuals I'm lazy.



RACC home - Bots-United: beer, babies & bots (especially the latter)
"Learn to think by yourself, else others will do it for you."
  
Reply With Quote