~ubuntu-branches/debian/sid/geany-plugins/sid

« back to all changes in this revision

Viewing changes to pretty-printer/src/PrettyPrinter.c

  • Committer: Package Import Robot
  • Author(s): Evgeni Golov, Evgeni Golov
  • Date: 2011-11-17 20:03:24 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20111117200324-8qmu6tuwjtfpv3n7
Tags: 0.21.1-1
[ Evgeni Golov ]
* [f4007f2] Imported Upstream version 0.21.1
* [5ff622d] install plugins from/to /usr/lib/<arch-triplet>/geany
* [75411d7] bump build-dep to geany 0.21
* [db92155] depend on the virtual geany-abi-XX package
* [dd84769] switch to 3.0 (quilt)
* [3ab76d7] drop readme.source
* [233d44c] refresh patch against 0.21.1
* [030bec1] add lintian override for
            documentation-package-not-architecture-independent
* [aba43d7] use debhelper compat level 9

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
//======================= FUNCTIONS ====================================================================
22
22
 
 
23
//error reporting functions
 
24
static void PP_ERROR(const char* fmt, ...) G_GNUC_PRINTF(1,2);  //prints an error message
 
25
 
23
26
//xml pretty printing functions
24
27
static void putCharInBuffer(char charToAdd);                     //put a char into the new char buffer
25
 
static void putCharsInBuffer(char* charsToAdd);                  //put the chars into the new char buffer
 
28
static void putCharsInBuffer(const char* charsToAdd);            //put the chars into the new char buffer
26
29
static void putNextCharsInBuffer(int nbChars);                   //put the next nbChars of the input buffer into the new buffer
27
 
static int readWhites();                                         //read the next whites into the input buffer
28
 
static char readNextChar();                                      //read the next char into the input buffer;
29
 
static char getNextChar();                                       //returns the next char but do not increase the input buffer index (use readNextChar for that)
30
 
static char getPreviousInsertedChar();                           //returns the last inserted char into the new buffer
31
 
static gboolean isWhite(char c);                                 //check if the specified char is a white
32
 
static gboolean isLineBreak(char c);                             //check if the specified char is a new line
33
 
static gboolean isQuote(char c);                                 //check if the specified char is a quote (simple or double)
34
 
static int putNewLine();                                         //put a new line into the new char buffer with the correct number of whites (indentation)
35
 
static gboolean isInlineNodeAllowed();                           //check if it is possible to have an inline node
36
 
static void resetBackwardIndentation(gboolean resetLineBreak);   //reset the indentation for the current depth (just reset the index in fact)
 
30
static int readWhites(bool considerLineBreakAsWhite);            //read the next whites into the input buffer
 
31
static char readNextChar(void);                                  //read the next char into the input buffer;
 
32
static char getNextChar(void);                                   //returns the next char but do not increase the input buffer index (use readNextChar for that)
 
33
static char getPreviousInsertedChar(void);                       //returns the last inserted char into the new buffer
 
34
static bool isWhite(char c);                                     //check if the specified char is a white
 
35
static bool isSpace(char c);                                     //check if the specified char is a space
 
36
static bool isLineBreak(char c);                                 //check if the specified char is a new line
 
37
static bool isQuote(char c);                                     //check if the specified char is a quote (simple or double)
 
38
static int putNewLine(void);                                     //put a new line into the new char buffer with the correct number of whites (indentation)
 
39
static bool isInlineNodeAllowed(void);                           //check if it is possible to have an inline node
 
40
static bool isOnSingleLine(int skip, char stop1, char stop2);    //check if the current node data is on one line (for inlining)
 
41
static void resetBackwardIndentation(bool resetLineBreak);       //reset the indentation for the current depth (just reset the index in fact)
37
42
                                                             
38
43
//specific parsing functions                                 
39
 
static int processElements();                                    //returns the number of elements processed
40
 
static void processElementAttribute();                           //process on attribute of a node
41
 
static void processElementAttributes();                          //process all the attributes of a node
42
 
static void processHeader();                                     //process the header <?xml version="..." ?>
43
 
static void processNode();                                       //process an XML node
44
 
static void processTextNode();                                   //process a text node
45
 
static void processComment();                                    //process a comment
46
 
static void processCDATA();                                      //process a CDATA node
47
 
static void processDoctype();                                    //process a DOCTYPE node
48
 
static void processDoctypeElement();                             //process a DOCTYPE ELEMENT node
49
 
                                                             
 
44
static int processElements(void);                                //returns the number of elements processed
 
45
static void processElementAttribute(void);                       //process on attribute of a node
 
46
static void processElementAttributes(void);                      //process all the attributes of a node
 
47
static void processHeader(void);                                 //process the header <?xml version="..." ?>
 
48
static void processNode(void);                                   //process an XML node
 
49
static void processTextNode(void);                               //process a text node
 
50
static void processComment(void);                                //process a comment
 
51
static void processCDATA(void);                                  //process a CDATA node
 
52
static void processDoctype(void);                                //process a DOCTYPE node
 
53
static void processDoctypeElement(void);                         //process a DOCTYPE ELEMENT node
 
54
 
50
55
//debug function                                             
51
 
static void printError(char *msg, ...);                          //just print a message like the printf method
52
 
static void printDebugStatus();                                  //just print some variables into the console for debugging
 
56
static void printError(const char *msg, ...) G_GNUC_PRINTF(1,2); //just print a message like the printf method
 
57
static void printDebugStatus(void);                              //just print some variables into the console for debugging
53
58
 
54
59
//============================================ PRIVATE PROPERTIES ======================================
55
60
 
65
70
static int inputBufferIndex;                                      //input buffer index (position of the next char to read into the input string)
66
71
static int currentDepth;                                          //current depth (for indentation)
67
72
static char* currentNodeName;                                     //current node name
68
 
static gboolean appendIndentation;                                //if the indentation must be added (with a line break before)
69
 
static gboolean lastNodeOpen;                                     //defines if the last action was a not opening or not
 
73
static bool appendIndentation;                                //if the indentation must be added (with a line break before)
 
74
static bool lastNodeOpen;                                     //defines if the last action was a not opening or not
70
75
static PrettyPrintingOptions* options;                            //options of PrettyPrinting
71
76
 
72
77
//============================================ GENERAL FUNCTIONS =======================================
73
78
 
 
79
static void PP_ERROR(const char* fmt, ...)
 
80
{
 
81
    va_list va;
 
82
    
 
83
    va_start(va, fmt);
 
84
    vfprintf(stderr, fmt, va);
 
85
    putc('\n', stderr);
 
86
    va_end(va);
 
87
}
 
88
 
74
89
int processXMLPrettyPrinting(char** buffer, int* length, PrettyPrintingOptions* ppOptions)
75
90
{
76
91
    //empty buffer, nothing to process
79
94
    
80
95
    //initialize the variables
81
96
    result = PRETTY_PRINTING_SUCCESS;
82
 
    gboolean freeOptions = FALSE;
83
 
    if (ppOptions == NULL) { ppOptions = createDefaultPrettyPrintingOptions(); freeOptions = TRUE; }
 
97
    bool freeOptions = FALSE;
 
98
    if (ppOptions == NULL) 
 
99
    { 
 
100
        ppOptions = createDefaultPrettyPrintingOptions(); 
 
101
        freeOptions = TRUE; 
 
102
    }
 
103
    
84
104
    options = ppOptions;
85
 
    
86
105
    currentNodeName = NULL;
87
106
    appendIndentation = FALSE;
88
107
    lastNodeOpen = FALSE;
95
114
    
96
115
    xmlPrettyPrintedLength = *length;
97
116
    xmlPrettyPrinted = (char*)malloc(sizeof(char)*(*length));
98
 
    if (xmlPrettyPrinted == NULL) { g_error("Allocation error"); }
 
117
    if (xmlPrettyPrinted == NULL) { PP_ERROR("Allocation error (initialisation)"); return PRETTY_PRINTING_SYSTEM_ERROR; }
99
118
    
100
119
    //go to the first char
101
 
    readWhites();
 
120
    readWhites(TRUE);
102
121
 
103
122
    //process the pretty-printing
104
123
    processElements();
107
126
    putCharInBuffer('\0');
108
127
    
109
128
    //adjust the final size
110
 
    xmlPrettyPrinted = realloc(xmlPrettyPrinted, xmlPrettyPrintedIndex);
111
 
    if (xmlPrettyPrinted == NULL) { g_error("Allocation error"); }
 
129
    char* reallocated = (char*)realloc(xmlPrettyPrinted, xmlPrettyPrintedIndex); 
 
130
    if (reallocated == NULL) { PP_ERROR("Allocation error (reallocation size is %d)", xmlPrettyPrintedIndex); return PRETTY_PRINTING_SYSTEM_ERROR; }
 
131
    xmlPrettyPrinted = reallocated;
112
132
    
113
133
    //freeing the unused values
114
134
    if (freeOptions) { free(options); }
136
156
    return result;
137
157
}
138
158
 
139
 
PrettyPrintingOptions* createDefaultPrettyPrintingOptions()
 
159
PrettyPrintingOptions* createDefaultPrettyPrintingOptions(void)
140
160
{
141
 
    PrettyPrintingOptions* options = (PrettyPrintingOptions*)malloc(sizeof(PrettyPrintingOptions));
142
 
    if (options == NULL) 
 
161
    PrettyPrintingOptions* defaultOptions = (PrettyPrintingOptions*)malloc(sizeof(PrettyPrintingOptions));
 
162
    if (defaultOptions == NULL) 
143
163
    { 
144
 
        g_error("Unable to allocate memory for PrettyPrintingOptions");
145
 
        return NULL; 
 
164
        PP_ERROR("Unable to allocate memory for PrettyPrintingOptions");
 
165
        return NULL;
146
166
    }
147
167
    
148
 
    options->newLineChars = "\r\n";
149
 
    options->indentChar = ' ';
150
 
    options->indentLength = 2;
151
 
    options->oneLineText = TRUE;
152
 
    options->inlineText = TRUE;
153
 
    options->oneLineComment = TRUE;
154
 
    options->inlineComment = TRUE;
155
 
    options->oneLineCdata = TRUE;
156
 
    options->inlineCdata = TRUE;
157
 
    options->emptyNodeStripping = TRUE;
158
 
    options->emptyNodeStrippingSpace = TRUE;
159
 
    options->forceEmptyNodeSplit = FALSE;
160
 
    options->trimLeadingWhites = TRUE;
161
 
    options->trimTrailingWhites = TRUE;
 
168
    defaultOptions->newLineChars = "\r\n";
 
169
    defaultOptions->indentChar = ' ';
 
170
    defaultOptions->indentLength = 2;
 
171
    defaultOptions->oneLineText = FALSE;
 
172
    defaultOptions->inlineText = TRUE;
 
173
    defaultOptions->oneLineComment = FALSE;
 
174
    defaultOptions->inlineComment = TRUE;
 
175
    defaultOptions->oneLineCdata = FALSE;
 
176
    defaultOptions->inlineCdata = TRUE;
 
177
    defaultOptions->emptyNodeStripping = TRUE;
 
178
    defaultOptions->emptyNodeStrippingSpace = TRUE;
 
179
    defaultOptions->forceEmptyNodeSplit = FALSE;
 
180
    defaultOptions->trimLeadingWhites = TRUE;
 
181
    defaultOptions->trimTrailingWhites = TRUE;
 
182
    defaultOptions->alignComment = TRUE;
 
183
    defaultOptions->alignText = TRUE;
 
184
    defaultOptions->alignCdata = TRUE;
162
185
    
163
 
    return options;
 
186
    return defaultOptions;
164
187
}
165
188
 
166
189
void putNextCharsInBuffer(int nbChars)
180
203
    {
181
204
        if (charToAdd == '\0') { ++xmlPrettyPrintedLength; }
182
205
        else { xmlPrettyPrintedLength += inputBufferLength; }
183
 
        xmlPrettyPrinted = (char*)realloc(xmlPrettyPrinted, xmlPrettyPrintedLength);
184
 
        if (xmlPrettyPrinted == NULL) { g_error("Allocation error"); }
 
206
        char* reallocated = (char*)realloc(xmlPrettyPrinted, xmlPrettyPrintedLength);
 
207
        if (reallocated == NULL) { PP_ERROR("Allocation error (char was %c)", charToAdd); return; }
 
208
        xmlPrettyPrinted = reallocated;
185
209
    }
186
210
    
187
211
    //putting the char and increase the index for the next one
189
213
    ++xmlPrettyPrintedIndex;
190
214
}
191
215
 
192
 
void putCharsInBuffer(char* charsToAdd)
 
216
void putCharsInBuffer(const char* charsToAdd)
193
217
{
194
 
    int index = 0;
195
 
    while (charsToAdd[index] != '\0')
 
218
    int currentIndex = 0;
 
219
    while (charsToAdd[currentIndex] != '\0')
196
220
    {
197
 
        putCharInBuffer(charsToAdd[index]);
198
 
        ++index;
 
221
        putCharInBuffer(charsToAdd[currentIndex]);
 
222
        ++currentIndex;
199
223
    }
200
224
}
201
225
 
202
 
char getPreviousInsertedChar()
 
226
char getPreviousInsertedChar(void)
203
227
{
204
228
    return xmlPrettyPrinted[xmlPrettyPrintedIndex-1];
205
229
}
206
230
 
207
 
int putNewLine()
 
231
int putNewLine(void)
208
232
{
209
233
    putCharsInBuffer(options->newLineChars);
210
234
    int spaces = currentDepth*options->indentLength;
217
241
    return spaces;
218
242
}
219
243
 
220
 
char getNextChar()
 
244
char getNextChar(void)
221
245
{
222
246
    return inputBuffer[inputBufferIndex];
223
247
}
224
248
 
225
 
char readNextChar()
 
249
char readNextChar(void)
226
250
{   
227
251
    return inputBuffer[inputBufferIndex++];
228
252
}
229
253
 
230
 
int readWhites()
 
254
int readWhites(bool considerLineBreakAsWhite)
231
255
{
232
256
    int counter = 0;
233
 
    while(isWhite(inputBuffer[inputBufferIndex]))
 
257
    while(isWhite(inputBuffer[inputBufferIndex]) && 
 
258
          (!isLineBreak(inputBuffer[inputBufferIndex]) || 
 
259
           considerLineBreakAsWhite))
234
260
    {
235
261
        ++counter;
236
262
        ++inputBufferIndex;
239
265
    return counter;
240
266
}
241
267
 
242
 
gboolean isQuote(char c)
243
 
{
244
 
    if (c == '\'') return TRUE;
245
 
    if (c == '"') return TRUE;
246
 
    
247
 
    return FALSE;
248
 
}
249
 
 
250
 
gboolean isWhite(char c)
251
 
{
252
 
    if (c == ' ') return TRUE;
253
 
    if (c == '\t') return TRUE;
254
 
    if (c == '\r') return TRUE;
255
 
    if (c == '\n') return TRUE;
256
 
 
257
 
    return FALSE;
258
 
}
259
 
 
260
 
gboolean isLineBreak(char c)
261
 
{
262
 
    if (c == '\n') return TRUE;
263
 
    if (c == '\r') return TRUE;
264
 
    
265
 
    return FALSE;
266
 
}
267
 
 
268
 
gboolean isInlineNodeAllowed()
 
268
bool isQuote(char c)
 
269
{
 
270
    return (c == '\'' ||
 
271
            c == '\"');
 
272
}
 
273
 
 
274
bool isWhite(char c)
 
275
{
 
276
    return (isSpace(c) ||
 
277
            isLineBreak(c));
 
278
}
 
279
 
 
280
bool isSpace(char c)
 
281
{
 
282
    return (c == ' ' ||
 
283
            c == '\t');
 
284
}
 
285
 
 
286
bool isLineBreak(char c)
 
287
{
 
288
    return (c == '\n' || 
 
289
            c == '\r');
 
290
}
 
291
 
 
292
bool isInlineNodeAllowed(void)
269
293
{
270
294
    //the last action was not an opening => inline not allowed
271
295
    if (!lastNodeOpen) { return FALSE; }
274
298
    int secondChar = inputBuffer[inputBufferIndex+1]; //should be '!'
275
299
    int thirdChar = inputBuffer[inputBufferIndex+2]; //should be '-' or '['
276
300
    
277
 
    int index = inputBufferIndex+1;
 
301
    //loop through the content up to the next opening/closing node
 
302
    int currentIndex = inputBufferIndex+1;
278
303
    if (firstChar == '<')
279
304
    {
280
305
        //another node is being open ==> no inline !
281
306
        if (secondChar != '!') { return FALSE; }
282
307
        
283
 
        //okay we are in a comment node, so read until it is closed
 
308
        //okay we are in a comment/cdata node, so read until it is closed
284
309
        
285
310
        //select the closing char
286
311
        char closingComment = '-';
288
313
        
289
314
        //read until closing
290
315
        char oldChar = ' ';
291
 
        index += 3; //that by pass meanless chars
292
 
        gboolean loop = TRUE;
 
316
        currentIndex += 3; //that bypass meanless chars
 
317
        bool loop = TRUE;
293
318
        while (loop)
294
319
        {
295
 
            char current = inputBuffer[index];
296
 
            if (current == closingComment && oldChar == closingComment) { loop = FALSE; } //end of comment
 
320
            char current = inputBuffer[currentIndex];
 
321
            if (current == closingComment && oldChar == closingComment) { loop = FALSE; } //end of comment/cdata
297
322
            oldChar = current;
298
 
            ++index;
 
323
            ++currentIndex;
299
324
        }
300
325
        
301
326
        //okay now avoid blanks
302
327
        // inputBuffer[index] is now '>'
303
 
        ++index;
304
 
        while (isWhite(inputBuffer[index])) { ++index; }
 
328
        ++currentIndex;
 
329
        while (isWhite(inputBuffer[currentIndex])) { ++currentIndex; }
305
330
    }
306
331
    else
307
332
    {
308
333
        //this is a text node. Simply loop to the next '<'
309
 
        while (inputBuffer[index] != '<') { ++index; }
 
334
        while (inputBuffer[currentIndex] != '<') { ++currentIndex; }
310
335
    }
311
336
    
312
337
    //check what do we have now
313
 
    char currentChar = inputBuffer[index];
 
338
    char currentChar = inputBuffer[currentIndex];
314
339
    if (currentChar == '<')
315
340
    {
316
341
        //check if that is a closing node
317
 
        currentChar = inputBuffer[index+1];
 
342
        currentChar = inputBuffer[currentIndex+1];
318
343
        if (currentChar == '/')
319
344
        {
320
345
            //as we are in a correct XML (so far...), if the node is 
321
 
            //being directly close, the inline is allowed !!!
 
346
            //being directly closed, the inline is allowed !!!
322
347
            return TRUE;
323
348
        }
324
349
    }
327
352
    return FALSE;
328
353
}
329
354
 
330
 
void resetBackwardIndentation(gboolean resetLineBreak)
 
355
bool isOnSingleLine(int skip, char stop1, char stop2)
 
356
{
 
357
    int currentIndex = inputBufferIndex+skip; //skip the n first chars (in comment <!--)
 
358
    bool onSingleLine = TRUE;
 
359
    
 
360
    char oldChar = inputBuffer[currentIndex];
 
361
    char currentChar = inputBuffer[currentIndex+1];
 
362
    while(onSingleLine && oldChar != stop1 && currentChar != stop2)
 
363
    {
 
364
        onSingleLine = !isLineBreak(oldChar);
 
365
        
 
366
        ++currentIndex;
 
367
        oldChar = currentChar;
 
368
        currentChar = inputBuffer[currentIndex+1];
 
369
        
 
370
        /**
 
371
         * A line break inside the node has been reached. But we should check
 
372
         * if there is something before the end of the node (otherwise, there
 
373
         * are only spaces and it may be wanted to be considered as a single
 
374
         * line). //TODO externalize an option for that ?
 
375
         */
 
376
        if (!onSingleLine)
 
377
        {
 
378
            while(oldChar != stop1 && currentChar != stop2)
 
379
            {
 
380
                //okay there is something else => this is not on one line
 
381
                if (!isWhite(oldChar)) return FALSE;
 
382
              
 
383
                ++currentIndex;
 
384
                oldChar = currentChar;
 
385
                currentChar = inputBuffer[currentIndex+1];
 
386
            }
 
387
            
 
388
            //the end of the node has been reached with only whites. Then
 
389
            //the node can be considered being one single line
 
390
            return TRUE;
 
391
        }
 
392
    }
 
393
    
 
394
    return onSingleLine;
 
395
}
 
396
 
 
397
void resetBackwardIndentation(bool resetLineBreak)
331
398
{
332
399
    xmlPrettyPrintedIndex -= (currentDepth*options->indentLength);
333
400
    if (resetLineBreak) 
347
414
//-----------------------------------------------------------------------------------------------------------------------------------------
348
415
//#########################################################################################################################################
349
416
 
350
 
int processElements()
 
417
int processElements(void)
351
418
{
352
419
    int counter = 0;
353
420
    ++currentDepth;
354
 
    gboolean loop = TRUE;
 
421
    bool loop = TRUE;
355
422
    while (loop && result == PRETTY_PRINTING_SUCCESS)
356
423
    {
357
424
        //strip unused whites
358
 
        readWhites();
 
425
        readWhites(TRUE);
359
426
        
360
427
        char nextChar = getNextChar();
361
428
        if (nextChar == '\0') { return 0; } //no more data to read
364
431
        if (appendIndentation) { putNewLine(); }
365
432
        
366
433
        //always append indentation (but need to store the state)
367
 
        gboolean indentBackward = appendIndentation;
 
434
        bool indentBackward = appendIndentation;
368
435
        appendIndentation = TRUE; 
369
436
        
370
437
        //okay what do we have now ?
418
485
    return counter;
419
486
}
420
487
 
421
 
void processElementAttribute()
 
488
void processElementAttribute(void)
422
489
{
423
490
    //process the attribute name
424
491
    char nextChar = readNextChar();
446
513
    putCharInBuffer(quote);
447
514
}
448
515
 
449
 
void processElementAttributes()
 
516
void processElementAttributes(void)
450
517
{
451
518
    char current = getNextChar(); //should not be a white
452
519
    if (isWhite(current)) 
456
523
        return; 
457
524
    }
458
525
    
459
 
    gboolean loop = TRUE;
 
526
    bool loop = TRUE;
460
527
    while (loop)
461
528
    {
462
 
        readWhites(); //strip the whites
 
529
        readWhites(TRUE); //strip the whites
463
530
        
464
531
        char next = getNextChar(); //don't read the last char (processed afterwards)
465
532
        if (next == '/') { loop = FALSE; } /* end of node */
473
540
    }
474
541
}
475
542
 
476
 
void processHeader()
 
543
void processHeader(void)
477
544
{
478
545
    int firstChar = inputBuffer[inputBufferIndex]; //should be '<'
479
546
    int secondChar = inputBuffer[inputBufferIndex+1]; //must be '?'
492
559
        
493
560
        while(!isWhite(getNextChar())) { putNextCharsInBuffer(1); }
494
561
        
495
 
        readWhites();
 
562
        readWhites(TRUE);
496
563
        processElementAttributes(); 
497
564
        
498
565
        //puts the '?' and '>' chars into the new buffer
500
567
    }
501
568
}
502
569
 
503
 
void processNode()
 
570
void processNode(void)
504
571
{
505
572
    int opening = readNextChar();
506
573
    if (opening != '<') 
524
591
 
525
592
    //store the name
526
593
    char* nodeName = (char*)malloc(sizeof(char)*nodeNameLength+1);
527
 
    if (nodeName == NULL) { g_error("Allocation error"); }
 
594
    if (nodeName == NULL) { PP_ERROR("Allocation error (node name length is %d)", nodeNameLength); return ; }
528
595
    nodeName[nodeNameLength] = '\0';
529
596
    int i;
530
597
    for (i=0 ; i<nodeNameLength ; ++i)
531
598
    {
532
 
        int index = xmlPrettyPrintedIndex-nodeNameLength+i;
533
 
        nodeName[i] = xmlPrettyPrinted[index];
 
599
        int tempIndex = xmlPrettyPrintedIndex-nodeNameLength+i;
 
600
        nodeName[i] = xmlPrettyPrinted[tempIndex];
534
601
    }
535
602
    
536
603
    currentNodeName = nodeName; //set the name for using in other methods
537
604
    lastNodeOpen = TRUE;
538
605
 
539
606
    //process the attributes    
540
 
    readWhites();
 
607
    readWhites(TRUE);
541
608
    processElementAttributes();
542
609
    
543
610
    //process the end of the tag
576
643
    { 
577
644
        //the tag is just closed (maybe some content)
578
645
        putNextCharsInBuffer(1); 
579
 
        subElementsProcessed = processElements(TRUE); 
 
646
        subElementsProcessed = processElements();
580
647
    } 
581
648
    else 
582
649
    { 
638
705
    currentNodeName = NULL;
639
706
}
640
707
 
641
 
void processComment()
 
708
void processComment(void)
642
709
{
643
 
    gboolean inlineAllowed = FALSE;
 
710
    bool inlineAllowed = FALSE;
644
711
    if (options->inlineComment) { inlineAllowed = isInlineNodeAllowed(); }
 
712
    if (inlineAllowed && !options->oneLineComment) { inlineAllowed = isOnSingleLine(4, '-', '-'); }
645
713
    if (inlineAllowed) { resetBackwardIndentation(TRUE); }
646
714
    
647
715
    putNextCharsInBuffer(4); //add the chars '<!--'
648
716
    
649
717
    char oldChar = '-';
650
 
    gboolean loop = TRUE;
 
718
    bool loop = TRUE;
651
719
    while (loop)
652
720
    {
653
721
        char nextChar = readNextChar();
658
726
        
659
727
        if (!isLineBreak(nextChar)) //the comment simply continues
660
728
        {
661
 
            putCharInBuffer(nextChar);
662
 
            oldChar = nextChar;
663
 
        }
664
 
        else if (!options->oneLineComment) //oh ! there is a line break
665
 
        {
666
 
            readWhites(); //strip the whites and new line
667
 
            putNewLine(); //put a new indentation line
668
 
            oldChar = ' '; //and update the last char
 
729
            if (options->oneLineComment && isSpace(nextChar))
 
730
            {
 
731
                //removes all the unecessary spaces
 
732
                while(isSpace(getNextChar()))
 
733
                {
 
734
                    nextChar = readNextChar();
 
735
                }
 
736
                putCharInBuffer(' ');
 
737
                oldChar = ' ';
 
738
            }
 
739
            else
 
740
            {
 
741
                //comment is left untouched
 
742
                putCharInBuffer(nextChar);
 
743
                oldChar = nextChar;
 
744
            }
669
745
            
670
 
            //TODO manage relative spacing
 
746
            if (!loop && options->alignComment) //end of comment
 
747
            {
 
748
                //ensures the chars preceding the first '-' are all spaces (there are at least
 
749
                //5 spaces in front of the '-->' for the alignment with '<!--')
 
750
                bool onlySpaces = xmlPrettyPrinted[xmlPrettyPrintedIndex-3] == ' ' &&
 
751
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-4] == ' ' &&
 
752
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-5] == ' ' &&
 
753
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-6] == ' ' &&
 
754
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-7] == ' ';
 
755
                
 
756
                //if all the preceding chars are white, then go for replacement
 
757
                if (onlySpaces)
 
758
                {
 
759
                    xmlPrettyPrintedIndex -= 7; //remove indentation spaces
 
760
                    putCharsInBuffer("--"); //reset the first chars of '-->'
 
761
                }
 
762
            }
 
763
        }
 
764
        else if (!options->oneLineComment && !inlineAllowed) //oh ! there is a line break
 
765
        {
 
766
            //if the comments need to be aligned, just add 5 spaces
 
767
            if (options->alignComment) 
 
768
            {
 
769
                int read = readWhites(FALSE); //strip the whites and new line
 
770
                if (nextChar == '\r' && read == 0 && getNextChar() == '\n') //handles the \r\n return line
 
771
                {
 
772
                    readNextChar(); 
 
773
                    readWhites(FALSE);
 
774
                }
 
775
              
 
776
                putNewLine(); //put a new indentation line
 
777
                putCharsInBuffer("     "); //align with <!-- 
 
778
                oldChar = ' '; //and update the last char
 
779
            }
 
780
            else
 
781
            {
 
782
                putCharInBuffer(nextChar);
 
783
                oldChar = nextChar;
 
784
            }
671
785
        }
672
786
        else //the comments must be inlined
673
787
        {
674
 
            readWhites(); //strip the whites and add a space if needed
675
 
            if (getPreviousInsertedChar() != ' ') 
 
788
            readWhites(TRUE); //strip the whites and add a space if needed
 
789
            if (getPreviousInsertedChar() != ' ' &&
 
790
                strncmp(xmlPrettyPrinted+xmlPrettyPrintedIndex-4, "<!--", 4) != 0) //prevents adding a space at the beginning 
676
791
            { 
677
792
                putCharInBuffer(' '); 
 
793
                oldChar = ' ';
678
794
            }
679
795
        }
680
796
    }
694
810
    lastNodeOpen = FALSE;
695
811
}
696
812
 
697
 
void processTextNode()
 
813
void processTextNode(void)
698
814
{
699
815
    //checks if inline is allowed
700
 
    gboolean inlineTextAllowed = FALSE;
 
816
    bool inlineTextAllowed = FALSE;
701
817
    if (options->inlineText) { inlineTextAllowed = isInlineNodeAllowed(); }
702
 
    if (inlineTextAllowed) { resetBackwardIndentation(TRUE); } //remove previous indentation
703
 
    
 
818
    if (inlineTextAllowed && !options->oneLineText) { inlineTextAllowed = isOnSingleLine(0, '<', '/'); }
 
819
    if (inlineTextAllowed || !options->alignText) 
 
820
    { 
 
821
        resetBackwardIndentation(TRUE); //remove previous indentation
 
822
        if (!inlineTextAllowed) { putNewLine(); }
 
823
    } 
 
824
   
704
825
    //the leading whites are automatically stripped. So we re-add it
705
826
    if (!options->trimLeadingWhites)
706
827
    {
707
828
        int backwardIndex = inputBufferIndex-1;
708
 
        while (inputBuffer[backwardIndex] == ' ' || 
709
 
               inputBuffer[backwardIndex] == '\t') 
 
829
        while (isSpace(inputBuffer[backwardIndex])) 
710
830
        { 
711
831
            --backwardIndex; //backward rolling
712
832
        } 
730
850
        char nextChar = readNextChar();
731
851
        if (isLineBreak(nextChar))
732
852
        {
733
 
            readWhites();
734
853
            if (options->oneLineText)
735
854
            { 
 
855
                readWhites(TRUE);
 
856
              
736
857
                //as we can put text on one line, remove the line break 
737
858
                //and replace it by a space but only if the previous 
738
859
                //char wasn't a space
739
 
                if (getPreviousInsertedChar() != ' ') 
740
 
                { 
741
 
                    putCharInBuffer(' '); 
742
 
                }
 
860
                if (getPreviousInsertedChar() != ' ') { putCharInBuffer(' '); }
743
861
            }
744
 
            else 
 
862
            else if (options->alignText)
745
863
            {
 
864
                int read = readWhites(FALSE);
 
865
                if (nextChar == '\r' && read == 0 && getNextChar() == '\n') //handles the '\r\n'
 
866
                {
 
867
                   nextChar = readNextChar();
 
868
                   readWhites(FALSE);
 
869
                }
 
870
              
746
871
                //put a new line only if the closing tag is not reached
747
872
                if (getNextChar() != '<') 
748
873
                {   
749
874
                    putNewLine(); 
750
875
                } 
751
876
            }
 
877
            else
 
878
            {
 
879
                putCharInBuffer(nextChar);
 
880
            }
752
881
        }
753
882
        else
754
883
        {
773
902
    lastNodeOpen = FALSE;
774
903
}
775
904
 
776
 
void processCDATA()
 
905
void processCDATA(void)
777
906
{
778
 
    gboolean inlineAllowed = FALSE;
 
907
    bool inlineAllowed = FALSE;
779
908
    if (options->inlineCdata) { inlineAllowed = isInlineNodeAllowed(); }
 
909
    if (inlineAllowed && !options->oneLineCdata) { inlineAllowed = isOnSingleLine(9, ']', ']'); }
780
910
    if (inlineAllowed) { resetBackwardIndentation(TRUE); }
781
911
    
782
912
    putNextCharsInBuffer(9); //putting the '<![CDATA[' into the buffer
783
913
    
784
 
    gboolean loop = TRUE;
 
914
    bool loop = TRUE;
785
915
    char oldChar = '[';
786
916
    while(loop)
787
917
    {
791
921
        
792
922
        if (!isLineBreak(nextChar)) //the cdata simply continues
793
923
        {
794
 
            putCharInBuffer(nextChar);
795
 
            oldChar = nextChar;
796
 
        }
797
 
        else if (!options->oneLineCdata)
798
 
        {
799
 
            readWhites(); //strip the whites and new line
800
 
            putNewLine(); //put a new indentation line
801
 
            oldChar = ' '; //and update the last char
 
924
            if (options->oneLineCdata && isSpace(nextChar))
 
925
            {
 
926
                //removes all the unecessary spaces
 
927
                while(isSpace(nextChar2))
 
928
                {
 
929
                    nextChar = readNextChar();
 
930
                    nextChar2 = getNextChar();
 
931
                }
 
932
                
 
933
                putCharInBuffer(' ');
 
934
                oldChar = ' ';
 
935
            }
 
936
            else
 
937
            {
 
938
                //comment is left untouched
 
939
                putCharInBuffer(nextChar);
 
940
                oldChar = nextChar;
 
941
            }
802
942
            
803
 
            //TODO manage relative spacing
 
943
            if (!loop && options->alignCdata) //end of cdata
 
944
            {
 
945
                //ensures the chars preceding the first '-' are all spaces (there are at least
 
946
                //10 spaces in front of the ']]>' for the alignment with '<![CDATA[')
 
947
                bool onlySpaces = xmlPrettyPrinted[xmlPrettyPrintedIndex-3] == ' ' &&
 
948
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-4] == ' ' &&
 
949
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-5] == ' ' &&
 
950
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-6] == ' ' &&
 
951
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-7] == ' ' &&
 
952
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-8] == ' ' &&
 
953
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-9] == ' ' &&
 
954
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-10] == ' ' &&
 
955
                                  xmlPrettyPrinted[xmlPrettyPrintedIndex-11] == ' ';
 
956
                
 
957
                //if all the preceding chars are white, then go for replacement
 
958
                if (onlySpaces)
 
959
                {
 
960
                    xmlPrettyPrintedIndex -= 11; //remove indentation spaces
 
961
                    putCharsInBuffer("]]"); //reset the first chars of '-->'
 
962
                }
 
963
            }
 
964
        }
 
965
        else if (!options->oneLineCdata && !inlineAllowed) //line break
 
966
        {
 
967
            //if the cdata need to be aligned, just add 9 spaces
 
968
            if (options->alignCdata) 
 
969
            {
 
970
                int read = readWhites(FALSE); //strip the whites and new line
 
971
                if (nextChar == '\r' && read == 0 && getNextChar() == '\n') //handles the \r\n return line
 
972
                {
 
973
                    readNextChar(); 
 
974
                    readWhites(FALSE);
 
975
                }
 
976
              
 
977
                putNewLine(); //put a new indentation line
 
978
                putCharsInBuffer("         "); //align with <![CDATA[
 
979
                oldChar = ' '; //and update the last char
 
980
            }
 
981
            else
 
982
            {
 
983
                putCharInBuffer(nextChar);
 
984
                oldChar = nextChar;
 
985
            }
804
986
        }
805
987
        else //cdata are inlined
806
988
        {
807
 
            readWhites(); //strip the whites and add a space if necessary
808
 
            if(getPreviousInsertedChar() != ' ') { putCharInBuffer(' '); }
809
 
        }
810
 
    }
811
 
    
 
989
            readWhites(TRUE); //strip the whites and add a space if necessary
 
990
            if(getPreviousInsertedChar() != ' ' &&
 
991
               strncmp(xmlPrettyPrinted+xmlPrettyPrintedIndex-9, "<![CDATA[", 9) != 0) //prevents adding a space at the beginning 
 
992
            { 
 
993
                putCharInBuffer(' '); 
 
994
                oldChar = ' ';
 
995
            }
 
996
        }
 
997
    }
 
998
    
 
999
    //if the cdata is inline, then all the trailing spaces are removed
 
1000
    if (options->oneLineCdata)
 
1001
    {
 
1002
        xmlPrettyPrintedIndex -= 2; //because of the last ']]' inserted
 
1003
        while(isWhite(xmlPrettyPrinted[xmlPrettyPrintedIndex-1]))
 
1004
        {
 
1005
            --xmlPrettyPrintedIndex;
 
1006
        }
 
1007
        putCharsInBuffer("]]");
 
1008
    }
 
1009
    
 
1010
    //finalize the cdata
812
1011
    char lastChar = readNextChar(); //should be '>'
813
1012
    if (lastChar != '>') 
814
1013
    { 
821
1020
    
822
1021
    if (inlineAllowed) { appendIndentation = FALSE; }
823
1022
    
824
 
    //there vas no node open
 
1023
    //there was no node open
825
1024
    lastNodeOpen = FALSE;
826
1025
}
827
1026
 
828
 
void processDoctype()   
 
1027
void processDoctype(void)
829
1028
{
830
1029
    putNextCharsInBuffer(9); //put the '<!DOCTYPE' into the buffer
831
1030
    
832
 
    gboolean loop = TRUE;
 
1031
    bool loop = TRUE;
833
1032
    while(loop)
834
1033
    {
835
 
        readWhites();
 
1034
        readWhites(TRUE);
836
1035
        putCharInBuffer(' '); //only one space for the attributes
837
1036
        
838
1037
        int nextChar = readNextChar();
886
1085
    }
887
1086
}
888
1087
 
889
 
void processDoctypeElement()
 
1088
void processDoctypeElement(void)
890
1089
{
891
1090
    printError("ELEMENT is currently not supported by PrettyPrinter\n");
892
1091
    result = PRETTY_PRINTING_NOT_SUPPORTED_YET;
893
1092
}
894
1093
 
895
 
void printError(char *msg, ...) 
 
1094
void printError(const char *msg, ...)
896
1095
{
897
1096
    va_list va;
898
1097
    va_start(va, msg);
899
 
    g_warning(msg, va);
 
1098
    #ifdef HAVE_GLIB
 
1099
    g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, msg, va);
 
1100
    #else
 
1101
    vfprintf(stderr, msg, va);
 
1102
    putc('\n', stderr);
 
1103
    #endif
900
1104
    va_end(va);
901
 
    
902
 
    //TODO also do a fprintf on stderr ?
903
 
    
 
1105
 
904
1106
    printDebugStatus();
905
 
 
1107
}
906
1108
 
907
 
void printDebugStatus()
 
1109
void printDebugStatus(void)
908
1110
{
 
1111
    #ifdef HAVE_GLIB
909
1112
    g_debug("\n===== INPUT =====\n%s\n=================\ninputLength = %d\ninputIndex = %d\noutputLength = %d\noutputIndex = %d\n", 
910
1113
            inputBuffer, 
911
1114
            inputBufferLength, 
912
1115
            inputBufferIndex,
913
1116
            xmlPrettyPrintedLength,
914
1117
            xmlPrettyPrintedIndex);
 
1118
    #else
 
1119
    PP_ERROR("\n===== INPUT =====\n%s\n=================\ninputLength = %d\ninputIndex = %d\noutputLength = %d\noutputIndex = %d\n", 
 
1120
            inputBuffer, 
 
1121
            inputBufferLength, 
 
1122
            inputBufferIndex,
 
1123
            xmlPrettyPrintedLength,
 
1124
            xmlPrettyPrintedIndex);
 
1125
    #endif
915
1126
}