<commit_before>/*
 * Crystals (working title)
 *
 * Copyright (c) 2010, 2011
 *               <NAME>, <NAME>
 *               and <NAME>.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *
 *   * The names of contributors may not be used to endorse or promote
 *     products derived from this software without specific prior
 *     written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * AFOREMENTIONED COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file    src/field/mapload.c
 * @author  <NAME>
 * @brief   Map loader.
 */

#include "../crystals.h"


/* -- CONSTANTS -- */

static const uint16_t MAP_VERSION = 1;	 /**< Expected map version. */
static const long CHUNK_NOT_FOUND = -1;	/**< Sentinel chunk position. */

enum chunk_ids
{
  ID_FORM,
  ID_HEADER,
  ID_VERSION,
  ID_DIMENSIONS,
  ID_TAGS,
  ID_VALUES,
  ID_ZONES,
  ID_PROPERTIES,
  NUM_CHUNKS
};


/**
 * Length in bytes of each chunk ID.
 */
static const size_t ID_LENGTH = 4;


/**
 * Array of ChunkID identifiers.
 */
static const char CHUNK_IDS[NUM_CHUNKS][5] = {
  "FORM",			/* ID_FORM */
  "CMFT",			/* ID_HEADER */
  "VERS",			/* ID_VERSION */
  "DIMS",			/* ID_DIMENSIONS */
  "TAGS",			/* ID_TAGS */
  "VALS",			/* ID_VALUES */
  "ZONE",			/* ID_ZONES */
  "PROP",			/* ID_PROPERTIES */
};


/* -- STATIC DECLARATIONS -- */

/**
 * Parses the given file as a map file and attempts to return a map
 * created from its contents.
 *
 * @param file  The file to read from.
 *
 * @return  A pointer to a map created from the given map file, or
 *          NULL if there were errors during the parsing.
 */
static map_t *parse_map_file (FILE *file);


/**
 * Finds the locations of the chunks in the map file that the loader
 * is interested in.
 *
 * @param file  The file to read from.  This should be seeked to the
 *              start of the file.
 *
 * @return  An array of long integers, parallel to the CHUNK_IDS
 *          array, containing the positions of chunks.  A -1 in any
 *          index denotes an error in finding the chunk.
 */
static long *find_chunks (FILE *file);


/**
 * Initialises an array to hold the chunk position set.
 *
 * @return  an array suitable for holding the chunk positions, or
 *          NULL if allocation failed.
 */
static long *init_chunk_positions_array (void);


/**
 * Scans the main body of the file for chunk positions.
 *
 * @param file             The file to read from.  This should be
 *                         seeked to the start of the body (that is,
 *                         after the FORM header).
 * @param file_length      The length of the body of the file, in
 *                         bytes.  This is used for consistency
 *                         checking.
 * @param chunk_positions  The array to populate with the chunk
 *                         positions.
 */
static void scan_body_for_chunks (FILE *file, uint32_t file_length,
				  long *chunk_positions);


/**
 * Checks the required chunks to see if any are missing.
 *
 * @param chunk_positions  The array of chunk positions, as returned
 *                         by find_chunks.
 *
 * @return TRUE if one or more chunks is missing; FALSE otherwise.
 */
static bool chunks_missing (long *chunk_locations);


/**
 * Skips to the given chunk position in a file.
 *
 * @param file            The file to seek within.
 * @param chunk_position  The position within the file, in bytes from
 *                        the file start, of the chunk.
 */
static void skip_to_chunk (FILE *file, long chunk_position);


/**
 * Reads the version number chunk from the file.
 * @param file            The file to read from.
 * @param chunk_position  The position within the file, in bytes from
 *                        the file start, of the chunk.
 *
 * @return  the version number.
 */
static uint16_t read_map_version_chunk (FILE *file,
					long chunk_position);


/**
 * Reads the version number from the file.
 *
 * @param file  The file to read from.
 *
 * @return  the version number.
 */
static uint16_t read_map_version (FILE *file);

/**
 * Reads the map dimensions chunk from the file, initialising the map
 * using the results.
 *
 * @param file                 The file to read from.
 * @param chunk_position       The position within the file, in bytes
 *                             from the file start, of the chunk.
 * @param out_width            Pointer to a variable in which the
 *                             width of the map, in tiles, is to be
 *                             stored.
 * @param out_height           Pointer to a variable in which the
 *                             height of the map, in tiles, is to be
 *                             stored.
 * @param out_max_layer_index  Pointer to a variable in which the
 *                             maximum layer index is to be stored.
 * @param out_max_zone_index   Pointer to a variable in which the
 *                             maximum zone index is to be stored.
 */
static void read_map_dimensions_chunk (FILE *file,
				       long chunk_position,
				       dimension_t *out_width,
				       dimension_t *out_height,
				       layer_index_t<commit_msg>The Curious Case of the Missing Newline<commit_after>/*
 * Crystals (working title)
 *
 * Copyright (c) 2010, 2011
 *               <NAME>, <NAME>
 *               and <NAME>.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *
 *   * The names of contributors may not be used to endorse or promote
 *     products derived from this software without specific prior
 *     written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * AFOREMENTIONED COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file    src/field/mapload.c
 * @author  <NAME>
 * @brief   Map loader.
 */

#include "../crystals.h"


/* -- CONSTANTS -- */

static const uint16_t MAP_VERSION = 1;	 /**< Expected map version. */
static const long CHUNK_NOT_FOUND = -1;	/**< Sentinel chunk position. */

enum chunk_ids
{
  ID_FORM,
  ID_HEADER,
  ID_VERSION,
  ID_DIMENSIONS,
  ID_TAGS,
  ID_VALUES,
  ID_ZONES,
  ID_PROPERTIES,
  NUM_CHUNKS
};


/**
 * Length in bytes of each chunk ID.
 */
static const size_t ID_LENGTH = 4;


/**
 * Array of ChunkID identifiers.
 */
static const char CHUNK_IDS[NUM_CHUNKS][5] = {
  "FORM",			/* ID_FORM */
  "CMFT",			/* ID_HEADER */
  "VERS",			/* ID_VERSION */
  "DIMS",			/* ID_DIMENSIONS */
  "TAGS",			/* ID_TAGS */
  "VALS",			/* ID_VALUES */
  "ZONE",			/* ID_ZONES */
  "PROP",			/* ID_PROPERTIES */
};


/* -- STATIC DECLARATIONS -- */

/**
 * Parses the given file as a map file and attempts to return a map
 * created from its contents.
 *
 * @param file  The file to read from.
 *
 * @return  A pointer to a map created from the given map file, or
 *          NULL if there were errors during the parsing.
 */
static map_t *parse_map_file (FILE *file);


/**
 * Finds the locations of the chunks in the map file that the loader
 * is interested in.
 *
 * @param file  The file to read from.  This should be seeked to the
 *              start of the file.
 *
 * @return  An array of long integers, parallel to the CHUNK_IDS
 *          array, containing the positions of chunks.  A -1 in any
 *          index denotes an error in finding the chunk.
 */
static long *find_chunks (FILE *file);


/**
 * Initialises an array to hold the chunk position set.
 *
 * @return  an array suitable for holding the chunk positions, or
 *          NULL if allocation failed.
 */
static long *init_chunk_positions_array (void);


/**
 * Scans the main body of the file for chunk positions.
 *
 * @param file             The file to read from.  This should be
 *                         seeked to the start of the body (that is,
 *                         after the FORM header).
 * @param file_length      The length of the body of the file, in
 *                         bytes.  This is used for consistency
 *                         checking.
 * @param chunk_positions  The array to populate with the chunk
 *                         positions.
 */
static void scan_body_for_chunks (FILE *file, uint32_t file_length,
				  long *chunk_positions);


/**
 * Checks the required chunks to see if any are missing.
 *
 * @param chunk_positions  The array of chunk positions, as returned
 *                         by find_chunks.
 *
 * @return TRUE if one or more chunks is missing; FALSE otherwise.
 */
static bool chunks_missing (long *chunk_locations);


/**
 * Skips to the given chunk position in a file.
 *
 * @param file            The file to seek within.
 * @param chunk_position  The position within the file, in bytes from
 *                        the file start, of the chunk.
 */
static void skip_to_chunk (FILE *file, long chunk_position);


/**
 * Reads the version number chunk from the file.
 * @param file            The file to read from.
 * @param chunk_position  The position within the file, in bytes from
 *                        the file start, of the chunk.
 *
 * @return  the version number.
 */
static uint16_t read_map_version_chunk (FILE *file,
					long chunk_position);


/**
 * Reads the version number from the file.
 *
 * @param file  The file to read from.
 *
 * @return  the version number.
 */
static uint16_t read_map_version (FILE *file);


/**
 * Reads the map dimensions chunk from the file, initialising the map
 * using the results.
 *
 * @param file                 The file to read from.
 * @param chunk_position       The position within the file, in bytes
 *                             from the file start, of the chunk.
 * @param out_width            Pointer to a variable in which the
 *                             width of the map, in tiles, is to be
 *                             stored.
 * @param out_height           Pointer to a variable in which the
 *                             height of the map, in tiles, is to be
 *                             stored.
 * @param out_max_layer_index  Pointer to a variable in which the
 *                             maximum layer index is to be stored.
 * @param out_max_zone_index   Pointer to a variable in which the
 *                             maximum zone index is to be stored.
 */
static void read_map_dimensions_chunk (FILE *file,
				       long chunk_position,
				       dimension_t *out_width,
				       dimension_t *out_height,
				       layer_index_t
{'fraction_non_alphanumeric': 0.07639707616128272, 'fraction_numerical': 0.0033011082291912286, 'mean_word_length': 2.3204592901878915, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2801685', 'n_tokens_mistral': 3701, 'n_tokens_neox': 3446, 'n_words': 1541}