2
0
Sean Barrett 6 жил өмнө
parent
commit
1034f5e5c4
2 өөрчлөгдсөн 302 нэмэгдсэн , 5 устгасан
  1. 14 5
      README.md
  2. 288 0
      stb_include.h

+ 14 - 5
README.md

@@ -5,6 +5,14 @@ stb
 
 single-file public domain (or MIT licensed) libraries for C/C++ <a name="stb_libs"></a>
 
+Noteworthy:
+
+* image loader: <a href="/nothings/stb/blob/master/stb_image.h">stb_image.h</a>
+* image writer: <a href="/nothings/stb/blob/master/stb_image_write.h">stb_image_write.h</a>
+* image resizer: <a href="/nothings/stb/blob/master/stb_image_resize.h">stb_image_resize.h></a>
+* font text rasterizer: <a href="/nothings/stb/blob/master/stb_truetype.h">stb_truetype.h</a>
+* typesafe containers: <a href="/nothings/stb/blob/master/stb_ds.h">stb_ds.h</a>
+
 Most libraries by stb, except: stb_dxt by Fabian "ryg" Giesen, stb_image_resize
 by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
 
@@ -12,7 +20,7 @@ by Jorge L. "VinoBS" Rodriguez, and stb_sprintf by Jeff Roberts.
 library    | lastest version | category | LoC | description
 --------------------- | ---- | -------- | --- | --------------------------------
 **[stb_vorbis.c](stb_vorbis.c)** | 1.16 | audio | 5486 | decode ogg vorbis files from file/memory to float/16-bit signed output
-**[stb_image.h](stb_image.h)** | 2.22 | graphics | 7547 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
+**[stb_image.h](stb_image.h)** | 2.22 | graphics | 7555 | image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC
 **[stb_truetype.h](stb_truetype.h)** | 1.21 | graphics | 4882 | parse, decode, and rasterize characters from truetype fonts
 **[stb_image_write.h](stb_image_write.h)** | 1.13 | graphics | 1622 | image writing to disk: PNG, TGA, BMP
 **[stb_image_resize.h](stb_image_resize.h)** | 0.96 | graphics | 2630 | resize images larger/smaller with good quality
@@ -23,18 +31,19 @@ library    | lastest version | category | LoC | description
 **[stb_textedit.h](stb_textedit.h)** | 1.13 | user&nbsp;interface | 1404 | guts of a text editor for games etc implementing them from scratch
 **[stb_voxel_render.h](stb_voxel_render.h)** | 0.88 | 3D&nbsp;graphics | 3806 | Minecraft-esque voxel rendering "engine" with many more features
 **[stb_dxt.h](stb_dxt.h)** | 1.08b | 3D&nbsp;graphics | 728 | Fabian "ryg" Giesen's real-time DXT compressor
-**[stb_perlin.h](stb_perlin.h)** | 0.4 | 3D&nbsp;graphics | 366 | revised Perlin noise (3D input, 1D output)
+**[stb_perlin.h](stb_perlin.h)** | 0.4 | 3D&nbsp;graphics | 427 | revised Perlin noise (3D input, 1D output)
 **[stb_easy_font.h](stb_easy_font.h)** | 1.0 | 3D&nbsp;graphics | 303 | quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc
 **[stb_tilemap_editor.h](stb_tilemap_editor.h)** | 0.41 | game&nbsp;dev | 4161 | embeddable tilemap editor
 **[stb_herringbone_wa...](stb_herringbone_wang_tile.h)** | 0.7 | game&nbsp;dev | 1221 | herringbone Wang tile map generator
 **[stb_c_lexer.h](stb_c_lexer.h)** | 0.10 | parsing | 964 | simplify writing parsers for C-like languages
 **[stb_divide.h](stb_divide.h)** | 0.92 | math | 421 | more useful 32-bit modulus e.g. "euclidean divide"
 **[stb_connected_comp...](stb_connected_components.h)** | 0.96 | misc | 1049 | incrementally compute reachability on grids
-**[stb.h](stb.h)** | 2.34 | misc | 14453 | helper functions for C, mostly redundant in C++; basically author's personal stuff
+**[stb.h](stb.h)** | 2.34 | misc | 14451 | helper functions for C, mostly redundant in C++; basically author's personal stuff
 **[stb_leakcheck.h](stb_leakcheck.h)** | 0.5 | misc | 190 | quick-and-dirty malloc/free leak-checking
+**[stb_include.h](stb_include.h)** | 0.01 | misc | 288 | implement recursive #include support, particularly for GLSL
 
-Total libraries: 21  
-Total lines of C code: 55652
+Total libraries: 22  
+Total lines of C code: 56007
 
 
 FAQ

+ 288 - 0
stb_include.h

@@ -0,0 +1,288 @@
+// stb_include.h - v0.01 - parse and process #include directives - public domain
+//
+// To build this, in one source file that includes this file do
+//      #define STB_INCLUDE_IMPLEMENTATION
+//
+// This program parses a string and replaces lines of the form
+//         #include "foo"
+// with the contents of a file named "foo". It also embeds the
+// appropriate #line directives. Note that all include files must
+// reside in the location specified in the path passed to the API;
+// it does not check multiple directories.
+//
+// If the string contains a line of the form
+//         #inject
+// then it will be replaced with the contents of the string 'inject' passed to the API.
+//
+// Options:
+//
+//      Define STB_INCLUDE_LINE_GLSL to get GLSL-style #line directives
+//      which use numbers instead of filenames.
+//
+//      Define STB_INCLUDE_LINE_NONE to disable output of #line directives.
+//
+// Standard libraries:
+//
+//      stdio.h     FILE, fopen, fclose, fseek, ftell
+//      stdlib.h    malloc, realloc, free
+//      string.h    strcpy, strncmp, memcpy
+
+#ifndef STB_INCLUDE_STB_INCLUDE_H
+#define STB_INCLUDE_STB_INCLUDE_H
+
+// Do include-processing on the string 'str'. To free the return value, pass it to free()
+char *stb_include_string(char *str, char *inject, char *path_to_includes, char *filename_for_line_directive, char error[256]);
+
+// Concatenate the strings 'strs' and do include-processing on the result. To free the return value, pass it to free()
+char *stb_include_strings(char **strs, int count, char *inject, char *path_to_includes, char *filename_for_line_directive, char error[256]);
+
+// Load the file 'filename' and do include-processing on the string therein. note that
+// 'filename' is opened directly; 'path_to_includes' is not used. To free the return value, pass it to free()
+char *stb_include_file(char *filename, char *inject, char *path_to_includes, char error[256]);
+
+#endif
+
+
+#ifdef STB_INCLUDE_IMPLEMENTATION
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *stb_include_load_file(char *filename, size_t *plen)
+{
+   char *text;
+   size_t len;
+   FILE *f = fopen(filename, "rb");
+   if (f == 0) return 0;
+   fseek(f, 0, SEEK_END);
+   len = (size_t) ftell(f);
+   if (plen) *plen = len;
+   text = (char *) malloc(len+1);
+   if (text == 0) return 0;
+   fseek(f, 0, SEEK_SET);
+   fread(text, 1, len, f);
+   fclose(f);
+   text[len] = 0;
+   return text;
+}
+
+typedef struct
+{
+   int offset;
+   int end;
+   char *filename;
+   int next_line_after;
+} include_info;
+
+static include_info *stb_include_append_include(include_info *array, int len, int offset, int end, char *filename, int next_line)
+{
+   include_info *z = (include_info *) realloc(array, sizeof(*z) * (len+1));
+   z[len].offset   = offset;
+   z[len].end      = end;
+   z[len].filename = filename;
+   z[len].next_line_after = next_line;
+   return z;
+}
+
+static void stb_include_free_includes(include_info *array, int len)
+{
+   int i;
+   for (i=0; i < len; ++i)
+      free(array[i].filename);
+   free(array);
+}
+
+static int stb_include_isspace(int ch)
+{
+   return (ch == ' ' || ch == '\t' || ch == '\r' || ch == 'n');
+}
+
+// find location of all #include and #inject
+static int stb_include_find_includes(char *text, include_info **plist)
+{
+   int line_count = 1;
+   int inc_count = 0;
+   char *s = text, *start;
+   include_info *list = NULL;
+   while (*s) {
+      // parse is always at start of line when we reach here
+      start = s;
+      while (*s == ' ' || *s == '\t')
+         ++s;
+      if (*s == '#') {
+         ++s;
+         while (*s == ' ' || *s == '\t')
+            ++s;
+         if (0==strncmp(s, "include", 7) && stb_include_isspace(s[7])) {
+            s += 7;
+            while (*s == ' ' || *s == '\t')
+               ++s;
+            if (*s == '"') {
+               char *t = ++s;
+               while (*t != '"' && *t != '\n' && *t != '\r' && *t != 0)
+                  ++t;
+               if (*t == '"') {
+                  char *filename = (char *) malloc(t-s+1);
+                  memcpy(filename, s, t-s);
+                  filename[t-s] = 0;
+                  s=t;
+                  while (*s != '\r' && *s != '\n' && *s != 0)
+                     ++s;
+                  // s points to the newline, so s-start is everything except the newline
+                  list = stb_include_append_include(list, inc_count++, start-text, s-text, filename, line_count+1);
+               }
+            }
+         } else if (0==strncmp(s, "inject", 6) && (stb_include_isspace(s[6]) || s[6]==0)) {
+            while (*s != '\r' && *s != '\n' && *s != 0)
+               ++s;
+            list = stb_include_append_include(list, inc_count++, start-text, s-text, NULL, line_count+1);
+         }
+      }
+      while (*s != '\r' && *s != '\n' && *s != 0)
+         ++s;
+      if (*s == '\r' || *s == '\n') {
+         s = s + (s[0] + s[1] == '\r' + '\n' ? 2 : 1);
+      }
+      ++line_count;
+   }
+   *plist = list;
+   return inc_count;
+}
+
+// avoid dependency on sprintf()
+static void stb_include_itoa(char str[9], int n)
+{
+   int i;
+   for (i=0; i < 8; ++i)
+      str[i] = ' ';
+   str[i] = 0;
+
+   for (i=1; i < 8; ++i) {
+      str[7-i] = '0' + (n % 10);
+      n /= 10;
+      if (n == 0)
+         break;
+   }
+}
+
+static char *stb_include_append(char *str, size_t *curlen, char *addstr, size_t addlen)
+{
+   str = (char *) realloc(str, *curlen + addlen);
+   memcpy(str + *curlen, addstr, addlen);
+   *curlen += addlen;
+   return str;
+}
+
+char *stb_include_string(char *str, char *inject, char *path_to_includes, char *filename, char error[256])
+{
+   char temp[4096];
+   include_info *inc_list;
+   int i, num = stb_include_find_includes(str, &inc_list);
+   size_t source_len = strlen(str);
+   char *text=0;
+   size_t textlen=0, last=0;
+   for (i=0; i < num; ++i) {
+      text = stb_include_append(text, &textlen, str+last, inc_list[i].offset - last);
+      // write out line directive for the include
+      #ifndef STB_INCLUDE_LINE_NONE
+      #ifdef STB_INCLUDE_LINE_GLSL
+      if (textlen != 0)  // GLSL #version must appear first, so don't put a #line at the top
+      #endif
+      {
+         strcpy(temp, "#line ");
+         stb_include_itoa(temp+6, 1);
+         strcat(temp, " ");
+         #ifdef STB_INCLUDE_LINE_GLSL
+         stb_include_itoa(temp+15, i+1);
+         #else
+         strcat(temp, "\"");
+         if (inc_list[i].filename == 0)
+            strcmp(temp, "INJECT");
+         else
+            strcat(temp, inc_list[i].filename);
+         strcat(temp, "\"");
+         #endif
+         strcat(temp, "\n");
+         text = stb_include_append(text, &textlen, temp, strlen(temp));
+      }
+      #endif
+      if (inc_list[i].filename == 0) {
+         if (inject != 0)
+            text = stb_include_append(text, &textlen, inject, strlen(inject));
+      } else {
+         char *inc;
+         strcpy(temp, path_to_includes);
+         strcat(temp, "/");
+         strcat(temp, inc_list[i].filename);
+         inc = stb_include_file(temp, inject, path_to_includes, error);
+         if (inc == NULL) {
+            stb_include_free_includes(inc_list, num);
+            return NULL;
+         }
+         text = stb_include_append(text, &textlen, inc, strlen(inc));
+         free(inc);
+      }
+      // write out line directive
+      #ifndef STB_INCLUDE_LINE_NONE
+      strcpy(temp, "\n#line ");
+      stb_include_itoa(temp+6, inc_list[i].next_line_after);
+      strcat(temp, " ");
+      #ifdef STB_INCLUDE_LINE_GLSL
+      stb_include_itoa(temp+15, 0);
+      #else
+      strcat(temp, filename != 0 ? filename : "source-file");
+      #endif
+      text = stb_include_append(text, &textlen, temp, strlen(temp));
+      // no newlines, because we kept the #include newlines, which will get appended next
+      #endif
+      last = inc_list[i].end;
+   }
+   text = stb_include_append(text, &textlen, str+last, source_len - last + 1); // append '\0'
+   stb_include_free_includes(inc_list, num);
+   return text;
+}
+
+char *stb_include_strings(char **strs, int count, char *inject, char *path_to_includes, char *filename, char error[256])
+{
+   char *text;
+   char *result;
+   int i;
+   size_t length=0;
+   for (i=0; i < count; ++count)
+      length += strlen(strs[i]);
+   text = (char *) malloc(length+1);
+   length = 0;
+   for (i=0; i < count; ++count) {
+      strcpy(text + length, strs[i]);
+      length += strlen(strs[i]);
+   }
+   result = stb_include_string(text, inject, path_to_includes, filename, error);
+   free(text);
+   return result;   
+}
+
+char *stb_include_file(char *filename, char *inject, char *path_to_includes, char error[256])
+{
+   size_t len;
+   char *result;
+   char *text = stb_include_load_file(filename, &len);
+   if (text == NULL) {
+      strcpy(error, "Error: couldn't load '");
+      strcat(error, filename);
+      strcat(error, "'");
+      return 0;
+   }
+   result = stb_include_string(text, inject, path_to_includes, filename, error);
+   free(text);
+   return result;
+}
+
+#if 0 // @TODO, GL_ARB_shader_language_include-style system that doesn't touch filesystem
+char *stb_include_preloaded(char *str, char *inject, char *includes[][2], char error[256])
+{
+
+}
+#endif
+
+#endif // STB_INCLUDE_IMPLEMENTATION