init
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
a.out
|
||||||
|
a.out.old
|
||||||
|
/build
|
||||||
69
nob.c
Normal file
69
nob.c
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
// This is your build script. You only need to "bootstrap" it once with `cc -o nob nob.c`
|
||||||
|
// (you can call the executable whatever actually) or `cl nob.c` on MSVC. After that every
|
||||||
|
// time you run the `nob` executable if it detects that you modifed nob.c it will rebuild
|
||||||
|
// itself automatically thanks to NOB_GO_REBUILD_URSELF (see below)
|
||||||
|
|
||||||
|
// nob.h is an stb-style library https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
|
||||||
|
// What that means is that it's a single file that acts both like .c and .h files, but by default
|
||||||
|
// when you include it, it acts only as .h. To make it include implementations of the functions
|
||||||
|
// you must define NOB_IMPLEMENTATION macro. This is done to give you full control over where
|
||||||
|
// the implementations go.
|
||||||
|
#define NOB_IMPLEMENTATION
|
||||||
|
|
||||||
|
// Always keep a copy of nob.h in your repo. One of my main pet peeves with build systems like CMake
|
||||||
|
// and Autotools is that the codebases that use them naturally rot. That is if you do not actively update
|
||||||
|
// your build scripts, they may not work with the latest version of the build tools. Here we basically
|
||||||
|
// include the entirety of the source code of the tool along with the code base. It will never get
|
||||||
|
// outdated (unless you got no standard compliant C compiler lying around, but at that point why are
|
||||||
|
// you trying to build a C project?)
|
||||||
|
//
|
||||||
|
// (In these examples we actually symlinking nob.h, but this is to keep nob.h-s synced among all the
|
||||||
|
// examples)
|
||||||
|
#include "nob.h"
|
||||||
|
|
||||||
|
// Some folder paths that we use throughout the build process.
|
||||||
|
#define BUILD_FOLDER "build/"
|
||||||
|
#define SRC_FOLDER "src/"
|
||||||
|
|
||||||
|
#define CC "gcc"
|
||||||
|
|
||||||
|
#define SRCS \
|
||||||
|
SRC_FOLDER "main.c", \
|
||||||
|
SRC_FOLDER "stack.c", \
|
||||||
|
|
||||||
|
#define C_ARGS \
|
||||||
|
// "-Wall", \
|
||||||
|
// "-Wextra"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// This line enables the self-rebuilding. It detects when nob.c is updated and auto rebuilds it then
|
||||||
|
// runs it again.
|
||||||
|
NOB_GO_REBUILD_URSELF(argc, argv);
|
||||||
|
|
||||||
|
// It's better to keep all the building artifacts in a separate build folder. Let's create it if it
|
||||||
|
// does not exist yet.
|
||||||
|
//
|
||||||
|
// Majority of the nob command return bool which indicates whether operation has failed or not (true -
|
||||||
|
// success, false - failure). If the operation returned false you don't need to log anything, the
|
||||||
|
// convention is usually that the function logs what happened to itself. Just do
|
||||||
|
// `if (!nob_function()) return;`
|
||||||
|
if (!nob_mkdir_if_not_exists(BUILD_FOLDER)) return 1;
|
||||||
|
|
||||||
|
// The working horse of nob is the Nob_Cmd structure. It's a Dynamic Array of strings which represent
|
||||||
|
// command line that you want to execute.
|
||||||
|
Nob_Cmd cmd = {0};
|
||||||
|
|
||||||
|
// nob.h ships with a bunch of nob_cc_* macros that try abstract away the specific compiler.
|
||||||
|
// They are verify basic and not particularly flexible, but you can redefine them if you need to
|
||||||
|
// or not use them at all and create your own abstraction on top of Nob_Cmd.
|
||||||
|
|
||||||
|
nob_cmd_append(&cmd, CC);
|
||||||
|
nob_cmd_append(&cmd, C_ARGS);
|
||||||
|
nob_cc_output(&cmd, BUILD_FOLDER "main");
|
||||||
|
nob_cc_inputs(&cmd, SRCS);
|
||||||
|
|
||||||
|
if (!nob_cmd_run(&cmd)) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
50
src/main.c
Normal file
50
src/main.c
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#include "stack.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void printStack(Stack_t* s) {
|
||||||
|
|
||||||
|
printf("stack{\n\t.index = %d,\n\t.length = %d,\n\t data = @%p{", s->index, s->length, s->data);
|
||||||
|
|
||||||
|
for (unsigned i = s->length; i; i--) {
|
||||||
|
printf("\n\t\t[%d]%d,", i-1, s->data[i-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("\n\t}\n}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
Stack_t s;
|
||||||
|
initStackAlloc(&s, 4);
|
||||||
|
|
||||||
|
printStack(&s);
|
||||||
|
|
||||||
|
printf("isStackEmpty : %d\n", isStackEmpty(&s));
|
||||||
|
StackErrors_e res = pushStack(&s, 4);
|
||||||
|
printf("err : %d\n", res);
|
||||||
|
res = pushStack(&s, 3);
|
||||||
|
printf("err : %d\n", res);
|
||||||
|
|
||||||
|
int32_t val;
|
||||||
|
res = popStack(&s, &val);
|
||||||
|
printf("err : %d, val : %d\n", res, val);
|
||||||
|
res = popStack(&s, &val);
|
||||||
|
printf("err : %d, val : %d\n", res, val);
|
||||||
|
|
||||||
|
res = popStack(&s, &val);
|
||||||
|
printf("err : %d, val : %d\n", res, val);
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 4 + 1; i++) {
|
||||||
|
res = pushStack(&s, i);
|
||||||
|
printf("err : %d\n", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
printStack(&s);
|
||||||
|
}
|
||||||
111
src/stack.c
Normal file
111
src/stack.c
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
#include "stack.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
StackErrors_e initStackAlloc(Stack_t* stack_to_init, uint8_t size) {
|
||||||
|
|
||||||
|
assert(stack_to_init != NULL);
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return stack_size_can_not_be_zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
*stack_to_init = (Stack_t){
|
||||||
|
.index = 0,
|
||||||
|
.length = size,
|
||||||
|
};
|
||||||
|
|
||||||
|
stack_to_init->data = (int32_t*) malloc(size * sizeof(int32_t));
|
||||||
|
// check data was alloced
|
||||||
|
if (stack_to_init->data == NULL) {
|
||||||
|
return failed_to_alloc_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackErrors_e initStackStatic(
|
||||||
|
Stack_t* stack_to_init,
|
||||||
|
int32_t* data,
|
||||||
|
uint8_t size
|
||||||
|
) {
|
||||||
|
assert(stack_to_init != NULL);
|
||||||
|
assert(data != NULL);
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return stack_size_can_not_be_zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
*stack_to_init = (Stack_t){
|
||||||
|
.index = 0,
|
||||||
|
.length = size,
|
||||||
|
.data = data,
|
||||||
|
};
|
||||||
|
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deinitStackAlloc(Stack_t* stack) {
|
||||||
|
free(stack->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deinitStackStatic(Stack_t* stack) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackErrors_e pushStack(Stack_t* stack, int32_t value) {
|
||||||
|
assert(stack != NULL);
|
||||||
|
|
||||||
|
if (isStackFull(stack)) {
|
||||||
|
return stack_is_full;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->data[stack->index] = value;
|
||||||
|
stack->index++;
|
||||||
|
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackErrors_e popStack(Stack_t* stack, int32_t* popped_value) {
|
||||||
|
assert(stack != NULL);
|
||||||
|
assert(popped_value != NULL);
|
||||||
|
|
||||||
|
if(!isStackEmpty(stack)){
|
||||||
|
*popped_value = stack->data[--stack->index];
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stack_is_empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isStackEmpty(Stack_t* stack) {
|
||||||
|
assert(stack != NULL);
|
||||||
|
// this will become false when the stack index is 0
|
||||||
|
// as the stack index - 1 will underflow and become
|
||||||
|
// the max uint8_t
|
||||||
|
if (stack->index < (uint8_t)(stack->index - 1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isStackFull(Stack_t* stack) {
|
||||||
|
assert(stack != NULL);
|
||||||
|
if (stack->index >= stack->length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getStackSize(Stack_t* stack) {
|
||||||
|
assert(stack != NULL);
|
||||||
|
return stack->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getStackRemainingCapacity(Stack_t* stack) {
|
||||||
|
assert(stack != NULL);
|
||||||
|
return stack->length - stack->index;
|
||||||
|
}
|
||||||
|
|
||||||
37
src/stack.h
Normal file
37
src/stack.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct Stack_s{
|
||||||
|
uint8_t length;
|
||||||
|
uint8_t index;
|
||||||
|
int32_t* data;
|
||||||
|
} Stack_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
none = 0,
|
||||||
|
stack_size_can_not_be_zero,
|
||||||
|
failed_to_alloc_data,
|
||||||
|
stack_is_null,
|
||||||
|
stack_is_full,
|
||||||
|
stack_is_empty,
|
||||||
|
}StackErrors_e;
|
||||||
|
|
||||||
|
StackErrors_e initStackAlloc(Stack_t* stack_to_init, uint8_t size);
|
||||||
|
StackErrors_e initStackStatic(
|
||||||
|
Stack_t* stack_to_init,
|
||||||
|
int32_t* data,
|
||||||
|
uint8_t size
|
||||||
|
);
|
||||||
|
|
||||||
|
void deinitStackAlloc(Stack_t* stack);
|
||||||
|
void deinitStackStatic(Stack_t* stack);
|
||||||
|
|
||||||
|
StackErrors_e pushStack(Stack_t* stack, int32_t value);
|
||||||
|
StackErrors_e popStack(Stack_t* stack, int32_t* popped_value);
|
||||||
|
|
||||||
|
bool isStackEmpty(Stack_t* stack);
|
||||||
|
bool isStackFull(Stack_t* stack);
|
||||||
|
|
||||||
|
uint8_t getStackSize(Stack_t* stack);
|
||||||
|
uint8_t getStackRemainingCapacity(Stack_t* stack);
|
||||||
Reference in New Issue
Block a user