1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 * Copyright (C) 2009-2015, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 *******************************************************************************
8 */
9 
10 #include "unicode/utypes.h"
11 
12 #if !UCONFIG_NO_FORMATTING
13 
14 #include "fphdlimp.h"
15 #include "uvectr32.h"
16 
17 U_NAMESPACE_BEGIN
18 
19 // utility FieldPositionHandler
20 // base class, null implementation
21 
~FieldPositionHandler()22 FieldPositionHandler::~FieldPositionHandler() {
23 }
24 
setShift(int32_t delta)25 void FieldPositionHandler::setShift(int32_t delta) {
26   fShift = delta;
27 }
28 
29 
30 // utility subclass FieldPositionOnlyHandler
31 
FieldPositionOnlyHandler(FieldPosition & _pos)32 FieldPositionOnlyHandler::FieldPositionOnlyHandler(FieldPosition& _pos)
33   : pos(_pos) {
34 }
35 
~FieldPositionOnlyHandler()36 FieldPositionOnlyHandler::~FieldPositionOnlyHandler() {
37 }
38 
39 void
addAttribute(int32_t id,int32_t start,int32_t limit)40 FieldPositionOnlyHandler::addAttribute(int32_t id, int32_t start, int32_t limit) {
41   if (pos.getField() == id && (!acceptFirstOnly || !seenFirst)) {
42     seenFirst = TRUE;
43     pos.setBeginIndex(start + fShift);
44     pos.setEndIndex(limit + fShift);
45   }
46 }
47 
48 void
shiftLast(int32_t delta)49 FieldPositionOnlyHandler::shiftLast(int32_t delta) {
50   if (delta != 0 && pos.getField() != FieldPosition::DONT_CARE && pos.getBeginIndex() != -1) {
51     pos.setBeginIndex(delta + pos.getBeginIndex());
52     pos.setEndIndex(delta + pos.getEndIndex());
53   }
54 }
55 
56 UBool
isRecording(void) const57 FieldPositionOnlyHandler::isRecording(void) const {
58   return pos.getField() != FieldPosition::DONT_CARE;
59 }
60 
setAcceptFirstOnly(UBool acceptFirstOnly)61 void FieldPositionOnlyHandler::setAcceptFirstOnly(UBool acceptFirstOnly) {
62   this->acceptFirstOnly = acceptFirstOnly;
63 }
64 
65 
66 // utility subclass FieldPositionIteratorHandler
67 
FieldPositionIteratorHandler(FieldPositionIterator * posIter,UErrorCode & _status)68 FieldPositionIteratorHandler::FieldPositionIteratorHandler(FieldPositionIterator* posIter,
69                                                            UErrorCode& _status)
70     : iter(posIter), vec(NULL), status(_status), fCategory(UFIELD_CATEGORY_UNDEFINED) {
71   if (iter && U_SUCCESS(status)) {
72     vec = new UVector32(status);
73   }
74 }
75 
FieldPositionIteratorHandler(UVector32 * vec,UErrorCode & status)76 FieldPositionIteratorHandler::FieldPositionIteratorHandler(
77     UVector32* vec,
78     UErrorCode& status)
79     : iter(nullptr), vec(vec), status(status), fCategory(UFIELD_CATEGORY_UNDEFINED) {
80 }
81 
~FieldPositionIteratorHandler()82 FieldPositionIteratorHandler::~FieldPositionIteratorHandler() {
83   // setData adopts the vec regardless of status, so it's safe to null it
84   if (iter) {
85     iter->setData(vec, status);
86   }
87   // if iter is null, we never allocated vec, so no need to free it
88   vec = NULL;
89 }
90 
91 void
addAttribute(int32_t id,int32_t start,int32_t limit)92 FieldPositionIteratorHandler::addAttribute(int32_t id, int32_t start, int32_t limit) {
93   if (vec && U_SUCCESS(status) && start < limit) {
94     int32_t size = vec->size();
95     vec->addElement(fCategory, status);
96     vec->addElement(id, status);
97     vec->addElement(start + fShift, status);
98     vec->addElement(limit + fShift, status);
99     if (!U_SUCCESS(status)) {
100       vec->setSize(size);
101     }
102   }
103 }
104 
105 void
shiftLast(int32_t delta)106 FieldPositionIteratorHandler::shiftLast(int32_t delta) {
107   if (U_SUCCESS(status) && delta != 0) {
108     int32_t i = vec->size();
109     if (i > 0) {
110       --i;
111       vec->setElementAt(delta + vec->elementAti(i), i);
112       --i;
113       vec->setElementAt(delta + vec->elementAti(i), i);
114     }
115   }
116 }
117 
118 UBool
isRecording(void) const119 FieldPositionIteratorHandler::isRecording(void) const {
120   return U_SUCCESS(status);
121 }
122 
123 U_NAMESPACE_END
124 
125 #endif /* !UCONFIG_NO_FORMATTING */
126