summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormaxim nikonov <maxim.nikonov@hqo.co>2026-02-06 00:00:50 +0500
committermaxim nikonov <maxim.nikonov@hqo.co>2026-02-06 00:00:50 +0500
commit4ce4967c33d56e4b56d85d11fe0e0be91e159f5d (patch)
tree8786f3adfd52865aa302577a4149d8129effdf1f
parentc53067d2f6cfd6e3c6b476c51ab8c4b931e40a30 (diff)
wip
-rwxr-xr-xbin/fluidbin2685160 -> 2663096 bytes
-rw-r--r--fluid/app/Image_Asset.cxx78
-rw-r--r--fluid/io/Code_Writer.cxx139
-rw-r--r--fluid/io/Code_Writer.h59
4 files changed, 225 insertions, 51 deletions
diff --git a/bin/fluid b/bin/fluid
index 1cff6c3cb..60d0fab00 100755
--- a/bin/fluid
+++ b/bin/fluid
Binary files differ
diff --git a/fluid/app/Image_Asset.cxx b/fluid/app/Image_Asset.cxx
index 7a05cd99b..09550fac0 100644
--- a/fluid/app/Image_Asset.cxx
+++ b/fluid/app/Image_Asset.cxx
@@ -38,16 +38,64 @@
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
-#include <map>
+#include <string.h>
#include <string>
+/** Simple string-to-Image_Asset map entry */
+struct Image_Asset_Entry {
+ char *key;
+ Image_Asset *value;
+};
-/**
- \brief A map of all image assets.
- \todo This is a global variable, but should be associated
- with a project instead.
- */
-static std::map<std::string, Image_Asset*> image_asset_map;
+/** Simple string-to-Image_Asset map (linear search) */
+static struct {
+ Image_Asset_Entry *entries;
+ int count;
+ int capacity;
+
+ Image_Asset *find(const char *key) {
+ int i;
+ for (i = 0; i < count; i++) {
+ if (strcmp(entries[i].key, key) == 0)
+ return entries[i].value;
+ }
+ return 0;
+ }
+
+ void insert(const char *key, Image_Asset *value) {
+ // Check if already exists
+ int i;
+ for (i = 0; i < count; i++) {
+ if (strcmp(entries[i].key, key) == 0) {
+ entries[i].value = value;
+ return;
+ }
+ }
+ // Insert new
+ if (count >= capacity) {
+ capacity = capacity ? capacity * 2 : 16;
+ entries = (Image_Asset_Entry*)realloc(entries, capacity * sizeof(Image_Asset_Entry));
+ }
+ entries[count].key = strdup(key);
+ entries[count].value = value;
+ count++;
+ }
+
+ void erase(const char *key) {
+ int i;
+ for (i = 0; i < count; i++) {
+ if (strcmp(entries[i].key, key) == 0) {
+ free(entries[i].key);
+ // Move last entry to this position
+ if (i < count - 1) {
+ entries[i] = entries[count - 1];
+ }
+ count--;
+ return;
+ }
+ }
+ }
+} image_asset_map;
/**
@@ -392,12 +440,12 @@ void Image_Asset::write_inline(fld::io::Code_Writer& f, int inactive) {
\returns The image asset, or nullptr if it cannot be loaded.
*/
Image_Asset* Image_Asset::find(const char *iname) {
- if (!iname || !*iname) return nullptr;
+ if (!iname || !*iname) return 0;
// First search to see if it exists already. If it does, return it.
- auto result = image_asset_map.find(iname);
- if (result != image_asset_map.end())
- return result->second;
+ Image_Asset *result = image_asset_map.find(iname);
+ if (result)
+ return result;
// Check if a file by that name exists.
Fluid.proj.enter_project_dir();
@@ -408,7 +456,7 @@ Image_Asset* Image_Asset::find(const char *iname) {
else
fl_message("Can't open image file:\n%s\n%s",iname,strerror(errno));
Fluid.proj.leave_project_dir();
- return nullptr;
+ return 0;
}
fclose(f);
@@ -421,11 +469,11 @@ Image_Asset* Image_Asset::find(const char *iname) {
else
fl_message("Can't read image file:\n%s\nunrecognized image format",iname);
Fluid.proj.leave_project_dir();
- return nullptr;
+ return 0;
}
// Add the new asset to our image asset map and return it to the caller.
- image_asset_map[iname] = asset;
+ image_asset_map.insert(iname, asset);
return asset;
}
@@ -490,7 +538,7 @@ void Image_Asset::dec_ref() {
when the object is destroyed.
*/
Image_Asset::~Image_Asset() {
- image_asset_map.erase(filename_);
+ image_asset_map.erase(filename_.c_str());
if (image_) image_->release();
}
diff --git a/fluid/io/Code_Writer.cxx b/fluid/io/Code_Writer.cxx
index 916d024bd..0998ed287 100644
--- a/fluid/io/Code_Writer.cxx
+++ b/fluid/io/Code_Writer.cxx
@@ -28,14 +28,100 @@
#include <zlib.h>
#include <string>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
using namespace fld;
using namespace fld::io;
using namespace fld::proj;
+// ---- Fd_Id_Map implementation ----
+
+void Fd_Id_Map::clear() {
+ int i;
+ for (i = 0; i < count; i++) {
+ free(entries[i].key);
+ }
+ free(entries);
+ entries = 0;
+ count = 0;
+ capacity = 0;
+}
+
+const char *Fd_Id_Map::find_or_insert(const char *key, void *value, void **found_value) {
+ int i;
+ for (i = 0; i < count; i++) {
+ if (strcmp(entries[i].key, key) == 0) {
+ *found_value = entries[i].value;
+ return entries[i].key;
+ }
+ }
+ // Not found, insert
+ if (count >= capacity) {
+ capacity = capacity ? capacity * 2 : 16;
+ entries = (Fd_Id_Entry*)realloc(entries, capacity * sizeof(Fd_Id_Entry));
+ }
+ entries[count].key = strdup(key);
+ entries[count].value = value;
+ *found_value = value;
+ return entries[count++].key;
+}
+
+// ---- Fd_String_Set implementation ----
+
+void Fd_String_Set::clear() {
+ int i;
+ for (i = 0; i < count; i++) {
+ free(strings[i]);
+ }
+ free(strings);
+ strings = 0;
+ count = 0;
+ capacity = 0;
+}
+
+bool Fd_String_Set::contains(const char *s) {
+ int i;
+ for (i = 0; i < count; i++) {
+ if (strcmp(strings[i], s) == 0) return true;
+ }
+ return false;
+}
+
+void Fd_String_Set::insert(const char *s) {
+ if (count >= capacity) {
+ capacity = capacity ? capacity * 2 : 16;
+ strings = (char**)realloc(strings, capacity * sizeof(char*));
+ }
+ strings[count++] = strdup(s);
+}
+
+// ---- Fd_Pointer_Set implementation ----
+
+void Fd_Pointer_Set::clear() {
+ free(pointers);
+ pointers = 0;
+ count = 0;
+ capacity = 0;
+}
+
+bool Fd_Pointer_Set::contains(void *p) {
+ int i;
+ for (i = 0; i < count; i++) {
+ if (pointers[i] == p) return true;
+ }
+ return false;
+}
+
+void Fd_Pointer_Set::insert(void *p) {
+ if (count >= capacity) {
+ capacity = capacity ? capacity * 2 : 16;
+ pointers = (void**)realloc(pointers, capacity * sizeof(void*));
+ }
+ pointers[count++] = p;
+}
+
/**
Return true if c can be in a C identifier.
I needed this so it is not messed up by locale settings.
@@ -76,18 +162,14 @@ const char* Code_Writer::unique_id(void* o, const char* type, const char* name,
// okay, search the tree and see if the name was already used:
int which = 0;
for (;;) {
- auto it = unique_id_list.find(buffer);
- // If the id does not exist, add it to the map
- if (it == unique_id_list.end()) {
- it = unique_id_list.insert(std::make_pair(buffer, o)).first;
- return it->first.c_str();
- }
- // If it does exist, and the pointers are the same, just return it.
- if (it->second == o) {
- return it->first.c_str();
+ void *found_value = 0;
+ const char *key = unique_id_list.find_or_insert(buffer, o, &found_value);
+ // If found_value matches o, we either inserted new or found existing with same pointer
+ if (found_value == o) {
+ return key;
}
- // Else repeat until we have a new id,
- sprintf(q,"%x",++which);
+ // Else the id exists with a different pointer, try next
+ sprintf(q, "%x", ++which);
}
}
@@ -148,7 +230,7 @@ int Code_Writer::write_h_once(const char *format, ...) {
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
- if (text_in_header.find(buf) != text_in_header.end()) {
+ if (text_in_header.contains(buf)) {
return 0;
}
fprintf(header_file, "%s\n", buf);
@@ -169,11 +251,11 @@ int Code_Writer::write_c_once(const char *format, ...) {
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
// Return if the text was already printed to the header file.
- if (text_in_header.find(buf) != text_in_header.end()) {
+ if (text_in_header.contains(buf)) {
return 0;
}
// Return if the text was already printed to the source file.
- if (text_in_code.find(buf) != text_in_code.end()) {
+ if (text_in_code.contains(buf)) {
return 0;
}
crc_printf("%s\n", buf);
@@ -188,7 +270,7 @@ int Code_Writer::write_c_once(const char *format, ...) {
\return true if found in the tree, false if added to the tree
*/
bool Code_Writer::c_contains(void *pp) {
- if (ptr_in_code.find(pp) != ptr_in_code.end()) {
+ if (ptr_in_code.contains(pp)) {
return true;
}
ptr_in_code.insert(pp);
@@ -643,9 +725,11 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) {
// explicitly set by the user in the Project Settings.
std::string macro_name_str = proj_.include_guard;
if (macro_name_str.empty()) {
- std::ostringstream macro_name;
+ char macro_name[1024];
+ char *mp = macro_name;
+ char *mp_end = macro_name + sizeof(macro_name) - 16;
std::string header_name;
- const char* a = nullptr;
+ const char* a = 0;
if (write_codeview) {
header_name = proj_.headerfile_name();
a = header_name.c_str();
@@ -656,21 +740,22 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) {
int len = 0;
unsigned ucs = fl_utf8decode(a, b, &len);
if ((ucs > 127) || (!isalpha(ucs) && (ucs != '_')))
- macro_name << '_';
- while (a < b) {
+ *mp++ = '_';
+ while (a < b && mp < mp_end) {
ucs = fl_utf8decode(a, b, &len);
if (ucs > 0x0000ffff) { // large unicode character
- macro_name << "\\U" << std::setw(8) << std::setfill('0') << std::hex << ucs;
+ mp += sprintf(mp, "\\U%08x", ucs);
} else if (ucs > 127) { // small unicode character or not an ASCI letter or digit
- macro_name << "\\u" << std::setw(4) << std::setfill('0') << std::hex << ucs;
+ mp += sprintf(mp, "\\u%04x", ucs);
} else if (!isalnum(ucs)) {
- macro_name << '_';
+ *mp++ = '_';
} else {
- macro_name << (char)ucs;
+ *mp++ = (char)ucs;
}
a += len;
}
- macro_name_str = macro_name.str();
+ *mp = 0;
+ macro_name_str = macro_name;
}
fprintf(header_file, "#ifndef %s\n", macro_name_str.c_str());
fprintf(header_file, "#define %s\n", macro_name_str.c_str());
diff --git a/fluid/io/Code_Writer.h b/fluid/io/Code_Writer.h
index c199197ec..9d52e0600 100644
--- a/fluid/io/Code_Writer.h
+++ b/fluid/io/Code_Writer.h
@@ -23,14 +23,55 @@
#include <stdarg.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <string>
-#include <set>
-#include <map>
class Node;
-struct Fd_Identifier_Tree;
-struct Fd_Text_Tree;
-struct Fd_Pointer_Tree;
+
+/** Simple string-to-pointer map entry */
+struct Fd_Id_Entry {
+ char *key;
+ void *value;
+};
+
+/** Simple string-to-pointer map (unsorted array, linear search) */
+struct Fd_Id_Map {
+ Fd_Id_Entry *entries;
+ int count;
+ int capacity;
+
+ Fd_Id_Map() : entries(0), count(0), capacity(0) {}
+ ~Fd_Id_Map() { clear(); }
+ void clear();
+ const char *find_or_insert(const char *key, void *value, void **found_value);
+};
+
+/** Simple string set (unsorted array, linear search) */
+struct Fd_String_Set {
+ char **strings;
+ int count;
+ int capacity;
+
+ Fd_String_Set() : strings(0), count(0), capacity(0) {}
+ ~Fd_String_Set() { clear(); }
+ void clear();
+ bool contains(const char *s);
+ void insert(const char *s);
+};
+
+/** Simple pointer set (unsorted array, linear search) */
+struct Fd_Pointer_Set {
+ void **pointers;
+ int count;
+ int capacity;
+
+ Fd_Pointer_Set() : pointers(0), count(0), capacity(0) {}
+ ~Fd_Pointer_Set() { clear(); }
+ void clear();
+ bool contains(void *p);
+ void insert(void *p);
+};
int is_id(char c);
@@ -52,13 +93,13 @@ private:
FILE *header_file = nullptr;
/// tree of unique but human-readable identifiers
- std::map<std::string, void*> unique_id_list { };
+ Fd_Id_Map unique_id_list;
/// searchable text tree for text that is only written once to the header file
- std::set<std::string> text_in_header { };
+ Fd_String_Set text_in_header;
/// searchable text tree for text that is only written once to the code file
- std::set<std::string> text_in_code { };
+ Fd_String_Set text_in_code;
/// searchable tree for pointers that are only written once to the code file
- std::set<void*> ptr_in_code { };
+ Fd_Pointer_Set ptr_in_code;
/// crc32 for blocks of text written to the code file
unsigned long block_crc_ = 0;