2025-03-20 04:16:06 +01:00
|
|
|
// Written by retoor@molodetz.nl
|
|
|
|
|
|
|
|
// This code provides functions to determine and convert between snake_case and camelCase strings. It reads from files and processes string
|
|
|
|
// formats, outputting converted formats.
|
|
|
|
|
|
|
|
// The source code includes custom headers: "rio.h", "rmalloc.h", "rprint.h", "rstring.h".
|
|
|
|
|
|
|
|
// MIT License
|
|
|
|
|
2025-01-14 18:53:15 +01:00
|
|
|
#ifndef RCASE_H
|
|
|
|
#define RCASE_H
|
2025-03-20 04:16:06 +01:00
|
|
|
|
2025-01-14 18:53:15 +01:00
|
|
|
#include "rio.h"
|
|
|
|
#include "rmalloc.h"
|
|
|
|
#include "rprint.h"
|
|
|
|
#include "rstring.h"
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#define RCAMEL_CASE 1
|
|
|
|
#define RSNAKE_CASE 2
|
|
|
|
#define RINVALID_CASE 0
|
2025-03-20 04:16:06 +01:00
|
|
|
#define RCONST_TEST_T 4
|
2025-01-14 18:53:15 +01:00
|
|
|
|
|
|
|
int rdetermine_case(const char *str) {
|
2025-03-20 04:16:06 +01:00
|
|
|
char previousChar = 0;
|
2025-01-14 18:53:15 +01:00
|
|
|
int length = strlen(str);
|
|
|
|
|
|
|
|
while (*str) {
|
2025-03-20 04:16:06 +01:00
|
|
|
if (previousChar == '_' && islower(*str))
|
2025-01-14 18:53:15 +01:00
|
|
|
return RSNAKE_CASE;
|
2025-03-20 04:16:06 +01:00
|
|
|
if (previousChar != '_' && !isupper(previousChar) && isupper(*str))
|
2025-01-14 18:53:15 +01:00
|
|
|
return RCAMEL_CASE;
|
2025-03-20 04:16:06 +01:00
|
|
|
previousChar = *str;
|
2025-01-14 18:53:15 +01:00
|
|
|
str++;
|
|
|
|
}
|
|
|
|
|
2025-03-20 04:16:06 +01:00
|
|
|
if (length == 0)
|
2025-01-14 18:53:15 +01:00
|
|
|
return RINVALID_CASE;
|
2025-03-20 04:16:06 +01:00
|
|
|
|
2025-01-14 18:53:15 +01:00
|
|
|
if (strchr(str, '_')) {
|
2025-03-20 04:16:06 +01:00
|
|
|
if (str[0] == '_' || str[length - 1] == '_' || strstr(str, "__"))
|
2025-01-14 18:53:15 +01:00
|
|
|
return RINVALID_CASE;
|
2025-03-20 04:16:06 +01:00
|
|
|
|
2025-01-14 18:53:15 +01:00
|
|
|
for (int i = 0; i < length; i++) {
|
2025-03-20 04:16:06 +01:00
|
|
|
if (!islower(str[i]) && str[i] != '_')
|
2025-01-14 18:53:15 +01:00
|
|
|
return RINVALID_CASE;
|
|
|
|
}
|
|
|
|
return RSNAKE_CASE;
|
|
|
|
} else {
|
2025-03-20 04:16:06 +01:00
|
|
|
if (!islower(str[0]))
|
2025-01-14 18:53:15 +01:00
|
|
|
return RINVALID_CASE;
|
2025-03-20 04:16:06 +01:00
|
|
|
|
2025-01-14 18:53:15 +01:00
|
|
|
for (int i = 1; i < length; i++) {
|
2025-03-20 04:16:06 +01:00
|
|
|
if (str[i] == '_')
|
2025-01-14 18:53:15 +01:00
|
|
|
return RINVALID_CASE;
|
2025-03-20 04:16:06 +01:00
|
|
|
if (isupper(str[i]) && isupper(str[i - 1]))
|
2025-01-14 18:53:15 +01:00
|
|
|
return RINVALID_CASE;
|
|
|
|
}
|
|
|
|
return RCAMEL_CASE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char *rsnake_to_camel(const char *snake_case) {
|
|
|
|
int length = strlen(snake_case);
|
|
|
|
char *camel_case = (char *)malloc(length + 1);
|
|
|
|
int j = 0;
|
|
|
|
int toUpper = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < length; i++) {
|
2025-03-20 04:16:06 +01:00
|
|
|
if (snake_case[i] == '_') {
|
|
|
|
if (snake_case[i + 1] == 'T' || (snake_case[i + 1] == 't' && !isspace(snake_case[i + 2]))) {
|
|
|
|
toUpper = 1;
|
2025-01-14 18:53:15 +01:00
|
|
|
}
|
2025-03-20 04:16:06 +01:00
|
|
|
continue;
|
2025-01-14 18:53:15 +01:00
|
|
|
}
|
2025-03-20 04:16:06 +01:00
|
|
|
if (toUpper) {
|
|
|
|
camel_case[j++] = toupper(snake_case[i]);
|
|
|
|
toUpper = 0;
|
2025-01-14 18:53:15 +01:00
|
|
|
} else {
|
2025-03-20 04:16:06 +01:00
|
|
|
camel_case[j++] = snake_case[i];
|
2025-01-14 18:53:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
camel_case[j] = '\0';
|
|
|
|
return camel_case;
|
|
|
|
}
|
2025-03-20 04:16:06 +01:00
|
|
|
|
2025-01-14 18:53:15 +01:00
|
|
|
char *rcamel_to_snake(const char *camelCase) {
|
|
|
|
int length = strlen(camelCase);
|
|
|
|
char *snake_case = (char *)malloc(2 * length + 1);
|
|
|
|
int j = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
if (isupper(camelCase[i])) {
|
2025-03-20 04:16:06 +01:00
|
|
|
if (i != 0)
|
2025-01-14 18:53:15 +01:00
|
|
|
snake_case[j++] = '_';
|
|
|
|
snake_case[j++] = tolower(camelCase[i]);
|
|
|
|
} else {
|
|
|
|
snake_case[j++] = camelCase[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
snake_case[j] = '\0';
|
|
|
|
return snake_case;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *rflip_case(char *content) {
|
2025-03-20 04:16:06 +01:00
|
|
|
switch (rdetermine_case(content)) {
|
|
|
|
case RSNAKE_CASE:
|
2025-01-14 18:53:15 +01:00
|
|
|
return rcamel_to_snake(content);
|
2025-03-20 04:16:06 +01:00
|
|
|
case RCAMEL_CASE:
|
2025-01-14 18:53:15 +01:00
|
|
|
return rsnake_to_camel(content);
|
2025-03-20 04:16:06 +01:00
|
|
|
default:
|
2025-01-14 18:53:15 +01:00
|
|
|
rprintr("Could not determine case\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char *rflip_case_file(char *filepath) {
|
|
|
|
size_t file_size = rfile_size(filepath);
|
2025-03-20 04:16:06 +01:00
|
|
|
if (file_size == 0)
|
2025-01-14 18:53:15 +01:00
|
|
|
return NULL;
|
2025-03-20 04:16:06 +01:00
|
|
|
|
2025-01-14 18:53:15 +01:00
|
|
|
char *content = (char *)malloc(file_size);
|
|
|
|
char *result = NULL;
|
2025-03-20 04:16:06 +01:00
|
|
|
|
2025-01-14 18:53:15 +01:00
|
|
|
if (rfile_readb(filepath, content, file_size)) {
|
|
|
|
result = rflip_case(content);
|
2025-03-20 04:16:06 +01:00
|
|
|
free(content);
|
2025-01-14 18:53:15 +01:00
|
|
|
}
|
2025-03-20 04:16:06 +01:00
|
|
|
|
2025-01-14 18:53:15 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rcase_main(int argc, char *argv[]) {
|
|
|
|
if (argc < 2) {
|
|
|
|
printf("usage: rcase <file>\n");
|
|
|
|
return 1;
|
|
|
|
}
|
2025-03-20 04:16:06 +01:00
|
|
|
|
2025-01-14 18:53:15 +01:00
|
|
|
for (int i = 1; i < argc; i++) {
|
|
|
|
char *result = rflip_case_file(argv[i]);
|
|
|
|
if (result) {
|
|
|
|
printf("%s\n", result);
|
|
|
|
free(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2025-03-20 04:16:06 +01:00
|
|
|
|
|
|
|
#endif
|