00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "config.h"
00038
00039 #include "Array.h"
00040 #include "util.h"
00041 #include "debug.h"
00042 #include "InternalErr.h"
00043 #include "escaping.h"
00044
00045
00046 #include <algorithm>
00047 #include <functional>
00048
00049
00050 using namespace std;
00051
00052 void
00053 Array::_duplicate(const Array &a)
00054 {
00055 _shape = a._shape;
00056 }
00057
00058
00059
00060
00061
00062
00063
00071 void
00072 Array::update_length(int)
00073 {
00074 int length = 1;
00075 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00076 length *= (*i).c_size > 0 ? (*i).c_size : 1;
00077 }
00078
00079 set_length(length);
00080 }
00081
00082
00083
00084
00102 Array::Array(const string &n, BaseType *v) : Vector(n, 0, dods_array_c)
00103 {
00104 add_var(v);
00105 }
00106
00108 Array::Array(const Array &rhs) : Vector(rhs)
00109 {
00110 _duplicate(rhs);
00111 }
00112
00114 Array::~Array()
00115 {
00116 DBG(cerr << "Entering ~Array (" << this << ")" << endl);
00117 DBG(cerr << "Exiting ~Array" << endl);
00118 }
00119
00120 BaseType *
00121 Array::ptr_duplicate()
00122 {
00123 return new Array(*this);
00124 }
00125
00126 Array &
00127 Array::operator=(const Array &rhs)
00128 {
00129 if (this == &rhs)
00130 return *this;
00131
00132 dynamic_cast<Vector &>(*this) = rhs;
00133
00134 _duplicate(rhs);
00135
00136 return *this;
00137 }
00138
00158 void
00159 Array::add_var(BaseType *v, Part)
00160 {
00161 if (v && v->type() == dods_array_c) {
00162 Array &a = dynamic_cast<Array&>(*v);
00163 Vector::add_var(a.var());
00164 Dim_iter i = a.dim_begin();
00165 Dim_iter i_end = a.dim_end();
00166 while (i != i_end) {
00167 append_dim(a.dimension_size(i), a.dimension_name(i));
00168 ++i;
00169 }
00170 }
00171 else {
00172 Vector::add_var(v);
00173 }
00174 }
00175
00187 void
00188 Array::append_dim(int size, string name)
00189 {
00190 dimension d;
00191
00192
00193 d.size = size;
00194 d.name = www2id(name);
00195
00196
00197 d.start = 0;
00198 d.stop = size - 1;
00199 d.stride = 1;
00200 d.c_size = size;
00201 d.selected = true;
00202
00203 _shape.push_back(d);
00204
00205 update_length(size);
00206 }
00207
00214 void
00215 Array::reset_constraint()
00216 {
00217 set_length(-1);
00218
00219 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
00220 (*i).start = 0;
00221 (*i).stop = (*i).size - 1;
00222 (*i).stride = 1;
00223 (*i).c_size = (*i).size;
00224
00225 (*i).selected = true;
00226
00227 update_length((*i).size);
00228 }
00229 }
00230
00231
00241 void
00242 Array::clear_constraint()
00243 {
00244 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
00245 (*i).start = 0;
00246 (*i).stop = 0;
00247 (*i).stride = 0;
00248 (*i).c_size = 0;
00249 (*i).selected = false;
00250 }
00251
00252 set_length(-1);
00253 }
00254
00255
00256
00257
00258
00259 static const char *array_sss = \
00260 "Invalid constraint parameters: At least one of the start, stride or stop \n\
00261 specified do not match the array variable.";
00262
00282 void
00283 Array::add_constraint(Dim_iter i, int start, int stride, int stop)
00284 {
00285 dimension &d = *i ;
00286
00287
00288
00289
00290
00291 if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0)
00292 throw Error(malformed_expr, array_sss);
00293
00294 if (((stop - start) / stride + 1) > d.size)
00295 throw Error(malformed_expr, array_sss);
00296
00297 d.start = start;
00298 d.stop = stop;
00299 d.stride = stride;
00300
00301 d.c_size = (stop - start) / stride + 1;
00302
00303 DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
00304
00305 d.selected = true;
00306
00307 update_length(d.c_size);
00308 }
00309
00311 Array::Dim_iter
00312 Array::dim_begin()
00313 {
00314 return _shape.begin() ;
00315 }
00316
00318 Array::Dim_iter
00319 Array::dim_end()
00320 {
00321 return _shape.end() ;
00322 }
00323
00333 unsigned int
00334 Array::dimensions(bool constrained)
00335 {
00336 unsigned int dim = 0;
00337 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00338 if (constrained) {
00339 if ((*i).selected)
00340 dim++;
00341 }
00342 else {
00343 dim++;
00344 }
00345 }
00346
00347 return dim;
00348 }
00349
00367 int
00368 Array::dimension_size(Dim_iter i, bool constrained)
00369 {
00370 int size = 0;
00371
00372 if (!_shape.empty())
00373 if (constrained) {
00374 if ((*i).selected)
00375 size = (*i).c_size;
00376 else
00377 size = 0;
00378 }
00379 else
00380 size = (*i).size;
00381
00382 return size;
00383 }
00384
00403 int
00404 Array::dimension_start(Dim_iter i, bool constrained)
00405 {
00406 int start = 0;
00407
00408 if (!_shape.empty())
00409 if (constrained) {
00410 if ((*i).selected)
00411 start = (*i).start;
00412 else
00413 start = 0;
00414 }
00415 else
00416 start = (*i).start;
00417
00418 return start;
00419 }
00420
00439 int
00440 Array::dimension_stop(Dim_iter i, bool constrained)
00441 {
00442 int stop = 0;
00443
00444 if (!_shape.empty())
00445 if (constrained) {
00446 if ((*i).selected)
00447 stop = (*i).stop;
00448 else
00449 stop = 0;
00450 }
00451 else
00452 stop = (*i).stop;
00453
00454 return stop;
00455 }
00456
00476 int
00477 Array::dimension_stride(Dim_iter i, bool constrained)
00478 {
00479 int stride = 0;
00480
00481 if (!_shape.empty())
00482 if (constrained) {
00483 if ((*i).selected)
00484 stride = (*i).stride;
00485 else
00486 stride = 0;
00487 }
00488 else
00489 stride = (*i).stride;
00490
00491 return stride;
00492 }
00493
00504 string
00505 Array::dimension_name(Dim_iter i)
00506 {
00507
00508
00509
00510
00511
00512 if (_shape.empty())
00513 throw InternalErr(__FILE__, __LINE__,
00514 "*This* array has no dimensions.");
00515 return (*i).name;
00516 }
00517
00535 void
00536 Array::print_decl(FILE *out, string space, bool print_semi,
00537 bool constraint_info, bool constrained)
00538 {
00539 if (constrained && !send_p())
00540 return;
00541
00542
00543 var()->print_decl(out, space, false, constraint_info, constrained);
00544
00545 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00546 if (constrained && !((*i).selected))
00547 continue;
00548 fprintf(out, "[") ;
00549 if ((*i).name != "") {
00550 fprintf(out, "%s = ", id2www((*i).name).c_str()) ;
00551 }
00552 if (constrained) {
00553 fprintf(out, "%d]", (*i).c_size) ;
00554 }
00555 else {
00556 fprintf(out, "%d]", (*i).size) ;
00557 }
00558 }
00559
00560 if (print_semi) {
00561 fprintf(out, ";\n") ;
00562 }
00563 }
00564
00565 void
00566 Array::print_xml(FILE *out, string space, bool constrained)
00567 {
00568 print_xml_core(out, space, constrained, "Array");
00569 }
00570
00571 void
00572 Array::print_as_map_xml(FILE *out, string space, bool constrained)
00573 {
00574 print_xml_core(out, space, constrained, "Map");
00575 }
00576
00577 class PrintArrayDim : public unary_function<Array::dimension&, void>
00578 {
00579 FILE *d_out;
00580 string d_space;
00581 bool d_constrained;
00582 public:
00583 PrintArrayDim(FILE *o, string s, bool c)
00584 : d_out(o), d_space(s), d_constrained(c)
00585 {}
00586
00587 void operator()(Array::dimension &d)
00588 {
00589 int size = d_constrained ? d.c_size : d.size;
00590 if (d.name.empty())
00591 fprintf(d_out, "%s<dimension size=\"%d\"/>\n", d_space.c_str(),
00592 size);
00593 else
00594 fprintf(d_out, "%s<dimension name=\"%s\" size=\"%d\"/>\n",
00595 d_space.c_str(), id2xml(d.name).c_str(), size);
00596 }
00597 };
00598
00599 void
00600 Array::print_xml_core(FILE *out, string space, bool constrained, string tag)
00601 {
00602 if (constrained && !send_p())
00603 return;
00604
00605 fprintf(out, "%s<%s", space.c_str(), tag.c_str());
00606 if (!name().empty())
00607 fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
00608 fprintf(out , ">\n");
00609
00610 get_attr_table().print_xml(out, space + " ", constrained);
00611
00612 BaseType *btp = var();
00613 string tmp_name = btp->name();
00614 btp->set_name("");
00615 btp->print_xml(out, space + " ", constrained);
00616 btp->set_name(tmp_name);
00617
00618 for_each(dim_begin(), dim_end(),
00619 PrintArrayDim(out, space + " ", constrained));
00620
00621 fprintf(out, "%s</%s>\n", space.c_str(), tag.c_str());
00622 }
00623
00634 unsigned int
00635 Array::print_array(FILE *out, unsigned int index, unsigned int dims,
00636 unsigned int shape[])
00637 {
00638 if (dims == 1) {
00639 fprintf(out, "{") ;
00640 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00641 var(index++)->print_val(out, "", false);
00642 fprintf(out, ", ") ;
00643 }
00644 var(index++)->print_val(out, "", false);
00645 fprintf(out, "}") ;
00646
00647 return index;
00648 }
00649 else {
00650 fprintf(out, "{") ;
00651
00652
00653
00654
00655
00656
00657 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00658 index = print_array(out, index, dims - 1, shape + 1);
00659 fprintf(out, ",") ;
00660 }
00661 index = print_array(out, index, dims - 1, shape + 1);
00662 fprintf(out, "}") ;
00663
00664 return index;
00665 }
00666 }
00667
00668 void
00669 Array::print_val(FILE *out, string space, bool print_decl_p)
00670 {
00671
00672
00673
00674
00675
00676
00677 if (print_decl_p) {
00678 print_decl(out, space, false, false, false);
00679 fprintf(out, " = ") ;
00680 }
00681
00682 unsigned int dims = dimensions(true);
00683 unsigned int *shape = new unsigned int[dims];
00684 unsigned int index = 0;
00685 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++)
00686 shape[index++] = dimension_size(i, true);
00687
00688 print_array(out, 0, dims, shape);
00689 delete [] shape; shape = 0;
00690
00691 if (print_decl_p) {
00692 fprintf(out, ";\n") ;
00693 }
00694 }
00695
00705 bool
00706 Array::check_semantics(string &msg, bool)
00707 {
00708 bool sem = BaseType::check_semantics(msg) && !_shape.empty();
00709
00710 if (!sem)
00711 msg = "An array variable must have dimensions";
00712
00713 return sem;
00714 }
00715
00724 void
00725 Array::dump(ostream &strm) const
00726 {
00727 strm << DapIndent::LMarg << "Array::dump - ("
00728 << (void *)this << ")" << endl ;
00729 DapIndent::Indent() ;
00730 Vector::dump(strm) ;
00731 strm << DapIndent::LMarg << "shape:" << endl ;
00732 DapIndent::Indent() ;
00733 Dim_citer i = _shape.begin() ;
00734 Dim_citer ie = _shape.end() ;
00735 unsigned int dim_num = 0 ;
00736 for (; i != ie; i++) {
00737 strm << DapIndent::LMarg << "dimension " << dim_num++ << ":" << endl ;
00738 DapIndent::Indent() ;
00739 strm << DapIndent::LMarg << "name: " << (*i).name << endl ;
00740 strm << DapIndent::LMarg << "size: " << (*i).size << endl ;
00741 strm << DapIndent::LMarg << "start: " << (*i).start << endl ;
00742 strm << DapIndent::LMarg << "stop: " << (*i).stop << endl ;
00743 strm << DapIndent::LMarg << "stride: " << (*i).stride << endl ;
00744 strm << DapIndent::LMarg << "constrained size: " << (*i).c_size
00745 << endl ;
00746 strm << DapIndent::LMarg << "selected: " << (*i).selected << endl ;
00747 DapIndent::UnIndent() ;
00748 }
00749 DapIndent::UnIndent() ;
00750 DapIndent::UnIndent() ;
00751 }
00752