123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358 |
- #include "yaml_private.h"
- /*
- * Flush the buffer if needed.
- */
- #define FLUSH(emitter) \
- ((emitter->buffer.pointer+5 < emitter->buffer.end) \
- || yaml_emitter_flush(emitter))
- /*
- * Put a character to the output buffer.
- */
- #define PUT(emitter,value) \
- (FLUSH(emitter) \
- && (*(emitter->buffer.pointer++) = (yaml_char_t)(value), \
- emitter->column++, \
- 1))
- /*
- * Put a line break to the output buffer.
- */
- #define PUT_BREAK(emitter) \
- (FLUSH(emitter) \
- && ((emitter->line_break == YAML_CR_BREAK ? \
- (*(emitter->buffer.pointer++) = (yaml_char_t) '\r') : \
- emitter->line_break == YAML_LN_BREAK ? \
- (*(emitter->buffer.pointer++) = (yaml_char_t) '\n') : \
- emitter->line_break == YAML_CRLN_BREAK ? \
- (*(emitter->buffer.pointer++) = (yaml_char_t) '\r', \
- *(emitter->buffer.pointer++) = (yaml_char_t) '\n') : 0), \
- emitter->column = 0, \
- emitter->line ++, \
- 1))
- /*
- * Copy a character from a string into buffer.
- */
- #define WRITE(emitter,string) \
- (FLUSH(emitter) \
- && (COPY(emitter->buffer,string), \
- emitter->column ++, \
- 1))
- /*
- * Copy a line break character from a string into buffer.
- */
- #define WRITE_BREAK(emitter,string) \
- (FLUSH(emitter) \
- && (CHECK(string,'\n') ? \
- (PUT_BREAK(emitter), \
- string.pointer ++, \
- 1) : \
- (COPY(emitter->buffer,string), \
- emitter->column = 0, \
- emitter->line ++, \
- 1)))
- /*
- * API functions.
- */
- YAML_DECLARE(int)
- yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event);
- /*
- * Utility functions.
- */
- static int
- yaml_emitter_set_emitter_error(yaml_emitter_t *emitter, const char *problem);
- static int
- yaml_emitter_need_more_events(yaml_emitter_t *emitter);
- static int
- yaml_emitter_append_tag_directive(yaml_emitter_t *emitter,
- yaml_tag_directive_t value, int allow_duplicates);
- static int
- yaml_emitter_increase_indent(yaml_emitter_t *emitter,
- int flow, int indentless);
- /*
- * State functions.
- */
- static int
- yaml_emitter_state_machine(yaml_emitter_t *emitter, yaml_event_t *event);
- static int
- yaml_emitter_emit_stream_start(yaml_emitter_t *emitter,
- yaml_event_t *event);
- static int
- yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
- yaml_event_t *event, int first);
- static int
- yaml_emitter_emit_document_content(yaml_emitter_t *emitter,
- yaml_event_t *event);
- static int
- yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
- yaml_event_t *event);
- static int
- yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter,
- yaml_event_t *event, int first);
- static int
- yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter,
- yaml_event_t *event, int first);
- static int
- yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter,
- yaml_event_t *event, int simple);
- static int
- yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter,
- yaml_event_t *event, int first);
- static int
- yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter,
- yaml_event_t *event, int first);
- static int
- yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter,
- yaml_event_t *event, int simple);
- static int
- yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event,
- int root, int sequence, int mapping, int simple_key);
- static int
- yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event);
- static int
- yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event);
- static int
- yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event);
- static int
- yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event);
- /*
- * Checkers.
- */
- static int
- yaml_emitter_check_empty_document(yaml_emitter_t *emitter);
- static int
- yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter);
- static int
- yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter);
- static int
- yaml_emitter_check_simple_key(yaml_emitter_t *emitter);
- static int
- yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event);
- /*
- * Processors.
- */
- static int
- yaml_emitter_process_anchor(yaml_emitter_t *emitter);
- static int
- yaml_emitter_process_tag(yaml_emitter_t *emitter);
- static int
- yaml_emitter_process_scalar(yaml_emitter_t *emitter);
- /*
- * Analyzers.
- */
- static int
- yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter,
- yaml_version_directive_t version_directive);
- static int
- yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter,
- yaml_tag_directive_t tag_directive);
- static int
- yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
- yaml_char_t *anchor, int alias);
- static int
- yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
- yaml_char_t *tag);
- static int
- yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length);
- static int
- yaml_emitter_analyze_event(yaml_emitter_t *emitter,
- yaml_event_t *event);
- /*
- * Writers.
- */
- static int
- yaml_emitter_write_bom(yaml_emitter_t *emitter);
- static int
- yaml_emitter_write_indent(yaml_emitter_t *emitter);
- static int
- yaml_emitter_write_indicator(yaml_emitter_t *emitter,
- const char *indicator, int need_whitespace,
- int is_whitespace, int is_indention);
- static int
- yaml_emitter_write_anchor(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length);
- static int
- yaml_emitter_write_tag_handle(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length);
- static int
- yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int need_whitespace);
- static int
- yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks);
- static int
- yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks);
- static int
- yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks);
- static int
- yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
- yaml_string_t string);
- static int
- yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length);
- static int
- yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length);
- /*
- * Set an emitter error and return 0.
- */
- static int
- yaml_emitter_set_emitter_error(yaml_emitter_t *emitter, const char *problem)
- {
- emitter->error = YAML_EMITTER_ERROR;
- emitter->problem = problem;
- return 0;
- }
- /*
- * Emit an event.
- */
- YAML_DECLARE(int)
- yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event)
- {
- if (!ENQUEUE(emitter, emitter->events, *event)) {
- yaml_event_delete(event);
- return 0;
- }
- while (!yaml_emitter_need_more_events(emitter)) {
- if (!yaml_emitter_analyze_event(emitter, emitter->events.head))
- return 0;
- if (!yaml_emitter_state_machine(emitter, emitter->events.head))
- return 0;
- yaml_event_delete(&DEQUEUE(emitter, emitter->events));
- }
- return 1;
- }
- /*
- * Check if we need to accumulate more events before emitting.
- *
- * We accumulate extra
- * - 1 event for DOCUMENT-START
- * - 2 events for SEQUENCE-START
- * - 3 events for MAPPING-START
- */
- static int
- yaml_emitter_need_more_events(yaml_emitter_t *emitter)
- {
- int level = 0;
- int accumulate = 0;
- yaml_event_t *event;
- if (QUEUE_EMPTY(emitter, emitter->events))
- return 1;
- switch (emitter->events.head->type) {
- case YAML_DOCUMENT_START_EVENT:
- accumulate = 1;
- break;
- case YAML_SEQUENCE_START_EVENT:
- accumulate = 2;
- break;
- case YAML_MAPPING_START_EVENT:
- accumulate = 3;
- break;
- default:
- return 0;
- }
- if (emitter->events.tail - emitter->events.head > accumulate)
- return 0;
- for (event = emitter->events.head; event != emitter->events.tail; event ++) {
- switch (event->type) {
- case YAML_STREAM_START_EVENT:
- case YAML_DOCUMENT_START_EVENT:
- case YAML_SEQUENCE_START_EVENT:
- case YAML_MAPPING_START_EVENT:
- level += 1;
- break;
- case YAML_STREAM_END_EVENT:
- case YAML_DOCUMENT_END_EVENT:
- case YAML_SEQUENCE_END_EVENT:
- case YAML_MAPPING_END_EVENT:
- level -= 1;
- break;
- default:
- break;
- }
- if (!level)
- return 0;
- }
- return 1;
- }
- /*
- * Append a directive to the directives stack.
- */
- static int
- yaml_emitter_append_tag_directive(yaml_emitter_t *emitter,
- yaml_tag_directive_t value, int allow_duplicates)
- {
- yaml_tag_directive_t *tag_directive;
- yaml_tag_directive_t copy = { NULL, NULL };
- for (tag_directive = emitter->tag_directives.start;
- tag_directive != emitter->tag_directives.top; tag_directive ++) {
- if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) {
- if (allow_duplicates)
- return 1;
- return yaml_emitter_set_emitter_error(emitter,
- "duplicate %TAG directive");
- }
- }
- copy.handle = yaml_strdup(value.handle);
- copy.prefix = yaml_strdup(value.prefix);
- if (!copy.handle || !copy.prefix) {
- emitter->error = YAML_MEMORY_ERROR;
- goto error;
- }
- if (!PUSH(emitter, emitter->tag_directives, copy))
- goto error;
- return 1;
- error:
- yaml_free(copy.handle);
- yaml_free(copy.prefix);
- return 0;
- }
- /*
- * Increase the indentation level.
- */
- static int
- yaml_emitter_increase_indent(yaml_emitter_t *emitter,
- int flow, int indentless)
- {
- if (!PUSH(emitter, emitter->indents, emitter->indent))
- return 0;
- if (emitter->indent < 0) {
- emitter->indent = flow ? emitter->best_indent : 0;
- }
- else if (!indentless) {
- emitter->indent += emitter->best_indent;
- }
- return 1;
- }
- /*
- * State dispatcher.
- */
- static int
- yaml_emitter_state_machine(yaml_emitter_t *emitter, yaml_event_t *event)
- {
- switch (emitter->state)
- {
- case YAML_EMIT_STREAM_START_STATE:
- return yaml_emitter_emit_stream_start(emitter, event);
- case YAML_EMIT_FIRST_DOCUMENT_START_STATE:
- return yaml_emitter_emit_document_start(emitter, event, 1);
- case YAML_EMIT_DOCUMENT_START_STATE:
- return yaml_emitter_emit_document_start(emitter, event, 0);
- case YAML_EMIT_DOCUMENT_CONTENT_STATE:
- return yaml_emitter_emit_document_content(emitter, event);
- case YAML_EMIT_DOCUMENT_END_STATE:
- return yaml_emitter_emit_document_end(emitter, event);
- case YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
- return yaml_emitter_emit_flow_sequence_item(emitter, event, 1);
- case YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE:
- return yaml_emitter_emit_flow_sequence_item(emitter, event, 0);
- case YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
- return yaml_emitter_emit_flow_mapping_key(emitter, event, 1);
- case YAML_EMIT_FLOW_MAPPING_KEY_STATE:
- return yaml_emitter_emit_flow_mapping_key(emitter, event, 0);
- case YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
- return yaml_emitter_emit_flow_mapping_value(emitter, event, 1);
- case YAML_EMIT_FLOW_MAPPING_VALUE_STATE:
- return yaml_emitter_emit_flow_mapping_value(emitter, event, 0);
- case YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
- return yaml_emitter_emit_block_sequence_item(emitter, event, 1);
- case YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
- return yaml_emitter_emit_block_sequence_item(emitter, event, 0);
- case YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
- return yaml_emitter_emit_block_mapping_key(emitter, event, 1);
- case YAML_EMIT_BLOCK_MAPPING_KEY_STATE:
- return yaml_emitter_emit_block_mapping_key(emitter, event, 0);
- case YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
- return yaml_emitter_emit_block_mapping_value(emitter, event, 1);
- case YAML_EMIT_BLOCK_MAPPING_VALUE_STATE:
- return yaml_emitter_emit_block_mapping_value(emitter, event, 0);
- case YAML_EMIT_END_STATE:
- return yaml_emitter_set_emitter_error(emitter,
- "expected nothing after STREAM-END");
- default:
- assert(1); /* Invalid state. */
- }
- return 0;
- }
- /*
- * Expect STREAM-START.
- */
- static int
- yaml_emitter_emit_stream_start(yaml_emitter_t *emitter,
- yaml_event_t *event)
- {
- emitter->open_ended = 0;
- if (event->type == YAML_STREAM_START_EVENT)
- {
- if (!emitter->encoding) {
- emitter->encoding = event->data.stream_start.encoding;
- }
- if (!emitter->encoding) {
- emitter->encoding = YAML_UTF8_ENCODING;
- }
- if (emitter->best_indent < 2 || emitter->best_indent > 9) {
- emitter->best_indent = 2;
- }
- if (emitter->best_width >= 0
- && emitter->best_width <= emitter->best_indent*2) {
- emitter->best_width = 80;
- }
- if (emitter->best_width < 0) {
- emitter->best_width = INT_MAX;
- }
- if (!emitter->line_break) {
- emitter->line_break = YAML_LN_BREAK;
- }
- emitter->indent = -1;
- emitter->line = 0;
- emitter->column = 0;
- emitter->whitespace = 1;
- emitter->indention = 1;
- if (emitter->encoding != YAML_UTF8_ENCODING) {
- if (!yaml_emitter_write_bom(emitter))
- return 0;
- }
- emitter->state = YAML_EMIT_FIRST_DOCUMENT_START_STATE;
- return 1;
- }
- return yaml_emitter_set_emitter_error(emitter,
- "expected STREAM-START");
- }
- /*
- * Expect DOCUMENT-START or STREAM-END.
- */
- static int
- yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
- yaml_event_t *event, int first)
- {
- if (event->type == YAML_DOCUMENT_START_EVENT)
- {
- yaml_tag_directive_t default_tag_directives[] = {
- {(yaml_char_t *)"!", (yaml_char_t *)"!"},
- {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"},
- {NULL, NULL}
- };
- yaml_tag_directive_t *tag_directive;
- int implicit;
- if (event->data.document_start.version_directive) {
- if (!yaml_emitter_analyze_version_directive(emitter,
- *event->data.document_start.version_directive))
- return 0;
- }
- for (tag_directive = event->data.document_start.tag_directives.start;
- tag_directive != event->data.document_start.tag_directives.end;
- tag_directive ++) {
- if (!yaml_emitter_analyze_tag_directive(emitter, *tag_directive))
- return 0;
- if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 0))
- return 0;
- }
- for (tag_directive = default_tag_directives;
- tag_directive->handle; tag_directive ++) {
- if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 1))
- return 0;
- }
- implicit = event->data.document_start.implicit;
- if (!first || emitter->canonical) {
- implicit = 0;
- }
- if ((event->data.document_start.version_directive ||
- (event->data.document_start.tag_directives.start
- != event->data.document_start.tag_directives.end)) &&
- emitter->open_ended)
- {
- if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
- return 0;
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- emitter->open_ended = 0;
- if (event->data.document_start.version_directive) {
- implicit = 0;
- if (!yaml_emitter_write_indicator(emitter, "%YAML", 1, 0, 0))
- return 0;
- if (event->data.document_start.version_directive->minor == 1) {
- if (!yaml_emitter_write_indicator(emitter, "1.1", 1, 0, 0))
- return 0;
- }
- else {
- if (!yaml_emitter_write_indicator(emitter, "1.2", 1, 0, 0))
- return 0;
- }
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (event->data.document_start.tag_directives.start
- != event->data.document_start.tag_directives.end) {
- implicit = 0;
- for (tag_directive = event->data.document_start.tag_directives.start;
- tag_directive != event->data.document_start.tag_directives.end;
- tag_directive ++) {
- if (!yaml_emitter_write_indicator(emitter, "%TAG", 1, 0, 0))
- return 0;
- if (!yaml_emitter_write_tag_handle(emitter, tag_directive->handle,
- strlen((char *)tag_directive->handle)))
- return 0;
- if (!yaml_emitter_write_tag_content(emitter, tag_directive->prefix,
- strlen((char *)tag_directive->prefix), 1))
- return 0;
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- }
- if (yaml_emitter_check_empty_document(emitter)) {
- implicit = 0;
- }
- if (!implicit) {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- if (!yaml_emitter_write_indicator(emitter, "---", 1, 0, 0))
- return 0;
- if (emitter->canonical) {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- }
- emitter->state = YAML_EMIT_DOCUMENT_CONTENT_STATE;
- emitter->open_ended = 0;
- return 1;
- }
- else if (event->type == YAML_STREAM_END_EVENT)
- {
- /**
- * This can happen if a block scalar with trailing empty lines
- * is at the end of the stream
- */
- if (emitter->open_ended == 2)
- {
- if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
- return 0;
- emitter->open_ended = 0;
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (!yaml_emitter_flush(emitter))
- return 0;
- emitter->state = YAML_EMIT_END_STATE;
- return 1;
- }
- return yaml_emitter_set_emitter_error(emitter,
- "expected DOCUMENT-START or STREAM-END");
- }
- /*
- * Expect the root node.
- */
- static int
- yaml_emitter_emit_document_content(yaml_emitter_t *emitter,
- yaml_event_t *event)
- {
- if (!PUSH(emitter, emitter->states, YAML_EMIT_DOCUMENT_END_STATE))
- return 0;
- return yaml_emitter_emit_node(emitter, event, 1, 0, 0, 0);
- }
- /*
- * Expect DOCUMENT-END.
- */
- static int
- yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
- yaml_event_t *event)
- {
- if (event->type == YAML_DOCUMENT_END_EVENT)
- {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- if (!event->data.document_end.implicit) {
- if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
- return 0;
- emitter->open_ended = 0;
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- else if (!emitter->open_ended)
- emitter->open_ended = 1;
- if (!yaml_emitter_flush(emitter))
- return 0;
- emitter->state = YAML_EMIT_DOCUMENT_START_STATE;
- while (!STACK_EMPTY(emitter, emitter->tag_directives)) {
- yaml_tag_directive_t tag_directive = POP(emitter,
- emitter->tag_directives);
- yaml_free(tag_directive.handle);
- yaml_free(tag_directive.prefix);
- }
- return 1;
- }
- return yaml_emitter_set_emitter_error(emitter,
- "expected DOCUMENT-END");
- }
- /*
- *
- * Expect a flow item node.
- */
- static int
- yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter,
- yaml_event_t *event, int first)
- {
- if (first)
- {
- if (!yaml_emitter_write_indicator(emitter, "[", 1, 1, 0))
- return 0;
- if (!yaml_emitter_increase_indent(emitter, 1, 0))
- return 0;
- emitter->flow_level ++;
- }
- if (event->type == YAML_SEQUENCE_END_EVENT)
- {
- emitter->flow_level --;
- emitter->indent = POP(emitter, emitter->indents);
- if (emitter->canonical && !first) {
- if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
- return 0;
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (!yaml_emitter_write_indicator(emitter, "]", 0, 0, 0))
- return 0;
- emitter->state = POP(emitter, emitter->states);
- return 1;
- }
- if (!first) {
- if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
- return 0;
- }
- if (emitter->canonical || emitter->column > emitter->best_width) {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE))
- return 0;
- return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0);
- }
- /*
- * Expect a flow key node.
- */
- static int
- yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter,
- yaml_event_t *event, int first)
- {
- if (first)
- {
- if (!yaml_emitter_write_indicator(emitter, "{", 1, 1, 0))
- return 0;
- if (!yaml_emitter_increase_indent(emitter, 1, 0))
- return 0;
- emitter->flow_level ++;
- }
- if (event->type == YAML_MAPPING_END_EVENT)
- {
- emitter->flow_level --;
- emitter->indent = POP(emitter, emitter->indents);
- if (emitter->canonical && !first) {
- if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
- return 0;
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (!yaml_emitter_write_indicator(emitter, "}", 0, 0, 0))
- return 0;
- emitter->state = POP(emitter, emitter->states);
- return 1;
- }
- if (!first) {
- if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
- return 0;
- }
- if (emitter->canonical || emitter->column > emitter->best_width) {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (!emitter->canonical && yaml_emitter_check_simple_key(emitter))
- {
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE))
- return 0;
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 1);
- }
- else
- {
- if (!yaml_emitter_write_indicator(emitter, "?", 1, 0, 0))
- return 0;
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_FLOW_MAPPING_VALUE_STATE))
- return 0;
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
- }
- }
- /*
- * Expect a flow value node.
- */
- static int
- yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter,
- yaml_event_t *event, int simple)
- {
- if (simple) {
- if (!yaml_emitter_write_indicator(emitter, ":", 0, 0, 0))
- return 0;
- }
- else {
- if (emitter->canonical || emitter->column > emitter->best_width) {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- }
- if (!yaml_emitter_write_indicator(emitter, ":", 1, 0, 0))
- return 0;
- }
- if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_MAPPING_KEY_STATE))
- return 0;
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
- }
- /*
- * Expect a block item node.
- */
- static int
- yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter,
- yaml_event_t *event, int first)
- {
- if (first)
- {
- if (!yaml_emitter_increase_indent(emitter, 0,
- (emitter->mapping_context && !emitter->indention)))
- return 0;
- }
- if (event->type == YAML_SEQUENCE_END_EVENT)
- {
- emitter->indent = POP(emitter, emitter->indents);
- emitter->state = POP(emitter, emitter->states);
- return 1;
- }
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- if (!yaml_emitter_write_indicator(emitter, "-", 1, 0, 1))
- return 0;
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE))
- return 0;
- return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0);
- }
- /*
- * Expect a block key node.
- */
- static int
- yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter,
- yaml_event_t *event, int first)
- {
- if (first)
- {
- if (!yaml_emitter_increase_indent(emitter, 0, 0))
- return 0;
- }
- if (event->type == YAML_MAPPING_END_EVENT)
- {
- emitter->indent = POP(emitter, emitter->indents);
- emitter->state = POP(emitter, emitter->states);
- return 1;
- }
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- if (yaml_emitter_check_simple_key(emitter))
- {
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE))
- return 0;
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 1);
- }
- else
- {
- if (!yaml_emitter_write_indicator(emitter, "?", 1, 0, 1))
- return 0;
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_BLOCK_MAPPING_VALUE_STATE))
- return 0;
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
- }
- }
- /*
- * Expect a block value node.
- */
- static int
- yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter,
- yaml_event_t *event, int simple)
- {
- if (simple) {
- if (!yaml_emitter_write_indicator(emitter, ":", 0, 0, 0))
- return 0;
- }
- else {
- if (!yaml_emitter_write_indent(emitter))
- return 0;
- if (!yaml_emitter_write_indicator(emitter, ":", 1, 0, 1))
- return 0;
- }
- if (!PUSH(emitter, emitter->states,
- YAML_EMIT_BLOCK_MAPPING_KEY_STATE))
- return 0;
- return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
- }
- /*
- * Expect a node.
- */
- static int
- yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event,
- int root, int sequence, int mapping, int simple_key)
- {
- emitter->root_context = root;
- emitter->sequence_context = sequence;
- emitter->mapping_context = mapping;
- emitter->simple_key_context = simple_key;
- switch (event->type)
- {
- case YAML_ALIAS_EVENT:
- return yaml_emitter_emit_alias(emitter, event);
- case YAML_SCALAR_EVENT:
- return yaml_emitter_emit_scalar(emitter, event);
- case YAML_SEQUENCE_START_EVENT:
- return yaml_emitter_emit_sequence_start(emitter, event);
- case YAML_MAPPING_START_EVENT:
- return yaml_emitter_emit_mapping_start(emitter, event);
- default:
- return yaml_emitter_set_emitter_error(emitter,
- "expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS");
- }
- return 0;
- }
- /*
- * Expect ALIAS.
- */
- static int
- yaml_emitter_emit_alias(yaml_emitter_t *emitter, SHIM(yaml_event_t *event))
- {
- if (!yaml_emitter_process_anchor(emitter))
- return 0;
- if (emitter->simple_key_context)
- if (!PUT(emitter, ' ')) return 0;
- emitter->state = POP(emitter, emitter->states);
- return 1;
- }
- /*
- * Expect SCALAR.
- */
- static int
- yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event)
- {
- if (!yaml_emitter_select_scalar_style(emitter, event))
- return 0;
- if (!yaml_emitter_process_anchor(emitter))
- return 0;
- if (!yaml_emitter_process_tag(emitter))
- return 0;
- if (!yaml_emitter_increase_indent(emitter, 1, 0))
- return 0;
- if (!yaml_emitter_process_scalar(emitter))
- return 0;
- emitter->indent = POP(emitter, emitter->indents);
- emitter->state = POP(emitter, emitter->states);
- return 1;
- }
- /*
- * Expect SEQUENCE-START.
- */
- static int
- yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event)
- {
- if (!yaml_emitter_process_anchor(emitter))
- return 0;
- if (!yaml_emitter_process_tag(emitter))
- return 0;
- if (emitter->flow_level || emitter->canonical
- || event->data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE
- || yaml_emitter_check_empty_sequence(emitter)) {
- emitter->state = YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE;
- }
- else {
- emitter->state = YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE;
- }
- return 1;
- }
- /*
- * Expect MAPPING-START.
- */
- static int
- yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event)
- {
- if (!yaml_emitter_process_anchor(emitter))
- return 0;
- if (!yaml_emitter_process_tag(emitter))
- return 0;
- if (emitter->flow_level || emitter->canonical
- || event->data.mapping_start.style == YAML_FLOW_MAPPING_STYLE
- || yaml_emitter_check_empty_mapping(emitter)) {
- emitter->state = YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE;
- }
- else {
- emitter->state = YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE;
- }
- return 1;
- }
- /*
- * Check if the document content is an empty scalar.
- */
- static int
- yaml_emitter_check_empty_document(SHIM(yaml_emitter_t *emitter))
- {
- return 0;
- }
- /*
- * Check if the next events represent an empty sequence.
- */
- static int
- yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter)
- {
- if (emitter->events.tail - emitter->events.head < 2)
- return 0;
- return (emitter->events.head[0].type == YAML_SEQUENCE_START_EVENT
- && emitter->events.head[1].type == YAML_SEQUENCE_END_EVENT);
- }
- /*
- * Check if the next events represent an empty mapping.
- */
- static int
- yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter)
- {
- if (emitter->events.tail - emitter->events.head < 2)
- return 0;
- return (emitter->events.head[0].type == YAML_MAPPING_START_EVENT
- && emitter->events.head[1].type == YAML_MAPPING_END_EVENT);
- }
- /*
- * Check if the next node can be expressed as a simple key.
- */
- static int
- yaml_emitter_check_simple_key(yaml_emitter_t *emitter)
- {
- yaml_event_t *event = emitter->events.head;
- size_t length = 0;
- switch (event->type)
- {
- case YAML_ALIAS_EVENT:
- length += emitter->anchor_data.anchor_length;
- break;
- case YAML_SCALAR_EVENT:
- if (emitter->scalar_data.multiline)
- return 0;
- length += emitter->anchor_data.anchor_length
- + emitter->tag_data.handle_length
- + emitter->tag_data.suffix_length
- + emitter->scalar_data.length;
- break;
- case YAML_SEQUENCE_START_EVENT:
- if (!yaml_emitter_check_empty_sequence(emitter))
- return 0;
- length += emitter->anchor_data.anchor_length
- + emitter->tag_data.handle_length
- + emitter->tag_data.suffix_length;
- break;
- case YAML_MAPPING_START_EVENT:
- if (!yaml_emitter_check_empty_mapping(emitter))
- return 0;
- length += emitter->anchor_data.anchor_length
- + emitter->tag_data.handle_length
- + emitter->tag_data.suffix_length;
- break;
- default:
- return 0;
- }
- if (length > 128)
- return 0;
- return 1;
- }
- /*
- * Determine an acceptable scalar style.
- */
- static int
- yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event)
- {
- yaml_scalar_style_t style = event->data.scalar.style;
- int no_tag = (!emitter->tag_data.handle && !emitter->tag_data.suffix);
- if (no_tag && !event->data.scalar.plain_implicit
- && !event->data.scalar.quoted_implicit) {
- return yaml_emitter_set_emitter_error(emitter,
- "neither tag nor implicit flags are specified");
- }
- if (style == YAML_ANY_SCALAR_STYLE)
- style = YAML_PLAIN_SCALAR_STYLE;
- if (emitter->canonical)
- style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
- if (emitter->simple_key_context && emitter->scalar_data.multiline)
- style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
- if (style == YAML_PLAIN_SCALAR_STYLE)
- {
- if ((emitter->flow_level && !emitter->scalar_data.flow_plain_allowed)
- || (!emitter->flow_level && !emitter->scalar_data.block_plain_allowed))
- style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
- if (!emitter->scalar_data.length
- && (emitter->flow_level || emitter->simple_key_context))
- style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
- if (no_tag && !event->data.scalar.plain_implicit)
- style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
- }
- if (style == YAML_SINGLE_QUOTED_SCALAR_STYLE)
- {
- if (!emitter->scalar_data.single_quoted_allowed)
- style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
- }
- if (style == YAML_LITERAL_SCALAR_STYLE || style == YAML_FOLDED_SCALAR_STYLE)
- {
- if (!emitter->scalar_data.block_allowed
- || emitter->flow_level || emitter->simple_key_context)
- style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
- }
- if (no_tag && !event->data.scalar.quoted_implicit
- && style != YAML_PLAIN_SCALAR_STYLE)
- {
- emitter->tag_data.handle = (yaml_char_t *)"!";
- emitter->tag_data.handle_length = 1;
- }
- emitter->scalar_data.style = style;
- return 1;
- }
- /*
- * Write an anchor.
- */
- static int
- yaml_emitter_process_anchor(yaml_emitter_t *emitter)
- {
- if (!emitter->anchor_data.anchor)
- return 1;
- if (!yaml_emitter_write_indicator(emitter,
- (emitter->anchor_data.alias ? "*" : "&"), 1, 0, 0))
- return 0;
- return yaml_emitter_write_anchor(emitter,
- emitter->anchor_data.anchor, emitter->anchor_data.anchor_length);
- }
- /*
- * Write a tag.
- */
- static int
- yaml_emitter_process_tag(yaml_emitter_t *emitter)
- {
- if (!emitter->tag_data.handle && !emitter->tag_data.suffix)
- return 1;
- if (emitter->tag_data.handle)
- {
- if (!yaml_emitter_write_tag_handle(emitter, emitter->tag_data.handle,
- emitter->tag_data.handle_length))
- return 0;
- if (emitter->tag_data.suffix) {
- if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix,
- emitter->tag_data.suffix_length, 0))
- return 0;
- }
- }
- else
- {
- if (!yaml_emitter_write_indicator(emitter, "!<", 1, 0, 0))
- return 0;
- if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix,
- emitter->tag_data.suffix_length, 0))
- return 0;
- if (!yaml_emitter_write_indicator(emitter, ">", 0, 0, 0))
- return 0;
- }
- return 1;
- }
- /*
- * Write a scalar.
- */
- static int
- yaml_emitter_process_scalar(yaml_emitter_t *emitter)
- {
- switch (emitter->scalar_data.style)
- {
- case YAML_PLAIN_SCALAR_STYLE:
- return yaml_emitter_write_plain_scalar(emitter,
- emitter->scalar_data.value, emitter->scalar_data.length,
- !emitter->simple_key_context);
- case YAML_SINGLE_QUOTED_SCALAR_STYLE:
- return yaml_emitter_write_single_quoted_scalar(emitter,
- emitter->scalar_data.value, emitter->scalar_data.length,
- !emitter->simple_key_context);
- case YAML_DOUBLE_QUOTED_SCALAR_STYLE:
- return yaml_emitter_write_double_quoted_scalar(emitter,
- emitter->scalar_data.value, emitter->scalar_data.length,
- !emitter->simple_key_context);
- case YAML_LITERAL_SCALAR_STYLE:
- return yaml_emitter_write_literal_scalar(emitter,
- emitter->scalar_data.value, emitter->scalar_data.length);
- case YAML_FOLDED_SCALAR_STYLE:
- return yaml_emitter_write_folded_scalar(emitter,
- emitter->scalar_data.value, emitter->scalar_data.length);
- default:
- assert(1); /* Impossible. */
- }
- return 0;
- }
- /*
- * Check if a %YAML directive is valid.
- */
- static int
- yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter,
- yaml_version_directive_t version_directive)
- {
- if (version_directive.major != 1 || (
- version_directive.minor != 1
- && version_directive.minor != 2
- )) {
- return yaml_emitter_set_emitter_error(emitter,
- "incompatible %YAML directive");
- }
- return 1;
- }
- /*
- * Check if a %TAG directive is valid.
- */
- static int
- yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter,
- yaml_tag_directive_t tag_directive)
- {
- yaml_string_t handle;
- yaml_string_t prefix;
- size_t handle_length;
- size_t prefix_length;
- handle_length = strlen((char *)tag_directive.handle);
- prefix_length = strlen((char *)tag_directive.prefix);
- STRING_ASSIGN(handle, tag_directive.handle, handle_length);
- STRING_ASSIGN(prefix, tag_directive.prefix, prefix_length);
- if (handle.start == handle.end) {
- return yaml_emitter_set_emitter_error(emitter,
- "tag handle must not be empty");
- }
- if (handle.start[0] != '!') {
- return yaml_emitter_set_emitter_error(emitter,
- "tag handle must start with '!'");
- }
- if (handle.end[-1] != '!') {
- return yaml_emitter_set_emitter_error(emitter,
- "tag handle must end with '!'");
- }
- handle.pointer ++;
- while (handle.pointer < handle.end-1) {
- if (!IS_ALPHA(handle)) {
- return yaml_emitter_set_emitter_error(emitter,
- "tag handle must contain alphanumerical characters only");
- }
- MOVE(handle);
- }
- if (prefix.start == prefix.end) {
- return yaml_emitter_set_emitter_error(emitter,
- "tag prefix must not be empty");
- }
- return 1;
- }
- /*
- * Check if an anchor is valid.
- */
- static int
- yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
- yaml_char_t *anchor, int alias)
- {
- size_t anchor_length;
- yaml_string_t string;
- anchor_length = strlen((char *)anchor);
- STRING_ASSIGN(string, anchor, anchor_length);
- if (string.start == string.end) {
- return yaml_emitter_set_emitter_error(emitter, alias ?
- "alias value must not be empty" :
- "anchor value must not be empty");
- }
- while (string.pointer != string.end) {
- if (!IS_ALPHA(string)) {
- return yaml_emitter_set_emitter_error(emitter, alias ?
- "alias value must contain alphanumerical characters only" :
- "anchor value must contain alphanumerical characters only");
- }
- MOVE(string);
- }
- emitter->anchor_data.anchor = string.start;
- emitter->anchor_data.anchor_length = string.end - string.start;
- emitter->anchor_data.alias = alias;
- return 1;
- }
- /*
- * Check if a tag is valid.
- */
- static int
- yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
- yaml_char_t *tag)
- {
- size_t tag_length;
- yaml_string_t string;
- yaml_tag_directive_t *tag_directive;
- tag_length = strlen((char *)tag);
- STRING_ASSIGN(string, tag, tag_length);
- if (string.start == string.end) {
- return yaml_emitter_set_emitter_error(emitter,
- "tag value must not be empty");
- }
- for (tag_directive = emitter->tag_directives.start;
- tag_directive != emitter->tag_directives.top; tag_directive ++) {
- size_t prefix_length = strlen((char *)tag_directive->prefix);
- if (prefix_length < (size_t)(string.end - string.start)
- && strncmp((char *)tag_directive->prefix, (char *)string.start,
- prefix_length) == 0)
- {
- emitter->tag_data.handle = tag_directive->handle;
- emitter->tag_data.handle_length =
- strlen((char *)tag_directive->handle);
- emitter->tag_data.suffix = string.start + prefix_length;
- emitter->tag_data.suffix_length =
- (string.end - string.start) - prefix_length;
- return 1;
- }
- }
- emitter->tag_data.suffix = string.start;
- emitter->tag_data.suffix_length = string.end - string.start;
- return 1;
- }
- /*
- * Check if a scalar is valid.
- */
- static int
- yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length)
- {
- yaml_string_t string;
- int block_indicators = 0;
- int flow_indicators = 0;
- int line_breaks = 0;
- int special_characters = 0;
- int leading_space = 0;
- int leading_break = 0;
- int trailing_space = 0;
- int trailing_break = 0;
- int break_space = 0;
- int space_break = 0;
- int preceded_by_whitespace = 0;
- int followed_by_whitespace = 0;
- int previous_space = 0;
- int previous_break = 0;
- STRING_ASSIGN(string, value, length);
- emitter->scalar_data.value = value;
- emitter->scalar_data.length = length;
- if (string.start == string.end)
- {
- emitter->scalar_data.multiline = 0;
- emitter->scalar_data.flow_plain_allowed = 0;
- emitter->scalar_data.block_plain_allowed = 1;
- emitter->scalar_data.single_quoted_allowed = 1;
- emitter->scalar_data.block_allowed = 0;
- return 1;
- }
- if ((CHECK_AT(string, '-', 0)
- && CHECK_AT(string, '-', 1)
- && CHECK_AT(string, '-', 2))
- || (CHECK_AT(string, '.', 0)
- && CHECK_AT(string, '.', 1)
- && CHECK_AT(string, '.', 2))) {
- block_indicators = 1;
- flow_indicators = 1;
- }
- preceded_by_whitespace = 1;
- followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
- while (string.pointer != string.end)
- {
- if (string.start == string.pointer)
- {
- if (CHECK(string, '#') || CHECK(string, ',')
- || CHECK(string, '[') || CHECK(string, ']')
- || CHECK(string, '{') || CHECK(string, '}')
- || CHECK(string, '&') || CHECK(string, '*')
- || CHECK(string, '!') || CHECK(string, '|')
- || CHECK(string, '>') || CHECK(string, '\'')
- || CHECK(string, '"') || CHECK(string, '%')
- || CHECK(string, '@') || CHECK(string, '`')) {
- flow_indicators = 1;
- block_indicators = 1;
- }
- if (CHECK(string, '?') || CHECK(string, ':')) {
- flow_indicators = 1;
- if (followed_by_whitespace) {
- block_indicators = 1;
- }
- }
- if (CHECK(string, '-') && followed_by_whitespace) {
- flow_indicators = 1;
- block_indicators = 1;
- }
- }
- else
- {
- if (CHECK(string, ',') || CHECK(string, '?')
- || CHECK(string, '[') || CHECK(string, ']')
- || CHECK(string, '{') || CHECK(string, '}')) {
- flow_indicators = 1;
- }
- if (CHECK(string, ':')) {
- flow_indicators = 1;
- if (followed_by_whitespace) {
- block_indicators = 1;
- }
- }
- if (CHECK(string, '#') && preceded_by_whitespace) {
- flow_indicators = 1;
- block_indicators = 1;
- }
- }
- if (!IS_PRINTABLE(string)
- || (!IS_ASCII(string) && !emitter->unicode)) {
- special_characters = 1;
- }
- if (IS_BREAK(string)) {
- line_breaks = 1;
- }
- if (IS_SPACE(string))
- {
- if (string.start == string.pointer) {
- leading_space = 1;
- }
- if (string.pointer+WIDTH(string) == string.end) {
- trailing_space = 1;
- }
- if (previous_break) {
- break_space = 1;
- }
- previous_space = 1;
- previous_break = 0;
- }
- else if (IS_BREAK(string))
- {
- if (string.start == string.pointer) {
- leading_break = 1;
- }
- if (string.pointer+WIDTH(string) == string.end) {
- trailing_break = 1;
- }
- if (previous_space) {
- space_break = 1;
- }
- previous_space = 0;
- previous_break = 1;
- }
- else
- {
- previous_space = 0;
- previous_break = 0;
- }
- preceded_by_whitespace = IS_BLANKZ(string);
- MOVE(string);
- if (string.pointer != string.end) {
- followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
- }
- }
- emitter->scalar_data.multiline = line_breaks;
- emitter->scalar_data.flow_plain_allowed = 1;
- emitter->scalar_data.block_plain_allowed = 1;
- emitter->scalar_data.single_quoted_allowed = 1;
- emitter->scalar_data.block_allowed = 1;
- if (leading_space || leading_break || trailing_space || trailing_break) {
- emitter->scalar_data.flow_plain_allowed = 0;
- emitter->scalar_data.block_plain_allowed = 0;
- }
- if (trailing_space) {
- emitter->scalar_data.block_allowed = 0;
- }
- if (break_space) {
- emitter->scalar_data.flow_plain_allowed = 0;
- emitter->scalar_data.block_plain_allowed = 0;
- emitter->scalar_data.single_quoted_allowed = 0;
- }
- if (space_break || special_characters) {
- emitter->scalar_data.flow_plain_allowed = 0;
- emitter->scalar_data.block_plain_allowed = 0;
- emitter->scalar_data.single_quoted_allowed = 0;
- emitter->scalar_data.block_allowed = 0;
- }
- if (line_breaks) {
- emitter->scalar_data.flow_plain_allowed = 0;
- emitter->scalar_data.block_plain_allowed = 0;
- }
- if (flow_indicators) {
- emitter->scalar_data.flow_plain_allowed = 0;
- }
- if (block_indicators) {
- emitter->scalar_data.block_plain_allowed = 0;
- }
- return 1;
- }
- /*
- * Check if the event data is valid.
- */
- static int
- yaml_emitter_analyze_event(yaml_emitter_t *emitter,
- yaml_event_t *event)
- {
- emitter->anchor_data.anchor = NULL;
- emitter->anchor_data.anchor_length = 0;
- emitter->tag_data.handle = NULL;
- emitter->tag_data.handle_length = 0;
- emitter->tag_data.suffix = NULL;
- emitter->tag_data.suffix_length = 0;
- emitter->scalar_data.value = NULL;
- emitter->scalar_data.length = 0;
- switch (event->type)
- {
- case YAML_ALIAS_EVENT:
- if (!yaml_emitter_analyze_anchor(emitter,
- event->data.alias.anchor, 1))
- return 0;
- return 1;
- case YAML_SCALAR_EVENT:
- if (event->data.scalar.anchor) {
- if (!yaml_emitter_analyze_anchor(emitter,
- event->data.scalar.anchor, 0))
- return 0;
- }
- if (event->data.scalar.tag && (emitter->canonical ||
- (!event->data.scalar.plain_implicit
- && !event->data.scalar.quoted_implicit))) {
- if (!yaml_emitter_analyze_tag(emitter, event->data.scalar.tag))
- return 0;
- }
- if (!yaml_emitter_analyze_scalar(emitter,
- event->data.scalar.value, event->data.scalar.length))
- return 0;
- return 1;
- case YAML_SEQUENCE_START_EVENT:
- if (event->data.sequence_start.anchor) {
- if (!yaml_emitter_analyze_anchor(emitter,
- event->data.sequence_start.anchor, 0))
- return 0;
- }
- if (event->data.sequence_start.tag && (emitter->canonical ||
- !event->data.sequence_start.implicit)) {
- if (!yaml_emitter_analyze_tag(emitter,
- event->data.sequence_start.tag))
- return 0;
- }
- return 1;
- case YAML_MAPPING_START_EVENT:
- if (event->data.mapping_start.anchor) {
- if (!yaml_emitter_analyze_anchor(emitter,
- event->data.mapping_start.anchor, 0))
- return 0;
- }
- if (event->data.mapping_start.tag && (emitter->canonical ||
- !event->data.mapping_start.implicit)) {
- if (!yaml_emitter_analyze_tag(emitter,
- event->data.mapping_start.tag))
- return 0;
- }
- return 1;
- default:
- return 1;
- }
- }
- /*
- * Write the BOM character.
- */
- static int
- yaml_emitter_write_bom(yaml_emitter_t *emitter)
- {
- if (!FLUSH(emitter)) return 0;
- *(emitter->buffer.pointer++) = (yaml_char_t) '\xEF';
- *(emitter->buffer.pointer++) = (yaml_char_t) '\xBB';
- *(emitter->buffer.pointer++) = (yaml_char_t) '\xBF';
- return 1;
- }
- static int
- yaml_emitter_write_indent(yaml_emitter_t *emitter)
- {
- int indent = (emitter->indent >= 0) ? emitter->indent : 0;
- if (!emitter->indention || emitter->column > indent
- || (emitter->column == indent && !emitter->whitespace)) {
- if (!PUT_BREAK(emitter)) return 0;
- }
- while (emitter->column < indent) {
- if (!PUT(emitter, ' ')) return 0;
- }
- emitter->whitespace = 1;
- emitter->indention = 1;
- return 1;
- }
- static int
- yaml_emitter_write_indicator(yaml_emitter_t *emitter,
- const char *indicator, int need_whitespace,
- int is_whitespace, int is_indention)
- {
- size_t indicator_length;
- yaml_string_t string;
- indicator_length = strlen(indicator);
- STRING_ASSIGN(string, (yaml_char_t *)indicator, indicator_length);
- if (need_whitespace && !emitter->whitespace) {
- if (!PUT(emitter, ' ')) return 0;
- }
- while (string.pointer != string.end) {
- if (!WRITE(emitter, string)) return 0;
- }
- emitter->whitespace = is_whitespace;
- emitter->indention = (emitter->indention && is_indention);
- return 1;
- }
- static int
- yaml_emitter_write_anchor(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length)
- {
- yaml_string_t string;
- STRING_ASSIGN(string, value, length);
- while (string.pointer != string.end) {
- if (!WRITE(emitter, string)) return 0;
- }
- emitter->whitespace = 0;
- emitter->indention = 0;
- return 1;
- }
- static int
- yaml_emitter_write_tag_handle(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length)
- {
- yaml_string_t string;
- STRING_ASSIGN(string, value, length);
- if (!emitter->whitespace) {
- if (!PUT(emitter, ' ')) return 0;
- }
- while (string.pointer != string.end) {
- if (!WRITE(emitter, string)) return 0;
- }
- emitter->whitespace = 0;
- emitter->indention = 0;
- return 1;
- }
- static int
- yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length,
- int need_whitespace)
- {
- yaml_string_t string;
- STRING_ASSIGN(string, value, length);
- if (need_whitespace && !emitter->whitespace) {
- if (!PUT(emitter, ' ')) return 0;
- }
- while (string.pointer != string.end) {
- if (IS_ALPHA(string)
- || CHECK(string, ';') || CHECK(string, '/')
- || CHECK(string, '?') || CHECK(string, ':')
- || CHECK(string, '@') || CHECK(string, '&')
- || CHECK(string, '=') || CHECK(string, '+')
- || CHECK(string, '$') || CHECK(string, ',')
- || CHECK(string, '_') || CHECK(string, '.')
- || CHECK(string, '~') || CHECK(string, '*')
- || CHECK(string, '\'') || CHECK(string, '(')
- || CHECK(string, ')') || CHECK(string, '[')
- || CHECK(string, ']')) {
- if (!WRITE(emitter, string)) return 0;
- }
- else {
- int width = WIDTH(string);
- unsigned int value;
- while (width --) {
- value = *(string.pointer++);
- if (!PUT(emitter, '%')) return 0;
- if (!PUT(emitter, (value >> 4)
- + ((value >> 4) < 10 ? '0' : 'A' - 10)))
- return 0;
- if (!PUT(emitter, (value & 0x0F)
- + ((value & 0x0F) < 10 ? '0' : 'A' - 10)))
- return 0;
- }
- }
- }
- emitter->whitespace = 0;
- emitter->indention = 0;
- return 1;
- }
- static int
- yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks)
- {
- yaml_string_t string;
- int spaces = 0;
- int breaks = 0;
- STRING_ASSIGN(string, value, length);
- /**
- * Avoid trailing spaces for empty values in block mode.
- * In flow mode, we still want the space to prevent ambiguous things
- * like {a:}.
- * Currently, the emitter forbids any plain empty scalar in flow mode
- * (e.g. it outputs {a: ''} instead), so emitter->flow_level will
- * never be true here.
- * But if the emitter is ever changed to allow emitting empty values,
- * the check for flow_level is already here.
- */
- if (!emitter->whitespace && (length || emitter->flow_level)) {
- if (!PUT(emitter, ' ')) return 0;
- }
- while (string.pointer != string.end)
- {
- if (IS_SPACE(string))
- {
- if (allow_breaks && !spaces
- && emitter->column > emitter->best_width
- && !IS_SPACE_AT(string, 1)) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- MOVE(string);
- }
- else {
- if (!WRITE(emitter, string)) return 0;
- }
- spaces = 1;
- }
- else if (IS_BREAK(string))
- {
- if (!breaks && CHECK(string, '\n')) {
- if (!PUT_BREAK(emitter)) return 0;
- }
- if (!WRITE_BREAK(emitter, string)) return 0;
- emitter->indention = 1;
- breaks = 1;
- }
- else
- {
- if (breaks) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- }
- if (!WRITE(emitter, string)) return 0;
- emitter->indention = 0;
- spaces = 0;
- breaks = 0;
- }
- }
- emitter->whitespace = 0;
- emitter->indention = 0;
- return 1;
- }
- static int
- yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks)
- {
- yaml_string_t string;
- int spaces = 0;
- int breaks = 0;
- STRING_ASSIGN(string, value, length);
- if (!yaml_emitter_write_indicator(emitter, "'", 1, 0, 0))
- return 0;
- while (string.pointer != string.end)
- {
- if (IS_SPACE(string))
- {
- if (allow_breaks && !spaces
- && emitter->column > emitter->best_width
- && string.pointer != string.start
- && string.pointer != string.end - 1
- && !IS_SPACE_AT(string, 1)) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- MOVE(string);
- }
- else {
- if (!WRITE(emitter, string)) return 0;
- }
- spaces = 1;
- }
- else if (IS_BREAK(string))
- {
- if (!breaks && CHECK(string, '\n')) {
- if (!PUT_BREAK(emitter)) return 0;
- }
- if (!WRITE_BREAK(emitter, string)) return 0;
- emitter->indention = 1;
- breaks = 1;
- }
- else
- {
- if (breaks) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- }
- if (CHECK(string, '\'')) {
- if (!PUT(emitter, '\'')) return 0;
- }
- if (!WRITE(emitter, string)) return 0;
- emitter->indention = 0;
- spaces = 0;
- breaks = 0;
- }
- }
- if (breaks)
- if (!yaml_emitter_write_indent(emitter)) return 0;
- if (!yaml_emitter_write_indicator(emitter, "'", 0, 0, 0))
- return 0;
- emitter->whitespace = 0;
- emitter->indention = 0;
- return 1;
- }
- static int
- yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length, int allow_breaks)
- {
- yaml_string_t string;
- int spaces = 0;
- STRING_ASSIGN(string, value, length);
- if (!yaml_emitter_write_indicator(emitter, "\"", 1, 0, 0))
- return 0;
- while (string.pointer != string.end)
- {
- if (!IS_PRINTABLE(string) || (!emitter->unicode && !IS_ASCII(string))
- || IS_BOM(string) || IS_BREAK(string)
- || CHECK(string, '"') || CHECK(string, '\\'))
- {
- unsigned char octet;
- unsigned int width;
- unsigned int value;
- int k;
- octet = string.pointer[0];
- width = (octet & 0x80) == 0x00 ? 1 :
- (octet & 0xE0) == 0xC0 ? 2 :
- (octet & 0xF0) == 0xE0 ? 3 :
- (octet & 0xF8) == 0xF0 ? 4 : 0;
- value = (octet & 0x80) == 0x00 ? octet & 0x7F :
- (octet & 0xE0) == 0xC0 ? octet & 0x1F :
- (octet & 0xF0) == 0xE0 ? octet & 0x0F :
- (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
- for (k = 1; k < (int)width; k ++) {
- octet = string.pointer[k];
- value = (value << 6) + (octet & 0x3F);
- }
- string.pointer += width;
- if (!PUT(emitter, '\\')) return 0;
- switch (value)
- {
- case 0x00:
- if (!PUT(emitter, '0')) return 0;
- break;
- case 0x07:
- if (!PUT(emitter, 'a')) return 0;
- break;
- case 0x08:
- if (!PUT(emitter, 'b')) return 0;
- break;
- case 0x09:
- if (!PUT(emitter, 't')) return 0;
- break;
- case 0x0A:
- if (!PUT(emitter, 'n')) return 0;
- break;
- case 0x0B:
- if (!PUT(emitter, 'v')) return 0;
- break;
- case 0x0C:
- if (!PUT(emitter, 'f')) return 0;
- break;
- case 0x0D:
- if (!PUT(emitter, 'r')) return 0;
- break;
- case 0x1B:
- if (!PUT(emitter, 'e')) return 0;
- break;
- case 0x22:
- if (!PUT(emitter, '\"')) return 0;
- break;
- case 0x5C:
- if (!PUT(emitter, '\\')) return 0;
- break;
- case 0x85:
- if (!PUT(emitter, 'N')) return 0;
- break;
- case 0xA0:
- if (!PUT(emitter, '_')) return 0;
- break;
- case 0x2028:
- if (!PUT(emitter, 'L')) return 0;
- break;
- case 0x2029:
- if (!PUT(emitter, 'P')) return 0;
- break;
- default:
- if (value <= 0xFF) {
- if (!PUT(emitter, 'x')) return 0;
- width = 2;
- }
- else if (value <= 0xFFFF) {
- if (!PUT(emitter, 'u')) return 0;
- width = 4;
- }
- else {
- if (!PUT(emitter, 'U')) return 0;
- width = 8;
- }
- for (k = (width-1)*4; k >= 0; k -= 4) {
- int digit = (value >> k) & 0x0F;
- if (!PUT(emitter, digit + (digit < 10 ? '0' : 'A'-10)))
- return 0;
- }
- }
- spaces = 0;
- }
- else if (IS_SPACE(string))
- {
- if (allow_breaks && !spaces
- && emitter->column > emitter->best_width
- && string.pointer != string.start
- && string.pointer != string.end - 1) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- if (IS_SPACE_AT(string, 1)) {
- if (!PUT(emitter, '\\')) return 0;
- }
- MOVE(string);
- }
- else {
- if (!WRITE(emitter, string)) return 0;
- }
- spaces = 1;
- }
- else
- {
- if (!WRITE(emitter, string)) return 0;
- spaces = 0;
- }
- }
- if (!yaml_emitter_write_indicator(emitter, "\"", 0, 0, 0))
- return 0;
- emitter->whitespace = 0;
- emitter->indention = 0;
- return 1;
- }
- static int
- yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
- yaml_string_t string)
- {
- char indent_hint[2];
- const char *chomp_hint = NULL;
- if (IS_SPACE(string) || IS_BREAK(string))
- {
- indent_hint[0] = '0' + (char)emitter->best_indent;
- indent_hint[1] = '\0';
- if (!yaml_emitter_write_indicator(emitter, indent_hint, 0, 0, 0))
- return 0;
- }
- emitter->open_ended = 0;
- string.pointer = string.end;
- if (string.start == string.pointer)
- {
- chomp_hint = "-";
- }
- else
- {
- do {
- string.pointer --;
- } while ((*string.pointer & 0xC0) == 0x80);
- if (!IS_BREAK(string))
- {
- chomp_hint = "-";
- }
- else if (string.start == string.pointer)
- {
- chomp_hint = "+";
- emitter->open_ended = 2;
- }
- else
- {
- do {
- string.pointer --;
- } while ((*string.pointer & 0xC0) == 0x80);
- if (IS_BREAK(string))
- {
- chomp_hint = "+";
- emitter->open_ended = 2;
- }
- }
- }
- if (chomp_hint)
- {
- if (!yaml_emitter_write_indicator(emitter, chomp_hint, 0, 0, 0))
- return 0;
- }
- return 1;
- }
- static int
- yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length)
- {
- yaml_string_t string;
- int breaks = 1;
- STRING_ASSIGN(string, value, length);
- if (!yaml_emitter_write_indicator(emitter, "|", 1, 0, 0))
- return 0;
- if (!yaml_emitter_write_block_scalar_hints(emitter, string))
- return 0;
- if (!PUT_BREAK(emitter)) return 0;
- emitter->indention = 1;
- emitter->whitespace = 1;
- while (string.pointer != string.end)
- {
- if (IS_BREAK(string))
- {
- if (!WRITE_BREAK(emitter, string)) return 0;
- emitter->indention = 1;
- breaks = 1;
- }
- else
- {
- if (breaks) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- }
- if (!WRITE(emitter, string)) return 0;
- emitter->indention = 0;
- breaks = 0;
- }
- }
- return 1;
- }
- static int
- yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter,
- yaml_char_t *value, size_t length)
- {
- yaml_string_t string;
- int breaks = 1;
- int leading_spaces = 1;
- STRING_ASSIGN(string, value, length);
- if (!yaml_emitter_write_indicator(emitter, ">", 1, 0, 0))
- return 0;
- if (!yaml_emitter_write_block_scalar_hints(emitter, string))
- return 0;
- if (!PUT_BREAK(emitter)) return 0;
- emitter->indention = 1;
- emitter->whitespace = 1;
- while (string.pointer != string.end)
- {
- if (IS_BREAK(string))
- {
- if (!breaks && !leading_spaces && CHECK(string, '\n')) {
- int k = 0;
- while (IS_BREAK_AT(string, k)) {
- k += WIDTH_AT(string, k);
- }
- if (!IS_BLANKZ_AT(string, k)) {
- if (!PUT_BREAK(emitter)) return 0;
- }
- }
- if (!WRITE_BREAK(emitter, string)) return 0;
- emitter->indention = 1;
- breaks = 1;
- }
- else
- {
- if (breaks) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- leading_spaces = IS_BLANK(string);
- }
- if (!breaks && IS_SPACE(string) && !IS_SPACE_AT(string, 1)
- && emitter->column > emitter->best_width) {
- if (!yaml_emitter_write_indent(emitter)) return 0;
- MOVE(string);
- }
- else {
- if (!WRITE(emitter, string)) return 0;
- }
- emitter->indention = 0;
- breaks = 0;
- }
- }
- return 1;
- }
|