00001 /* 00002 * ani-parser/strtreedump.cc 00003 * 00004 * Expandable, indent-capable, alloc-ahead string buffer for tree 00005 * node dump. 00006 * This is part of the AniVision project. 00007 * 00008 * Copyright (c) 2003 by Wolfgang Wieser (wwieser@gmx.de) 00009 * 00010 * This file may be distributed and/or modified under the terms of the 00011 * GNU General Public License version 2 as published by the Free Software 00012 * Foundation. 00013 * 00014 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00015 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00016 * 00017 */ 00018 00019 #include "strtreedump.h" 00020 00021 00022 void StringTreeDump::Entry::RemoveEnd(char c) 00023 { 00024 size_t len=str.length(); 00025 if(len>0 && str[len-1]==c) 00026 { str.trunc(len-1); } 00027 else 00028 { 00029 //fprintf(stderr,"Warning: Attempt to remove `%c' from tree dump but " 00030 // "`%c' is last char.\n",c,len ? str[len-1] : '\0'); 00031 } 00032 } 00033 00034 //------------------------------------------------------------------------------ 00035 00036 void StringTreeDump::append(const TLString &s) 00037 { 00038 Entry *ent=ents.last(); 00039 if(!ent || ent->indent!=curr_indent) 00040 { 00041 // Need new entry. 00042 // First, tighten previous entry. 00043 if(ents.last()) ents.last()->str.TightenSize(); 00044 // Alloc and queue new entry: 00045 ent=new Entry(curr_indent); 00046 ents.append(ent); 00047 } 00048 ent->append(s); 00049 indent_just_added=0; 00050 } 00051 00052 void StringTreeDump::RemoveEnd(char c) 00053 { 00054 Entry *ent=ents.last(); 00055 Assert(ent); // Otherwise we may not call this function... 00056 ent->RemoveEnd(c); 00057 } 00058 00059 00060 size_t StringTreeDump::write(FILE *fp,int indent_size,char indent_char) 00061 { 00062 size_t totbytes=0; 00063 int cpos=0; // current position 00064 00065 // One string to hold a line in the dump (temp): 00066 TLString tmp; 00067 00068 Entry *ent=ents.first(); 00069 if(ent) for(const char *ent_str=ent->str.str();;) 00070 { 00071 // One loop per line. 00072 // First, find the text: 00073 const char *add_start=ent_str; 00074 for(; *ent_str; ent_str++) 00075 { 00076 if(*ent_str=='\n') break; 00077 } 00078 const char *add_end=ent_str; 00079 bool was_nl=0; 00080 if(*ent_str=='\n') 00081 { was_nl=1; ++ent_str; } 00082 00083 if(add_end<=add_start) 00084 { 00085 if(was_nl) 00086 { 00087 //fprintf(stderr,"<->\n"); 00088 Assert(tmp.length()==0); 00089 fprintf(fp,"\n"); 00090 ++totbytes; 00091 } 00092 else 00093 { 00094 Assert(*ent_str=='\0'); 00095 ent=ent->next; 00096 if(!ent) goto done; 00097 ent_str=ent->str.str(); 00098 } 00099 continue; 00100 } 00101 00102 // Add indention: 00103 int add_indent=ent->indent-cpos; 00104 if(add_indent) 00105 { 00106 int tot_indent=add_indent*indent_size; 00107 char itmp[tot_indent+1]; 00108 for(int i=0; i<tot_indent; i++) 00109 { itmp[i]=indent_char; } 00110 itmp[tot_indent]='\0'; 00111 tmp.append(itmp); 00112 } 00113 00114 // Then, add text: 00115 tmp.append(add_start,add_end-add_start); 00116 00117 // Write it: 00118 fprintf(fp,"%s\n",tmp.str()); 00119 totbytes+=tmp.length()+1; // +1 for the newline 00120 tmp.trunc(0,/*do_not_shrink=*/1); 00121 } 00122 00123 done:; 00124 return(totbytes); 00125 } 00126 00127 00128 StringTreeDump::StringTreeDump() : 00129 ents() 00130 { 00131 curr_indent=0; 00132 indent_just_added=0; 00133 } 00134 00135 StringTreeDump::~StringTreeDump() 00136 { 00137 while(!ents.IsEmpty()) 00138 { delete ents.PopLast(); } 00139 }