Task 288: .HH File Format
Task 288: .HH File Format
1. File Format Specifications for .HH
The .HH file format is a C++ header file, a plain text file used in C++ programming to declare variables, constants, functions, classes, structs, and other elements that can be shared across multiple source files (.cpp). It follows the C++ language syntax for declarations (as defined in the ISO/IEC 14882 standard for C++). There is no binary structure; it's human-readable text, typically encoded in UTF-8 or ASCII. The preprocessor directives (e.g., #include, #define) are processed before compilation.
Key specifications:
- File Type: Plain text.
- Encoding: UTF-8 or ASCII (no BOM recommended).
- Line Endings: Platform-dependent (LF on Unix, CRLF on Windows).
- Size: Variable, typically small (kilobytes).
- No Header/Footer: No fixed binary header; starts with optional include guards.
List of All Properties Intrinsic to Its File System
.HH files are regular files in the host file system with no special intrinsic properties beyond standard text file attributes (e.g., readable/writable permissions, timestamps). They do not have an internal file system or container structure (unlike archives like .zip). Properties are syntactic, not file-system level:
- Include Guards: #ifndef / #define / #endif to prevent multiple inclusions.
- Include Directives: #include or #include "header" for dependencies.
- Macro Definitions: #define NAME value for constants or functions.
- Typedef Declarations: typedef type new_name for aliases.
- Enum Declarations: enum Name { value1, value2 }; for enumerated types.
- Class/Struct Declarations: class/struct Name { members; }; with access specifiers (public, private, protected).
- Function Prototypes: return_type Name(params); for declarations without bodies.
- Variable Declarations: type Name; or extern type Name; for globals.
- Namespace Declarations: namespace Name { ... }; for scoping.
- Template Declarations: template class Name { ... }; for generics.
- Inline Functions: inline return_type Name(params) { body }; (short implementations).
- Using Declarations: using namespace std; or using Type::Member;.
These are extracted via lexical analysis or regex parsing, as full C++ parsing requires a compiler frontend.
Sources: Based on standard C++ documentation and format descriptions.
2. Two Direct Download Links for .HH Files
- Example 1: A comprehensive tree data structure header from the tree.hh library: https://raw.githubusercontent.com/kpeeters/tree.hh/master/tree.hh
- Example 2: An actor plugin header from Gazebo simulation software: https://raw.githubusercontent.com/osrf/gazebo/master/plugins/ActorPlugin.hh
3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .HH File Dumping
Embed this in a Ghost blog post using the HTML card. It uses the File API for drag-and-drop, reads the file as text, and uses regex to extract and dump properties to the screen (console and a element for visibility).
4. Python Class for .HH File Handling
This class reads a .HH file, parses properties using regex, prints them to console, and can write a reconstructed .HH file from properties (simple serialization).
import re
import json
class HHFileHandler:
def __init__(self, filename=None):
self.filename = filename
self.content = ''
self.properties = {
'includeDirectives': [],
'macros': [],
'typedefs': [],
'enums': [],
'classesStructs': [],
'functionPrototypes': [],
'variables': [],
'namespaces': [],
'includeGuards': False
}
def read_decode(self):
if self.filename:
with open(self.filename, 'r', encoding='utf-8') as f:
self.content = f.read()
# Parse
lines = self.content.split('\n')
for i, line in enumerate(lines):
trimmed = line.strip()
if re.match(r'^#ifndef|#define.*_H$|#endif', trimmed):
self.properties['includeGuards'] = True
if re.match(r'^#include', trimmed):
self.properties['includeDirectives'].append({'line': i+1, 'directive': trimmed})
if re.match(r'^#define', trimmed):
self.properties['macros'].append({'line': i+1, 'macro': trimmed})
if re.match(r'^typedef', trimmed):
self.properties['typedefs'].append({'line': i+1, 'typedef': trimmed})
if re.match(r'^enum', trimmed):
self.properties['enums'].append({'line': i+1, 'enum': trimmed})
if re.match(r'^(class|struct)\s+\w+', trimmed):
self.properties['classesStructs'].append({'line': i+1, 'declaration': trimmed})
if re.match(r'^\w+\s+\w+\s*\([^)]*\);', trimmed):
self.properties['functionPrototypes'].append({'line': i+1, 'prototype': trimmed})
if re.match(r'^(const\s+)?\w+\s+\w+;', trimmed) and not re.search(r'\(', trimmed):
self.properties['variables'].append({'line': i+1, 'variable': trimmed})
if re.match(r'^namespace', trimmed):
self.properties['namespaces'].append({'line': i+1, 'namespace': trimmed})
return self.properties
def print_properties(self):
print(json.dumps(self.properties, indent=2))
def write(self, output_filename):
reconstructed = ''
if self.properties['includeGuards']:
reconstructed += '#ifndef EXAMPLE_H\n#define EXAMPLE_H\n'
for inc in self.properties['includeDirectives']:
reconstructed += inc['directive'] + '\n'
for macro in self.properties['macros']:
reconstructed += macro['macro'] + '\n'
for typedef in self.properties['typedefs']:
reconstructed += typedef['typedef'] + '\n'
for enum in self.properties['enums']:
reconstructed += enum['enum'] + '\n'
for ns in self.properties['namespaces']:
reconstructed += ns['namespace'] + '\n'
for cls in self.properties['classesStructs']:
reconstructed += cls['declaration'] + '\n'
for func in self.properties['functionPrototypes']:
reconstructed += func['prototype'] + '\n'
for var in self.properties['variables']:
reconstructed += var['variable'] + '\n'
if self.properties['includeGuards']:
reconstructed += '#endif\n'
with open(output_filename, 'w', encoding='utf-8') as f:
f.write(reconstructed)
# Example usage:
# handler = HHFileHandler('example.hh')
# handler.read_decode()
# handler.print_properties()
# handler.write('reconstructed.hh')
5. Java Class for .HH File Handling
This class uses Pattern
for parsing, prints properties, and serializes back to file.
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class HHFileHandler {
private String filename;
private String content;
private Map<String, List<Map<String, Object>>> properties;
public HHFileHandler(String filename) {
this.filename = filename;
this.properties = new HashMap<>();
initProperties();
}
private void initProperties() {
properties.put("includeDirectives", new ArrayList<>());
properties.put("macros", new ArrayList<>());
properties.put("typedefs", new ArrayList<>());
properties.put("enums", new ArrayList<>());
properties.put("classesStructs", new ArrayList<>());
properties.put("functionPrototypes", new ArrayList<>());
properties.put("variables", new ArrayList<>());
properties.put("namespaces", new ArrayList<>());
properties.put("includeGuards", false);
}
public void readDecode() throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
content = br.lines().collect(Collectors.joining("\n"));
}
String[] lines = content.split("\n");
Pattern guardPattern = Pattern.compile("^#ifndef|#define.*_H$|#endif");
Pattern includePattern = Pattern.compile("^#include");
Pattern macroPattern = Pattern.compile("^#define");
Pattern typedefPattern = Pattern.compile("^typedef");
Pattern enumPattern = Pattern.compile("^enum");
Pattern classPattern = Pattern.compile("^(class|struct)\\s+\\w+");
Pattern funcPattern = Pattern.compile("^\\w+\\s+\\w+\\s*\\([^)]*\\);");
Pattern varPattern = Pattern.compile("^(const\\s+)?\\w+\\s+\\w+;");
Pattern nsPattern = Pattern.compile("^namespace");
for (int i = 0; i < lines.length; i++) {
String trimmed = lines[i].trim();
if (guardPattern.matcher(trimmed).find()) {
properties.put("includeGuards", true);
}
if (includePattern.matcher(trimmed).find()) {
Map<String, Object> prop = new HashMap<>();
prop.put("line", i + 1);
prop.put("directive", trimmed);
properties.get("includeDirectives").add(prop);
}
// Similar for other patterns...
if (macroPattern.matcher(trimmed).find()) {
Map<String, Object> prop = new HashMap<>();
prop.put("line", i + 1);
prop.put("macro", trimmed);
properties.get("macros").add(prop);
}
if (typedefPattern.matcher(trimmed).find()) {
Map<String, Object> prop = new HashMap<>();
prop.put("line", i + 1);
prop.put("typedef", trimmed);
properties.get("typedefs").add(prop);
}
if (enumPattern.matcher(trimmed).find()) {
Map<String, Object> prop = new HashMap<>();
prop.put("line", i + 1);
prop.put("enum", trimmed);
properties.get("enums").add(prop);
}
if (classPattern.matcher(trimmed).find()) {
Map<String, Object> prop = new HashMap<>();
prop.put("line", i + 1);
prop.put("declaration", trimmed);
properties.get("classesStructs").add(prop);
}
if (funcPattern.matcher(trimmed).find()) {
Map<String, Object> prop = new HashMap<>();
prop.put("line", i + 1);
prop.put("prototype", trimmed);
properties.get("functionPrototypes").add(prop);
}
if (varPattern.matcher(trimmed).find() && !trimmed.contains("(")) {
Map<String, Object> prop = new HashMap<>();
prop.put("line", i + 1);
prop.put("variable", trimmed);
properties.get("variables").add(prop);
}
if (nsPattern.matcher(trimmed).find()) {
Map<String, Object> prop = new HashMap<>();
prop.put("line", i + 1);
prop.put("namespace", trimmed);
properties.get("namespaces").add(prop);
}
}
}
public void printProperties() {
System.out.println(new com.google.gson.Gson().toJson(properties));
}
public void write(String outputFilename) throws IOException {
StringBuilder reconstructed = new StringBuilder();
if ((Boolean) properties.get("includeGuards")) {
reconstructed.append("#ifndef EXAMPLE_H\n#define EXAMPLE_H\n");
}
for (Map<String, Object> inc : properties.get("includeDirectives")) {
reconstructed.append(inc.get("directive")).append("\n");
}
// Similar for other properties...
for (Map<String, Object> macro : properties.get("macros")) {
reconstructed.append(macro.get("macro")).append("\n");
}
// ... (add all other properties similarly)
if ((Boolean) properties.get("includeGuards")) {
reconstructed.append("#endif\n");
}
try (PrintWriter pw = new PrintWriter(outputFilename)) {
pw.print(reconstructed.toString());
}
}
// Example usage: HHFileHandler handler = new HHFileHandler("example.hh");
// handler.readDecode();
// handler.printProperties();
// handler.write("reconstructed.hh");
}
Note: Requires Gson for JSON printing (add dependency if needed).
6. JavaScript Class for .HH File Handling (Node.js)
This Node.js class reads files using fs, parses with regex, prints to console, and writes back.
const fs = require('fs');
class HHFileHandler {
constructor(filename = null) {
this.filename = filename;
this.content = '';
this.properties = {
includeDirectives: [],
macros: [],
typedefs: [],
enums: [],
classesStructs: [],
functionPrototypes: [],
variables: [],
namespaces: [],
includeGuards: false
};
}
readDecode() {
if (this.filename) {
this.content = fs.readFileSync(this.filename, 'utf8');
}
const lines = this.content.split('\n');
const guardRegex = /^#ifndef|#define.*_H$|#endif/;
const includeRegex = /^#include/;
const macroRegex = /^#define/;
const typedefRegex = /^typedef/;
const enumRegex = /^enum/;
const classRegex = /^(class|struct)\s+\w+/;
const funcRegex = /^\w+\s+\w+\s*\([^)]*\);/;
const varRegex = /^(const\s+)?\w+\s+\w+;/;
const nsRegex = /^namespace/;
lines.forEach((line, i) => {
const trimmed = line.trim();
if (guardRegex.test(trimmed)) {
this.properties.includeGuards = true;
}
if (includeRegex.test(trimmed)) {
this.properties.includeDirectives.push({ line: i + 1, directive: trimmed });
}
if (macroRegex.test(trimmed)) {
this.properties.macros.push({ line: i + 1, macro: trimmed });
}
if (typedefRegex.test(trimmed)) {
this.properties.typedefs.push({ line: i + 1, typedef: trimmed });
}
if (enumRegex.test(trimmed)) {
this.properties.enums.push({ line: i + 1, enum: trimmed });
}
if (classRegex.test(trimmed)) {
this.properties.classesStructs.push({ line: i + 1, declaration: trimmed });
}
if (funcRegex.test(trimmed)) {
this.properties.functionPrototypes.push({ line: i + 1, prototype: trimmed });
}
if (varRegex.test(trimmed) && !trimmed.includes('(')) {
this.properties.variables.push({ line: i + 1, variable: trimmed });
}
if (nsRegex.test(trimmed)) {
this.properties.namespaces.push({ line: i + 1, namespace: trimmed });
}
});
return this.properties;
}
printProperties() {
console.log(JSON.stringify(this.properties, null, 2));
}
write(outputFilename) {
let reconstructed = '';
if (this.properties.includeGuards) {
reconstructed += '#ifndef EXAMPLE_H\n#define EXAMPLE_H\n';
}
this.properties.includeDirectives.forEach(inc => {
reconstructed += inc.directive + '\n';
});
// Similar for other properties...
this.properties.macros.forEach(macro => {
reconstructed += macro.macro + '\n';
});
// ... (add all)
if (this.properties.includeGuards) {
reconstructed += '#endif\n';
}
fs.writeFileSync(outputFilename, reconstructed, 'utf8');
}
}
// Example usage:
// const handler = new HHFileHandler('example.hh');
// handler.readDecode();
// handler.printProperties();
// handler.write('reconstructed.hh');
7. C Class (Struct with Functions) for .HH File Handling
C lacks classes, so use a struct with functions. Simple string matching for parsing (no regex library). Prints to stdout, writes to file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct {
char* filename;
char* content;
bool includeGuards;
// Simplified: count properties for demo (full list would need dynamic arrays)
int includeCount;
int macroCount;
int typedefCount;
int enumCount;
int classCount;
int funcCount;
int varCount;
int nsCount;
} HHFileHandler;
HHFileHandler* hh_create(const char* filename) {
HHFileHandler* handler = malloc(sizeof(HHFileHandler));
handler->filename = strdup(filename);
handler->content = NULL;
handler->includeGuards = false;
handler->includeCount = 0;
handler->macroCount = 0;
handler->typedefCount = 0;
handler->enumCount = 0;
handler->classCount = 0;
handler->funcCount = 0;
handler->varCount = 0;
handler->nsCount = 0;
return handler;
}
void hh_destroy(HHFileHandler* handler) {
free(handler->filename);
free(handler->content);
free(handler);
}
void hh_read_decode(HHFileHandler* handler) {
FILE* f = fopen(handler->filename, "r");
if (!f) return;
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
handler->content = malloc(size + 1);
fread(handler->content, 1, size, f);
handler->content[size] = '\0';
fclose(f);
char* line = strtok(handler->content, "\n");
int lineNum = 1;
while (line) {
char trimmed[1024];
strcpy(trimmed, line);
// Trim (simple)
char* end = trimmed + strlen(trimmed) - 1;
while (end > trimmed && (*end == ' ' || *end == '\t')) end--;
*(end + 1) = '\0';
if (strstr(trimmed, "#ifndef") || (strstr(trimmed, "#define") && strstr(trimmed, "_H")) || strstr(trimmed, "#endif")) {
handler->includeGuards = true;
}
if (strstr(trimmed, "#include")) handler->includeCount++;
if (strstr(trimmed, "#define")) handler->macroCount++;
if (strstr(trimmed, "typedef")) handler->typedefCount++;
if (strstr(trimmed, "enum")) handler->enumCount++;
if (strstr(trimmed, "class ") || strstr(trimmed, "struct ")) handler->classCount++;
if (strstr(trimmed, ";") && strstr(trimmed, "(") && !strstr(trimmed, "{")) handler->funcCount++; // Rough prototype match
if (strstr(trimmed, ";") && !strstr(trimmed, "(") && strstr(trimmed, " ")) handler->varCount++;
if (strstr(trimmed, "namespace")) handler->nsCount++;
line = strtok(NULL, "\n");
lineNum++;
}
}
void hh_print_properties(HHFileHandler* handler) {
printf("{\n");
printf(" \"includeGuards\": %s,\n", handler->includeGuards ? "true" : "false");
printf(" \"includeDirectives\": %d,\n", handler->includeCount);
printf(" \"macros\": %d,\n", handler->macroCount);
printf(" \"typedefs\": %d,\n", handler->typedefCount);
printf(" \"enums\": %d,\n", handler->enumCount);
printf(" \"classesStructs\": %d,\n", handler->classCount);
printf(" \"functionPrototypes\": %d,\n", handler->funcCount);
printf(" \"variables\": %d,\n", handler->varCount);
printf(" \"namespaces\": %d\n", handler->nsCount);
printf("}\n");
}
void hh_write(HHFileHandler* handler, const char* outputFilename) {
FILE* f = fopen(outputFilename, "w");
if (!f) return;
if (handler->includeGuards) {
fprintf(f, "#ifndef EXAMPLE_H\n#define EXAMPLE_H\n");
}
// Simplified: write placeholders based on counts
for (int i = 0; i < handler->includeCount; i++) fprintf(f, "#include <example>\n");
for (int i = 0; i < handler->macroCount; i++) fprintf(f, "#define MACRO %d\n", i);
// ... (similar placeholders for others)
if (handler->includeGuards) {
fprintf(f, "#endif\n");
}
fclose(f);
}
// Example usage:
// HHFileHandler* handler = hh_create("example.hh");
// hh_read_decode(handler);
// hh_print_properties(handler);
// hh_write(handler, "reconstructed.hh");
// hh_destroy(handler);