mirror of
https://github.com/lhearachel/narc.git
synced 2025-06-18 13:35:32 -04:00
feat: Implement narc_strerror, narc_load
This commit is contained in:
parent
318a3249b8
commit
ee38b71c3b
@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
BasedOnStyle: LLVM
|
BasedOnStyle: LLVM
|
||||||
Language: Cpp
|
Language: Cpp
|
||||||
|
AlignConsecutiveMacros: Consecutive
|
||||||
AlignOperands: false
|
AlignOperands: false
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
AfterCaseLabel: false
|
AfterCaseLabel: false
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -13,3 +13,6 @@ compile_commands.json
|
|||||||
|
|
||||||
# Valgrind output
|
# Valgrind output
|
||||||
valgrind.log
|
valgrind.log
|
||||||
|
|
||||||
|
# Testing files
|
||||||
|
*.narc
|
||||||
|
71
include/narc.h
Normal file
71
include/narc.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 <lhearachel@proton.me>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef NARC_H
|
||||||
|
#define NARC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum narc_error {
|
||||||
|
NARCERR_NONE = 0,
|
||||||
|
|
||||||
|
NARCERR_MAGIC,
|
||||||
|
NARCERR_BOM,
|
||||||
|
NARCERR_VERSION,
|
||||||
|
NARCERR_HEADER_SIZE,
|
||||||
|
NARCERR_NUM_SECTIONS,
|
||||||
|
|
||||||
|
NARCERR_ERRNO = 0xFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct narc {
|
||||||
|
uint32_t magic;
|
||||||
|
uint16_t bom;
|
||||||
|
uint16_t version;
|
||||||
|
uint32_t size;
|
||||||
|
uint16_t header_size;
|
||||||
|
uint16_t num_sections;
|
||||||
|
unsigned char data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a `narc_error` value into a corresponding human-readable message.
|
||||||
|
*/
|
||||||
|
const char *narc_strerror(enum narc_error error);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load a NARC from an existing file at the given path. If the file contents
|
||||||
|
* validate as a NARC, then `out_narc` will be set to an address with sufficient
|
||||||
|
* memory allocation to hold the entire file. The calling client is responsible
|
||||||
|
* for freeing this allocation.
|
||||||
|
*
|
||||||
|
* Any of the following error codes may be emitted:
|
||||||
|
*
|
||||||
|
* - `NARCERR_NONE` - No error; `narc` contains good data.
|
||||||
|
* - `NARCERR_MAGIC` - The magic ID in the file's header did not match
|
||||||
|
* expectations.
|
||||||
|
* - `NARCERR_BOM` - The byte-order marker in the file's header did
|
||||||
|
* not match expectations.
|
||||||
|
* - `NARCERR_VERSION` - The version marker in the file's header did not
|
||||||
|
* match expectations.
|
||||||
|
* - `NARCERR_HEADER_SIZE` - The file's header reports an invalid size for
|
||||||
|
* itself.
|
||||||
|
* - `NARCERR_NUM_SECTIONS` - The number of sections expected by the file's
|
||||||
|
* header did not match expectations.
|
||||||
|
* - `NARCERR_ERRNO` - A system-level error occurred; consult `errno`.
|
||||||
|
*/
|
||||||
|
enum narc_error narc_load(const char *file_path, struct narc **out_narc);
|
||||||
|
|
||||||
|
#endif // NARC_H
|
50
src/cli.c
Normal file
50
src/cli.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 <lhearachel@proton.me>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "narc.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
struct narc *narc = NULL;
|
||||||
|
enum narc_error err = narc_load("test.narc", &narc);
|
||||||
|
if (err == NARCERR_ERRNO) {
|
||||||
|
fprintf(stderr, "System error: %s\n", strerror(errno));
|
||||||
|
fflush(stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
} else if (err != NARCERR_NONE) {
|
||||||
|
fprintf(stderr, "NARC error: %s\n", narc_strerror(err));
|
||||||
|
fflush(stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Loaded NARC successfully!\n");
|
||||||
|
printf("NARC size: %d\n", narc->size);
|
||||||
|
printf("NARC data sample:");
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
printf(" %02x", narc->data[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
free(narc);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
54
src/narc_load.c
Normal file
54
src/narc_load.c
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "narc.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define NARC_MAGIC 0x4352414E
|
||||||
|
#define LE_BOM 0xFFFE
|
||||||
|
#define VERSION_MARKER 0x0100
|
||||||
|
#define HEADER_SIZE 16
|
||||||
|
#define NUM_SECTIONS 3
|
||||||
|
|
||||||
|
#define ERROR_NEQ(expect, actual, err, file) \
|
||||||
|
{ \
|
||||||
|
if ((expect) != (actual)) { \
|
||||||
|
fclose(file); \
|
||||||
|
return err; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
enum narc_error narc_load(const char *file_path, struct narc **out_narc)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(file_path, "rb");
|
||||||
|
if (f == NULL) {
|
||||||
|
return NARCERR_ERRNO;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
size_t fsize = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
// Validate the header.
|
||||||
|
struct narc header;
|
||||||
|
fread(&header, sizeof(char), HEADER_SIZE, f);
|
||||||
|
|
||||||
|
ERROR_NEQ(NARC_MAGIC, header.magic, NARCERR_MAGIC, f);
|
||||||
|
ERROR_NEQ(LE_BOM, header.bom, NARCERR_BOM, f);
|
||||||
|
ERROR_NEQ(VERSION_MARKER, header.version, NARCERR_VERSION, f);
|
||||||
|
ERROR_NEQ(HEADER_SIZE, header.header_size, NARCERR_HEADER_SIZE, f);
|
||||||
|
ERROR_NEQ(NUM_SECTIONS, header.num_sections, NARCERR_NUM_SECTIONS, f);
|
||||||
|
|
||||||
|
// Header is good; allocate enough memory to hold the whole file.
|
||||||
|
*out_narc = malloc(fsize);
|
||||||
|
if (*out_narc == NULL) {
|
||||||
|
fclose(f);
|
||||||
|
return NARCERR_ERRNO;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(*out_narc, &header, sizeof(header));
|
||||||
|
fread((*out_narc)->data, sizeof(char), fsize - sizeof(header), f);
|
||||||
|
fclose(f);
|
||||||
|
return NARCERR_NONE;
|
||||||
|
}
|
22
src/narc_strerror.c
Normal file
22
src/narc_strerror.c
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "narc.h"
|
||||||
|
|
||||||
|
const char *narc_strerror(enum narc_error error)
|
||||||
|
{
|
||||||
|
switch (error) {
|
||||||
|
default:
|
||||||
|
case NARCERR_NONE:
|
||||||
|
return "(null)";
|
||||||
|
case NARCERR_MAGIC:
|
||||||
|
return "Invalid magic marker in NARC header";
|
||||||
|
case NARCERR_BOM:
|
||||||
|
return "Invalid byte-order marker in NARC header";
|
||||||
|
case NARCERR_VERSION:
|
||||||
|
return "Invalid version marker in NARC header";
|
||||||
|
case NARCERR_HEADER_SIZE:
|
||||||
|
return "Invalid NARC header size";
|
||||||
|
case NARCERR_NUM_SECTIONS:
|
||||||
|
return "Invalid section count in NARC header";
|
||||||
|
case NARCERR_ERRNO:
|
||||||
|
return "Standard error; refer to errno for details";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user