diff options
Diffstat (limited to 'fluid')
| -rw-r--r-- | fluid/app/Image_Asset.cxx | 78 | ||||
| -rw-r--r-- | fluid/io/Code_Writer.cxx | 139 | ||||
| -rw-r--r-- | fluid/io/Code_Writer.h | 59 |
3 files changed, 225 insertions, 51 deletions
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; |
